Everything is now OpenRA, not OpenRa
This commit is contained in:
26
Makefile
26
Makefile
@@ -5,41 +5,41 @@ PROGRAMS =fileformats gl game ra cnc aftermath server seqed
|
|||||||
|
|
||||||
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
||||||
|
|
||||||
fileformats_SRCS = $(shell find OpenRa.FileFormats/ -iname '*.cs')
|
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
|
||||||
fileformats_TARGET = OpenRa.FileFormats.dll
|
fileformats_TARGET = OpenRA.FileFormats.dll
|
||||||
fileformats_KIND = library
|
fileformats_KIND = library
|
||||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll
|
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll
|
||||||
|
|
||||||
gl_SRCS = $(shell find OpenRa.Gl/ -iname '*.cs')
|
gl_SRCS = $(shell find OpenRA.Gl/ -iname '*.cs')
|
||||||
gl_TARGET = OpenRa.Gl.dll
|
gl_TARGET = OpenRA.Gl.dll
|
||||||
gl_KIND = library
|
gl_KIND = library
|
||||||
gl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
gl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||||
gl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
gl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||||
$(gl_DEPS) $(game_TARGET)
|
$(gl_DEPS) $(game_TARGET)
|
||||||
|
|
||||||
game_SRCS = $(shell find OpenRa.Game/ -iname '*.cs')
|
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
|
||||||
game_TARGET = OpenRa.Game.exe
|
game_TARGET = OpenRA.Game.exe
|
||||||
game_KIND = winexe
|
game_KIND = winexe
|
||||||
game_DEPS = $(fileformats_TARGET)
|
game_DEPS = $(fileformats_TARGET)
|
||||||
game_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(game_DEPS) \
|
game_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(game_DEPS) \
|
||||||
thirdparty/Tao/Tao.OpenAl.dll thirdparty/Tao/Tao.FreeType.dll
|
thirdparty/Tao/Tao.OpenAl.dll thirdparty/Tao/Tao.FreeType.dll
|
||||||
game_FLAGS = -win32icon:OpenRa.Game/OpenRa.ico
|
game_FLAGS = -win32icon:OpenRA.Game/OpenRA.ico
|
||||||
|
|
||||||
ra_SRCS = $(shell find OpenRa.Mods.RA/ -iname '*.cs')
|
ra_SRCS = $(shell find OpenRA.Mods.RA/ -iname '*.cs')
|
||||||
ra_TARGET = mods/ra/OpenRa.Mods.RA.dll
|
ra_TARGET = mods/ra/OpenRA.Mods.RA.dll
|
||||||
ra_KIND = library
|
ra_KIND = library
|
||||||
ra_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
ra_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||||
ra_LIBS = $(COMMON_LIBS) $(ra_DEPS)
|
ra_LIBS = $(COMMON_LIBS) $(ra_DEPS)
|
||||||
|
|
||||||
cnc_SRCS = $(shell find OpenRa.Mods.Cnc/ -iname '*.cs')
|
cnc_SRCS = $(shell find OpenRA.Mods.Cnc/ -iname '*.cs')
|
||||||
cnc_TARGET = mods/cnc/OpenRa.Mods.Cnc.dll
|
cnc_TARGET = mods/cnc/OpenRA.Mods.Cnc.dll
|
||||||
cnc_KIND = library
|
cnc_KIND = library
|
||||||
cnc_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
cnc_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||||
cnc_LIBS = $(COMMON_LIBS) $(cnc_DEPS)
|
cnc_LIBS = $(COMMON_LIBS) $(cnc_DEPS)
|
||||||
|
|
||||||
aftermath_SRCS = $(shell find OpenRa.Mods.Aftermath/ -iname '*.cs')
|
aftermath_SRCS = $(shell find OpenRA.Mods.Aftermath/ -iname '*.cs')
|
||||||
aftermath_TARGET = mods/aftermath/OpenRa.Mods.Aftermath.dll
|
aftermath_TARGET = mods/aftermath/OpenRA.Mods.Aftermath.dll
|
||||||
aftermath_KIND = library
|
aftermath_KIND = library
|
||||||
aftermath_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
aftermath_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||||
aftermath_LIBS = $(COMMON_LIBS) $(aftermath_DEPS)
|
aftermath_LIBS = $(COMMON_LIBS) $(aftermath_DEPS)
|
||||||
|
|||||||
125
OpenRA.FileFormats/AudLoader.cs
Normal file
125
OpenRA.FileFormats/AudLoader.cs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
enum SoundFlags
|
||||||
|
{
|
||||||
|
Stereo = 0x1,
|
||||||
|
_16Bit = 0x2,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SoundFormat
|
||||||
|
{
|
||||||
|
WestwoodCompressed = 1,
|
||||||
|
ImaAdpcm = 99,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Chunk
|
||||||
|
{
|
||||||
|
public int CompressedSize;
|
||||||
|
public int OutputSize;
|
||||||
|
|
||||||
|
public static Chunk Read(BinaryReader r)
|
||||||
|
{
|
||||||
|
Chunk c;
|
||||||
|
c.CompressedSize = r.ReadUInt16();
|
||||||
|
c.OutputSize = r.ReadUInt16();
|
||||||
|
if (0xdeaf != r.ReadUInt32())
|
||||||
|
throw new InvalidDataException("Chunk header is bogus");
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AudLoader
|
||||||
|
{
|
||||||
|
static int[] IndexAdjust = { -1, -1, -1, -1, 2, 4, 6, 8 };
|
||||||
|
static int[] StepTable = {
|
||||||
|
7, 8, 9, 10, 11, 12, 13, 14, 16,
|
||||||
|
17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||||
|
41, 45, 50, 55, 60, 66, 73, 80, 88,
|
||||||
|
97, 107, 118, 130, 143, 157, 173, 190, 209,
|
||||||
|
230, 253, 279, 307, 337, 371, 408, 449, 494,
|
||||||
|
544, 598, 658, 724, 796, 876, 963, 1060, 1166,
|
||||||
|
1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749,
|
||||||
|
3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
|
||||||
|
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289,
|
||||||
|
16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 };
|
||||||
|
|
||||||
|
static short DecodeSample(byte b, ref int index, ref int current)
|
||||||
|
{
|
||||||
|
var sb = (b & 8) != 0;
|
||||||
|
b &= 7;
|
||||||
|
|
||||||
|
var delta = (StepTable[index] * b) / 4 + StepTable[index] / 8;
|
||||||
|
if (sb) delta = -delta;
|
||||||
|
|
||||||
|
current += delta;
|
||||||
|
if (current > short.MaxValue) current = short.MaxValue;
|
||||||
|
if (current < short.MinValue) current = short.MinValue;
|
||||||
|
|
||||||
|
index += IndexAdjust[b];
|
||||||
|
if (index < 0) index = 0;
|
||||||
|
if (index > 88) index = 88;
|
||||||
|
|
||||||
|
return (short)current;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] LoadSound(Stream s)
|
||||||
|
{
|
||||||
|
var br = new BinaryReader(s);
|
||||||
|
/*var sampleRate =*/ br.ReadUInt16();
|
||||||
|
var dataSize = br.ReadInt32();
|
||||||
|
var outputSize = br.ReadInt32();
|
||||||
|
/*var flags = (SoundFlags)*/ br.ReadByte();
|
||||||
|
/*var format = (SoundFormat)*/ br.ReadByte();
|
||||||
|
|
||||||
|
var output = new byte[outputSize];
|
||||||
|
var offset = 0;
|
||||||
|
var index = 0;
|
||||||
|
var currentSample = 0;
|
||||||
|
|
||||||
|
while (dataSize > 0)
|
||||||
|
{
|
||||||
|
var chunk = Chunk.Read(br);
|
||||||
|
for (int n = 0; n < chunk.CompressedSize; n++)
|
||||||
|
{
|
||||||
|
var b = br.ReadByte();
|
||||||
|
|
||||||
|
var t = DecodeSample(b, ref index, ref currentSample);
|
||||||
|
output[offset++] = (byte)t;
|
||||||
|
output[offset++] = (byte)(t >> 8);
|
||||||
|
|
||||||
|
t = DecodeSample((byte)(b >> 4), ref index, ref currentSample);
|
||||||
|
output[offset++] = (byte)t;
|
||||||
|
output[offset++] = (byte)(t >> 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataSize -= 8 + chunk.CompressedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
416
OpenRA.FileFormats/Blowfish.cs
Normal file
416
OpenRA.FileFormats/Blowfish.cs
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
class Blowfish
|
||||||
|
{
|
||||||
|
public Blowfish(byte[] key)
|
||||||
|
{
|
||||||
|
for (int i = 0, j = 0; i < 18; ++i)
|
||||||
|
{
|
||||||
|
uint a = key[j++ % key.Length];
|
||||||
|
uint b = key[j++ % key.Length];
|
||||||
|
uint c = key[j++ % key.Length];
|
||||||
|
uint d = key[j++ % key.Length];
|
||||||
|
|
||||||
|
m_p[i] ^= a << 24 | b << 16 | c << 8 | d;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint l = 0, r = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 18; )
|
||||||
|
{
|
||||||
|
Encrypt(ref l, ref r);
|
||||||
|
m_p[i++] = l;
|
||||||
|
m_p[i++] = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
for (int j = 0; j < 256; )
|
||||||
|
{
|
||||||
|
Encrypt(ref l, ref r);
|
||||||
|
m_s[i, j++] = l;
|
||||||
|
m_s[i, j++] = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint[] Encrypt(uint[] data) { return RunCipher(data, Encrypt); }
|
||||||
|
public uint[] Decrypt(uint[] data) { return RunCipher(data, Decrypt); }
|
||||||
|
|
||||||
|
delegate void CipherFunc( ref uint a, ref uint b );
|
||||||
|
|
||||||
|
uint[] RunCipher(uint[] data, CipherFunc f)
|
||||||
|
{
|
||||||
|
uint[] result = new uint[data.Length];
|
||||||
|
|
||||||
|
int size = data.Length / 2;
|
||||||
|
int i = 0;
|
||||||
|
while (size-- > 0)
|
||||||
|
{
|
||||||
|
uint a = SwapBytes(data[i]);
|
||||||
|
uint b = SwapBytes(data[i+1]);
|
||||||
|
|
||||||
|
f(ref a, ref b);
|
||||||
|
|
||||||
|
result[i++] = SwapBytes(a);
|
||||||
|
result[i++] = SwapBytes(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Encrypt(ref uint a, ref uint b)
|
||||||
|
{
|
||||||
|
uint _a = a, _b = b;
|
||||||
|
_a ^= m_p[0];
|
||||||
|
|
||||||
|
bool x = false;
|
||||||
|
for( int i = 1; i <= 16; i++, x ^= true)
|
||||||
|
{
|
||||||
|
if (x)
|
||||||
|
Round(ref _a, _b, i);
|
||||||
|
else
|
||||||
|
Round(ref _b, _a, i);
|
||||||
|
}
|
||||||
|
_b ^= m_p[17];
|
||||||
|
|
||||||
|
a = _b;
|
||||||
|
b = _a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decrypt(ref uint a, ref uint b)
|
||||||
|
{
|
||||||
|
uint _a = a, _b = b;
|
||||||
|
_a ^= m_p[17];
|
||||||
|
|
||||||
|
bool x = false;
|
||||||
|
for (int i = 16; i >= 1; i--, x ^= true)
|
||||||
|
{
|
||||||
|
if (x)
|
||||||
|
Round(ref _a, _b, i);
|
||||||
|
else
|
||||||
|
Round(ref _b, _a, i);
|
||||||
|
}
|
||||||
|
_b ^= m_p[0];
|
||||||
|
|
||||||
|
a = _b;
|
||||||
|
b = _a;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint S(uint x, int i)
|
||||||
|
{
|
||||||
|
return m_s[i, (x >> ((3 - i) << 3)) & 0xff];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint bf_f(uint x)
|
||||||
|
{
|
||||||
|
return ((S(x, 0) + S(x, 1)) ^ S(x, 2)) + S(x, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Round(ref uint a, uint b, int n)
|
||||||
|
{
|
||||||
|
a ^= bf_f(b) ^ m_p[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint SwapBytes(uint i)
|
||||||
|
{
|
||||||
|
i = (i << 16) | (i >> 16);
|
||||||
|
i = ((i << 8) & 0xff00ff00) | ((i >> 8) & 0x00ff00ff);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint[] m_p = new uint[] {
|
||||||
|
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
||||||
|
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
||||||
|
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||||
|
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
||||||
|
0x9216d5d9, 0x8979fb1b
|
||||||
|
};
|
||||||
|
|
||||||
|
uint[,] m_s = new uint[,] {
|
||||||
|
{
|
||||||
|
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
||||||
|
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||||
|
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||||
|
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||||
|
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
||||||
|
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||||
|
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
||||||
|
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||||
|
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||||
|
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||||
|
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
||||||
|
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||||
|
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
||||||
|
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||||
|
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||||
|
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||||
|
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
||||||
|
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||||
|
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
||||||
|
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||||
|
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||||
|
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||||
|
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
||||||
|
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||||
|
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
||||||
|
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||||
|
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||||
|
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||||
|
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
||||||
|
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||||
|
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
||||||
|
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||||
|
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||||
|
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||||
|
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
||||||
|
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||||
|
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
||||||
|
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||||
|
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||||
|
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||||
|
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
||||||
|
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||||
|
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
||||||
|
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||||
|
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||||
|
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||||
|
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
||||||
|
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||||
|
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
||||||
|
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||||
|
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||||
|
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||||
|
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
||||||
|
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||||
|
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
||||||
|
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||||
|
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||||
|
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||||
|
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
||||||
|
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||||
|
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
||||||
|
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||||
|
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||||
|
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
||||||
|
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||||
|
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||||
|
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||||
|
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
||||||
|
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||||
|
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
||||||
|
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||||
|
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||||
|
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||||
|
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
||||||
|
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||||
|
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
||||||
|
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||||
|
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||||
|
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||||
|
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
||||||
|
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||||
|
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
||||||
|
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||||
|
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||||
|
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||||
|
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
||||||
|
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||||
|
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
||||||
|
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||||
|
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||||
|
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||||
|
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
||||||
|
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||||
|
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
||||||
|
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||||
|
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||||
|
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||||
|
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
||||||
|
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||||
|
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
||||||
|
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||||
|
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||||
|
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||||
|
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
||||||
|
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||||
|
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
||||||
|
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||||
|
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||||
|
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||||
|
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
||||||
|
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||||
|
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
||||||
|
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||||
|
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||||
|
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||||
|
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
||||||
|
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||||
|
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
||||||
|
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||||
|
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||||
|
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||||
|
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
||||||
|
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||||
|
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
||||||
|
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||||
|
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||||
|
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
||||||
|
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||||
|
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||||
|
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||||
|
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
||||||
|
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||||
|
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
||||||
|
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||||
|
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||||
|
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||||
|
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
||||||
|
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||||
|
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
||||||
|
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||||
|
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||||
|
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||||
|
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
||||||
|
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||||
|
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
||||||
|
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||||
|
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||||
|
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||||
|
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
||||||
|
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||||
|
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
||||||
|
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||||
|
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||||
|
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||||
|
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
||||||
|
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||||
|
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
||||||
|
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||||
|
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||||
|
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||||
|
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
||||||
|
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||||
|
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
||||||
|
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||||
|
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||||
|
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||||
|
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
||||||
|
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||||
|
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
||||||
|
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||||
|
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||||
|
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||||
|
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
||||||
|
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||||
|
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
||||||
|
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||||
|
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||||
|
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||||
|
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
||||||
|
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||||
|
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
||||||
|
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||||
|
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||||
|
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||||
|
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
||||||
|
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||||
|
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
||||||
|
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||||
|
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||||
|
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
||||||
|
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||||
|
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||||
|
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||||
|
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
||||||
|
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||||
|
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
||||||
|
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||||
|
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||||
|
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||||
|
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
||||||
|
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||||
|
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
||||||
|
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||||
|
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||||
|
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||||
|
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
||||||
|
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||||
|
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
||||||
|
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||||
|
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||||
|
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||||
|
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
||||||
|
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||||
|
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
||||||
|
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||||
|
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||||
|
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||||
|
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
||||||
|
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||||
|
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
||||||
|
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||||
|
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||||
|
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||||
|
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
||||||
|
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||||
|
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
||||||
|
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||||
|
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||||
|
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||||
|
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
||||||
|
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||||
|
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
||||||
|
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||||
|
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||||
|
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||||
|
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
||||||
|
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||||
|
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
||||||
|
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||||
|
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||||
|
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||||
|
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
||||||
|
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||||
|
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
||||||
|
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||||
|
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||||
|
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||||
|
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
||||||
|
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||||
|
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
||||||
|
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||||
|
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||||
|
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
538
OpenRA.FileFormats/BlowfishKeyProvider.cs
Normal file
538
OpenRA.FileFormats/BlowfishKeyProvider.cs
Normal file
@@ -0,0 +1,538 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
/* possibly the fugliest C# i've ever seen. */
|
||||||
|
|
||||||
|
class BlowfishKeyProvider
|
||||||
|
{
|
||||||
|
const string pubkeyStr = "AihRvNoIbTn85FZRYNZRcT+i6KpU+maCsEqr3Q5q+LDB5tH7Tz2qQ38V";
|
||||||
|
|
||||||
|
static sbyte[] char2num = {
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||||
|
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
|
||||||
|
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||||
|
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||||||
|
|
||||||
|
class PublicKey
|
||||||
|
{
|
||||||
|
public uint[] key1 = new uint[64];
|
||||||
|
public uint[] key2 = new uint[64];
|
||||||
|
public uint len;
|
||||||
|
}
|
||||||
|
PublicKey pubkey = new PublicKey();
|
||||||
|
|
||||||
|
uint[] glob1 = new uint[64];
|
||||||
|
uint glob1_bitlen, glob1_len_x2;
|
||||||
|
uint[] glob2 = new uint[130];
|
||||||
|
uint[] glob1_hi = new uint[4];
|
||||||
|
uint[] glob1_hi_inv = new uint[4];
|
||||||
|
uint glob1_hi_bitlen;
|
||||||
|
uint glob1_hi_inv_lo, glob1_hi_inv_hi;
|
||||||
|
|
||||||
|
void init_bignum(uint[] n, uint val, uint len)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < len; i++) n[i] = 0;
|
||||||
|
n[0] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_key_to_big(uint[] n, byte[] key, uint klen, uint blen)
|
||||||
|
{
|
||||||
|
byte sign;
|
||||||
|
|
||||||
|
if ((key[0] & 0x80) != 0) sign = 0xff;
|
||||||
|
else sign = 0;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (uint* _pn = &n[0])
|
||||||
|
{
|
||||||
|
byte* pn = (byte*)_pn;
|
||||||
|
uint i = blen * 4;
|
||||||
|
for (; i > klen; i--) pn[i - 1] = (byte)sign;
|
||||||
|
for (; i > 0; i--) pn[i - 1] = key[klen - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void key_to_bignum(uint[] n, byte[] key, uint len)
|
||||||
|
{
|
||||||
|
uint keylen;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
if (key[j] != 2) return;
|
||||||
|
j++;
|
||||||
|
|
||||||
|
if ((key[j] & 0x80) != 0)
|
||||||
|
{
|
||||||
|
keylen = 0;
|
||||||
|
for (i = 0; i < (key[j] & 0x7f); i++) keylen = (keylen << 8) | key[j + i + 1];
|
||||||
|
j += (key[j] & 0x7f) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keylen = key[j];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
if (keylen <= len * 4)
|
||||||
|
move_key_to_big(n, key.Skip(j).ToArray(), keylen, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint len_bignum(uint[] n, uint len)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
i = len - 1;
|
||||||
|
while ((i >= 0) && (n[i] == 0)) i--;
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint bitlen_bignum(uint[] n, uint len)
|
||||||
|
{
|
||||||
|
uint ddlen, bitlen, mask;
|
||||||
|
ddlen = len_bignum(n, len);
|
||||||
|
if (ddlen == 0) return 0;
|
||||||
|
bitlen = ddlen * 32;
|
||||||
|
mask = 0x80000000;
|
||||||
|
while ((mask & n[ddlen - 1]) == 0)
|
||||||
|
{
|
||||||
|
mask >>= 1;
|
||||||
|
bitlen--;
|
||||||
|
}
|
||||||
|
return bitlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_pubkey()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
uint i2, tmp;
|
||||||
|
byte[] keytmp = new byte[256];
|
||||||
|
|
||||||
|
init_bignum(pubkey.key2, 0x10001, 64);
|
||||||
|
|
||||||
|
i2 = 0;
|
||||||
|
while (i < pubkeyStr.Length)
|
||||||
|
{
|
||||||
|
tmp = (uint)char2num[pubkeyStr[i++]];
|
||||||
|
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
|
||||||
|
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
|
||||||
|
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
|
||||||
|
keytmp[i2++] = (byte)((tmp >> 16) & 0xff);
|
||||||
|
keytmp[i2++] = (byte)((tmp >> 8) & 0xff);
|
||||||
|
keytmp[i2++] = (byte)(tmp & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
key_to_bignum(pubkey.key1, keytmp, 64);
|
||||||
|
pubkey.len = bitlen_bignum(pubkey.key1, 64) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint len_predata()
|
||||||
|
{
|
||||||
|
uint a = (pubkey.len - 1) / 8;
|
||||||
|
return (55 / a + 1) * (a + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmp_bignum(uint[] n1, uint[] n2, uint len)
|
||||||
|
{
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
--len;
|
||||||
|
if (n1[len] < n2[len]) return -1;
|
||||||
|
if (n1[len] > n2[len]) return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mov_bignum(uint[] dest, uint[] src, uint len)
|
||||||
|
{
|
||||||
|
Array.Copy(src, dest, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void shr_bignum(uint[] n, int bits, int len)
|
||||||
|
{
|
||||||
|
int i; int i2 = bits / 32;
|
||||||
|
|
||||||
|
if (i2 > 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < len - i2; i++) n[i] = n[i + i2];
|
||||||
|
for (; i < len; i++) n[i] = 0;
|
||||||
|
bits = bits % 32;
|
||||||
|
}
|
||||||
|
if (bits == 0) return;
|
||||||
|
for (i = 0; i < len - 1; i++) n[i] = (n[i] >> bits) | (n[i + 1] << (32 -
|
||||||
|
bits));
|
||||||
|
n[i] = n[i] >> bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shl_bignum(uint[] n, int bits, int len)
|
||||||
|
{
|
||||||
|
int i, i2;
|
||||||
|
|
||||||
|
i2 = bits / 32;
|
||||||
|
if (i2 > 0)
|
||||||
|
{
|
||||||
|
for (i = len - 1; i > i2; i--) n[i] = n[i - i2];
|
||||||
|
for (; i > 0; i--) n[i] = 0;
|
||||||
|
bits = bits % 32;
|
||||||
|
}
|
||||||
|
if (bits == 0) return;
|
||||||
|
for (i = len - 1; i > 0; i--) n[i] = (n[i] << bits) | (n[i - 1] >> (32 -
|
||||||
|
bits));
|
||||||
|
n[0] <<= bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint sub_bignum(uint[] dest, uint[] src1, uint[] src2, uint carry, int len)
|
||||||
|
{
|
||||||
|
uint i1, i2;
|
||||||
|
|
||||||
|
len += len;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (uint* _ps1 = &src1[0])
|
||||||
|
fixed (uint* _ps2 = &src2[0])
|
||||||
|
fixed (uint* _pd = &dest[0])
|
||||||
|
{
|
||||||
|
ushort* ps1 = (ushort*)_ps1;
|
||||||
|
ushort* ps2 = (ushort*)_ps2;
|
||||||
|
ushort* pd = (ushort*)_pd;
|
||||||
|
|
||||||
|
while (--len != -1)
|
||||||
|
{
|
||||||
|
i1 = *ps1++;
|
||||||
|
i2 = *ps2++;
|
||||||
|
*pd++ = (ushort)(i1 - i2 - carry);
|
||||||
|
if (((i1 - i2 - carry) & 0x10000) != 0) carry = 1; else carry = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe uint sub_bignum(uint* dest, uint* src1, uint* src2, uint carry, int len)
|
||||||
|
{
|
||||||
|
uint i1, i2;
|
||||||
|
|
||||||
|
len += len;
|
||||||
|
|
||||||
|
ushort* ps1 = (ushort*)src1;
|
||||||
|
ushort* ps2 = (ushort*)src2;
|
||||||
|
ushort* pd = (ushort*)dest;
|
||||||
|
|
||||||
|
while (--len != -1)
|
||||||
|
{
|
||||||
|
i1 = *ps1++;
|
||||||
|
i2 = *ps2++;
|
||||||
|
*pd++ = (ushort)(i1 - i2 - carry);
|
||||||
|
if (((i1 - i2 - carry) & 0x10000) != 0) carry = 1; else carry = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
return carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void inv_bignum(uint[] n1, uint[] n2, uint len)
|
||||||
|
{
|
||||||
|
uint[] n_tmp = new uint[64];
|
||||||
|
uint n2_bytelen, bit;
|
||||||
|
int n2_bitlen;
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
init_bignum(n_tmp, 0, len);
|
||||||
|
init_bignum(n1, 0, len);
|
||||||
|
n2_bitlen = (int)bitlen_bignum(n2, len);
|
||||||
|
bit = ((uint)1) << (n2_bitlen % 32);
|
||||||
|
j = ((n2_bitlen + 32) / 32) - 1;
|
||||||
|
n2_bytelen = (uint)((n2_bitlen - 1) / 32) * 4;
|
||||||
|
n_tmp[n2_bytelen / 4] |= ((uint)1) << ((n2_bitlen - 1) & 0x1f);
|
||||||
|
|
||||||
|
while (n2_bitlen > 0)
|
||||||
|
{
|
||||||
|
n2_bitlen--;
|
||||||
|
shl_bignum(n_tmp, 1, (int)len);
|
||||||
|
if (cmp_bignum(n_tmp, n2, len) != -1)
|
||||||
|
{
|
||||||
|
sub_bignum(n_tmp, n_tmp, n2, 0, (int)len);
|
||||||
|
n1[j] |= bit;
|
||||||
|
}
|
||||||
|
bit >>= 1;
|
||||||
|
if (bit == 0)
|
||||||
|
{
|
||||||
|
j--;
|
||||||
|
bit = 0x80000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
init_bignum(n_tmp, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inc_bignum(uint[] n, uint len)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while ((++n[i] == 0) && (--len > 0)) i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_two_dw(uint[] n, uint len)
|
||||||
|
{
|
||||||
|
mov_bignum(glob1, n, len);
|
||||||
|
glob1_bitlen = bitlen_bignum(glob1, len);
|
||||||
|
glob1_len_x2 = (glob1_bitlen + 15) / 16;
|
||||||
|
mov_bignum(glob1_hi, glob1.Skip((int)len_bignum(glob1, len) - 2).ToArray(), 2);
|
||||||
|
glob1_hi_bitlen = bitlen_bignum(glob1_hi, 2) - 32;
|
||||||
|
shr_bignum(glob1_hi, (int)glob1_hi_bitlen, 2);
|
||||||
|
inv_bignum(glob1_hi_inv, glob1_hi, 2);
|
||||||
|
shr_bignum(glob1_hi_inv, 1, 2);
|
||||||
|
glob1_hi_bitlen = (glob1_hi_bitlen + 15) % 16 + 1;
|
||||||
|
inc_bignum(glob1_hi_inv, 2);
|
||||||
|
if (bitlen_bignum(glob1_hi_inv, 2) > 32)
|
||||||
|
{
|
||||||
|
shr_bignum(glob1_hi_inv, 1, 2);
|
||||||
|
glob1_hi_bitlen--;
|
||||||
|
}
|
||||||
|
glob1_hi_inv_lo = (ushort)glob1_hi_inv[0];
|
||||||
|
glob1_hi_inv_hi = (ushort)(glob1_hi_inv[0] >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe void mul_bignum_word(ushort *pn1, uint[] n2, uint mul, uint len)
|
||||||
|
{
|
||||||
|
uint i, tmp;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (uint* _pn2 = &n2[0])
|
||||||
|
{
|
||||||
|
ushort* pn2 = (ushort*)_pn2;
|
||||||
|
|
||||||
|
tmp = 0;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
tmp = mul * (*pn2) + (*pn1) + tmp;
|
||||||
|
*pn1 = (ushort)tmp;
|
||||||
|
pn1++;
|
||||||
|
pn2++;
|
||||||
|
tmp >>= 16;
|
||||||
|
}
|
||||||
|
*pn1 += (ushort)tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mul_bignum(uint[] dest, uint[] src1, uint[] src2, uint len)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed( uint * _psrc2 = &src2[0] )
|
||||||
|
fixed(uint* _pdest = &dest[0])
|
||||||
|
{
|
||||||
|
ushort* psrc2 = (ushort*)_psrc2;
|
||||||
|
ushort* pdest = (ushort*)_pdest;
|
||||||
|
|
||||||
|
init_bignum(dest, 0, len * 2);
|
||||||
|
for (i = 0; i < len * 2; i++)
|
||||||
|
mul_bignum_word(pdest++, src1, *psrc2++, len * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void not_bignum(uint[] n, uint len)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
for (i = 0; i < len; i++) n[i] = ~n[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void neg_bignum(uint[] n, uint len)
|
||||||
|
{
|
||||||
|
not_bignum(n, len);
|
||||||
|
inc_bignum(n, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe uint get_mulword(uint* n)
|
||||||
|
{
|
||||||
|
ushort* wn = (ushort*)n;
|
||||||
|
uint i = (uint)((((((((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_lo + 0x10000) >> 1)
|
||||||
|
+ (((*(wn - 2) ^ 0xffff) * glob1_hi_inv_hi + glob1_hi_inv_hi) >> 1) + 1)
|
||||||
|
>> 16) + ((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_hi) >> 1) +
|
||||||
|
(((*wn ^ 0xffff) * glob1_hi_inv_lo) >> 1) + 1) >> 14) + glob1_hi_inv_hi
|
||||||
|
* (*wn ^ 0xffff) * 2) >> (int)glob1_hi_bitlen);
|
||||||
|
if (i > 0xffff) i = 0xffff;
|
||||||
|
return i & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dec_bignum(uint[] n, uint len)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while ((--n[i] == 0xffffffff) && (--len > 0))
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calc_a_bignum(uint[] n1, uint[] n2, uint[] n3, uint len)
|
||||||
|
{
|
||||||
|
uint g2_len_x2, len_diff;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed( uint* g1 = &glob1[0])
|
||||||
|
fixed (uint* g2 = &glob2[0])
|
||||||
|
{
|
||||||
|
mul_bignum(glob2, n2, n3, len);
|
||||||
|
glob2[len * 2] = 0;
|
||||||
|
g2_len_x2 = len_bignum(glob2, len * 2 + 1) * 2;
|
||||||
|
if (g2_len_x2 >= glob1_len_x2)
|
||||||
|
{
|
||||||
|
inc_bignum(glob2, len * 2 + 1);
|
||||||
|
neg_bignum(glob2, len * 2 + 1);
|
||||||
|
len_diff = g2_len_x2 + 1 - glob1_len_x2;
|
||||||
|
ushort* esi = ((ushort*)g2) + (1 + g2_len_x2 - glob1_len_x2);
|
||||||
|
ushort* edi = ((ushort*)g2) + (g2_len_x2 + 1);
|
||||||
|
for (; len_diff != 0; len_diff--)
|
||||||
|
{
|
||||||
|
edi--;
|
||||||
|
uint tmp = get_mulword((uint*)edi);
|
||||||
|
esi--;
|
||||||
|
if (tmp > 0)
|
||||||
|
{
|
||||||
|
mul_bignum_word(esi, glob1, tmp, 2 * len);
|
||||||
|
if ((*edi & 0x8000) == 0)
|
||||||
|
{
|
||||||
|
if (0 != sub_bignum((uint*)esi, (uint*)esi, g1, 0, (int)len)) (*edi)--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
neg_bignum(glob2, len);
|
||||||
|
dec_bignum(glob2, len);
|
||||||
|
}
|
||||||
|
mov_bignum(n1, glob2, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_tmp_vars(uint len)
|
||||||
|
{
|
||||||
|
init_bignum(glob1, 0, len);
|
||||||
|
init_bignum(glob2, 0, len);
|
||||||
|
init_bignum(glob1_hi_inv, 0, 4);
|
||||||
|
init_bignum(glob1_hi, 0, 4);
|
||||||
|
glob1_bitlen = 0;
|
||||||
|
glob1_hi_bitlen = 0;
|
||||||
|
glob1_len_x2 = 0;
|
||||||
|
glob1_hi_inv_lo = 0;
|
||||||
|
glob1_hi_inv_hi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calc_a_key(uint[] n1, uint[] n2, uint[] n3, uint[] n4, uint len)
|
||||||
|
{
|
||||||
|
uint[] n_tmp = new uint[64];
|
||||||
|
uint n3_len, n4_len;
|
||||||
|
int n3_bitlen;
|
||||||
|
uint bit_mask;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (uint* _pn3 = &n3[0])
|
||||||
|
{
|
||||||
|
uint* pn3 = _pn3;
|
||||||
|
|
||||||
|
init_bignum(n1, 1, len);
|
||||||
|
n4_len = len_bignum(n4, len);
|
||||||
|
init_two_dw(n4, n4_len);
|
||||||
|
n3_bitlen = (int)bitlen_bignum(n3, n4_len);
|
||||||
|
n3_len = (uint)((n3_bitlen + 31) / 32);
|
||||||
|
bit_mask = (((uint)1) << ((n3_bitlen - 1) % 32)) >> 1;
|
||||||
|
pn3 += n3_len - 1;
|
||||||
|
n3_bitlen--;
|
||||||
|
mov_bignum(n1, n2, n4_len);
|
||||||
|
while (--n3_bitlen != -1)
|
||||||
|
{
|
||||||
|
if (bit_mask == 0)
|
||||||
|
{
|
||||||
|
bit_mask = 0x80000000;
|
||||||
|
pn3--;
|
||||||
|
}
|
||||||
|
calc_a_bignum(n_tmp, n1, n1, n4_len);
|
||||||
|
if ((*pn3 & bit_mask) != 0)
|
||||||
|
calc_a_bignum(n1, n_tmp, n2, n4_len);
|
||||||
|
else
|
||||||
|
mov_bignum(n1, n_tmp, n4_len);
|
||||||
|
bit_mask >>= 1;
|
||||||
|
}
|
||||||
|
init_bignum(n_tmp, 0, n4_len);
|
||||||
|
clear_tmp_vars(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe void memcpy(byte* dest, byte* src, int len)
|
||||||
|
{
|
||||||
|
while (len-- != 0) *dest++ = *src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe void process_predata(byte* pre, uint pre_len, byte *buf)
|
||||||
|
{
|
||||||
|
uint[] n2 = new uint[64];
|
||||||
|
uint[] n3 = new uint[64];
|
||||||
|
|
||||||
|
uint a = (pubkey.len - 1) / 8;
|
||||||
|
while (a + 1 <= pre_len)
|
||||||
|
{
|
||||||
|
init_bignum(n2, 0, 64);
|
||||||
|
fixed( uint * pn2 = &n2[0] )
|
||||||
|
memcpy((byte *)pn2, pre, (int)a + 1);
|
||||||
|
calc_a_key(n3, n2, pubkey.key2, pubkey.key1, 64);
|
||||||
|
|
||||||
|
fixed( uint * pn3 = &n3[0] )
|
||||||
|
memcpy(buf, (byte *)pn3, (int)a);
|
||||||
|
|
||||||
|
pre_len -= a + 1;
|
||||||
|
pre += a + 1;
|
||||||
|
buf += a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] DecryptKey(byte[] src)
|
||||||
|
{
|
||||||
|
init_pubkey();
|
||||||
|
byte[] dest = new byte[256];
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* pdest = &dest[0])
|
||||||
|
fixed (byte* psrc = &src[0])
|
||||||
|
process_predata(psrc, len_predata(), pdest);
|
||||||
|
}
|
||||||
|
return dest.Take(56).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
OpenRA.FileFormats/Cache.cs
Normal file
59
OpenRA.FileFormats/Cache.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Cache<T, U> : IEnumerable<KeyValuePair<T, U>>
|
||||||
|
{
|
||||||
|
Dictionary<T, U> hax = new Dictionary<T, U>();
|
||||||
|
Func<T,U> loader;
|
||||||
|
|
||||||
|
public Cache(Func<T,U> loader)
|
||||||
|
{
|
||||||
|
if (loader == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
this.loader = loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U this[T key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
U result;
|
||||||
|
if (!hax.TryGetValue(key, out result))
|
||||||
|
hax.Add(key, result = loader(key));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<T, U>> GetEnumerator() { return hax.GetEnumerator(); }
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||||
|
|
||||||
|
public IEnumerable<T> Keys { get { return hax.Keys; } }
|
||||||
|
public IEnumerable<U> Values { get { return hax.Values; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
76
OpenRA.FileFormats/Collections/Set.cs
Executable file
76
OpenRA.FileFormats/Collections/Set.cs
Executable file
@@ -0,0 +1,76 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenRA.Collections
|
||||||
|
{
|
||||||
|
public class Set<T> : IEnumerable<T>
|
||||||
|
{
|
||||||
|
Dictionary<T, bool> data = new Dictionary<T, bool>();
|
||||||
|
|
||||||
|
public void Add( T obj )
|
||||||
|
{
|
||||||
|
data.Add( obj, false );
|
||||||
|
if( OnAdd != null )
|
||||||
|
OnAdd( obj );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove( T obj )
|
||||||
|
{
|
||||||
|
data.Remove( obj );
|
||||||
|
if( OnRemove != null )
|
||||||
|
OnRemove( obj );
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action<T> OnAdd;
|
||||||
|
public event Action<T> OnRemove;
|
||||||
|
|
||||||
|
public IEnumerator<T> GetEnumerator()
|
||||||
|
{
|
||||||
|
return data.Keys.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CachedView<T,U> : Set<U>
|
||||||
|
{
|
||||||
|
public CachedView( Set<T> set, Func<T, bool> include, Func<T, U> store )
|
||||||
|
: this( set, include, x => new[] { store( x ) } )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CachedView( Set<T> set, Func<T,bool> include, Func<T,IEnumerable<U>> store )
|
||||||
|
{
|
||||||
|
foreach( var t in set )
|
||||||
|
if( include( t ) )
|
||||||
|
store( t ).Do( x => Add( x ) );
|
||||||
|
|
||||||
|
set.OnAdd += obj => { if( include( obj ) ) store( obj ).Do( x => Add( x ) ); };
|
||||||
|
set.OnRemove += obj => { if( include( obj ) ) store( obj ).Do( x => Remove( x ) ); };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
OpenRA.FileFormats/DisposableAction.cs
Normal file
45
OpenRA.FileFormats/DisposableAction.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public class DisposableAction : IDisposable
|
||||||
|
{
|
||||||
|
public DisposableAction(Action a) { this.a = a; }
|
||||||
|
|
||||||
|
Action a;
|
||||||
|
bool disposed;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (disposed) return;
|
||||||
|
disposed = true;
|
||||||
|
a();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~DisposableAction()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
156
OpenRA.FileFormats/Dune2ShpReader.cs
Normal file
156
OpenRA.FileFormats/Dune2ShpReader.cs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public enum Dune2ImageFlags : int
|
||||||
|
{
|
||||||
|
F80_F2 = 0,
|
||||||
|
F2 = 2,
|
||||||
|
L16_F80_F2_1 = 1,
|
||||||
|
L16_F80_F2_2 = 3,
|
||||||
|
Ln_F80_F2 = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Dune2ImageHeader
|
||||||
|
{
|
||||||
|
public readonly Dune2ImageFlags Flags;
|
||||||
|
public readonly int Width;
|
||||||
|
public readonly int Height;
|
||||||
|
public readonly int Slices;
|
||||||
|
public readonly int FileSize;
|
||||||
|
public readonly int DataSize;
|
||||||
|
|
||||||
|
public readonly byte[] LookupTable;
|
||||||
|
public byte[] Image;
|
||||||
|
|
||||||
|
public Dune2ImageHeader(BinaryReader reader)
|
||||||
|
{
|
||||||
|
Flags = (Dune2ImageFlags)reader.ReadUInt16();
|
||||||
|
Slices = reader.ReadByte();
|
||||||
|
Width = reader.ReadUInt16();
|
||||||
|
Height = reader.ReadByte();
|
||||||
|
FileSize = reader.ReadUInt16();
|
||||||
|
DataSize = reader.ReadUInt16();
|
||||||
|
|
||||||
|
if (Flags == Dune2ImageFlags.L16_F80_F2_1 ||
|
||||||
|
Flags == Dune2ImageFlags.L16_F80_F2_2 ||
|
||||||
|
Flags == Dune2ImageFlags.Ln_F80_F2)
|
||||||
|
{
|
||||||
|
int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? reader.ReadByte() : (byte)16;
|
||||||
|
LookupTable = new byte[n];
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
LookupTable[i] = reader.ReadByte();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LookupTable = new byte[256];
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
LookupTable[i] = (byte)i;
|
||||||
|
LookupTable[1] = 0x7f;
|
||||||
|
LookupTable[2] = 0x7e;
|
||||||
|
LookupTable[3] = 0x7d;
|
||||||
|
LookupTable[4] = 0x7c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size Size
|
||||||
|
{
|
||||||
|
get { return new Size(Width, Height); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Dune2ShpReader : IEnumerable<Dune2ImageHeader>
|
||||||
|
{
|
||||||
|
public readonly int ImageCount;
|
||||||
|
|
||||||
|
List<Dune2ImageHeader> headers = new List<Dune2ImageHeader>();
|
||||||
|
|
||||||
|
public Dune2ShpReader(Stream stream)
|
||||||
|
{
|
||||||
|
BinaryReader reader = new BinaryReader(stream);
|
||||||
|
|
||||||
|
ImageCount = reader.ReadUInt16();
|
||||||
|
|
||||||
|
//Last offset is pointer to end of file.
|
||||||
|
uint[] offsets = new uint[ImageCount + 1];
|
||||||
|
|
||||||
|
uint temp = reader.ReadUInt32();
|
||||||
|
|
||||||
|
//If fourth byte in file is non-zero, the offsets are two bytes each.
|
||||||
|
bool twoByteOffsets = (temp & 0xFF0000) > 0;
|
||||||
|
if (twoByteOffsets)
|
||||||
|
{
|
||||||
|
offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes
|
||||||
|
offsets[1] = (temp & 0xFFFF) + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
offsets[0] = temp + 2;
|
||||||
|
|
||||||
|
for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++)
|
||||||
|
offsets[i] = (twoByteOffsets ? reader.ReadUInt16() : reader.ReadUInt32()) + 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < ImageCount; i++)
|
||||||
|
{
|
||||||
|
reader.BaseStream.Seek(offsets[i], SeekOrigin.Begin);
|
||||||
|
Dune2ImageHeader header = new Dune2ImageHeader(reader);
|
||||||
|
byte[] imgData = reader.ReadBytes(header.FileSize);
|
||||||
|
header.Image = new byte[header.Height * header.Width];
|
||||||
|
|
||||||
|
//Decode image data
|
||||||
|
if (header.Flags != Dune2ImageFlags.F2)
|
||||||
|
{
|
||||||
|
byte[] tempData = new byte[header.DataSize];
|
||||||
|
Format80.DecodeInto(imgData, tempData);
|
||||||
|
Format2.DecodeInto(tempData, header.Image);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Format2.DecodeInto(imgData, header.Image);
|
||||||
|
|
||||||
|
//Lookup values in lookup table
|
||||||
|
if (header.LookupTable != null)
|
||||||
|
for (int j = 0; j < header.Image.Length; j++)
|
||||||
|
header.Image[j] = header.LookupTable[header.Image[j]];
|
||||||
|
|
||||||
|
headers.Add(header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dune2ImageHeader this[int index]
|
||||||
|
{
|
||||||
|
get { return headers[index]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<Dune2ImageHeader> GetEnumerator()
|
||||||
|
{
|
||||||
|
return headers.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
OpenRA.FileFormats/Exts.cs
Normal file
39
OpenRA.FileFormats/Exts.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public static class Exts
|
||||||
|
{
|
||||||
|
public static string F(this string fmt, params object[] args)
|
||||||
|
{
|
||||||
|
return string.Format(fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Do<T>( this IEnumerable<T> e, Action<T> fn )
|
||||||
|
{
|
||||||
|
foreach( var ee in e )
|
||||||
|
fn( ee );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
119
OpenRA.FileFormats/FieldLoader.cs
Normal file
119
OpenRA.FileFormats/FieldLoader.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public static class FieldLoader
|
||||||
|
{
|
||||||
|
public static void Load(object self, IniSection ini)
|
||||||
|
{
|
||||||
|
foreach (var x in ini)
|
||||||
|
{
|
||||||
|
var field = self.GetType().GetField(x.Key.Trim());
|
||||||
|
if (field == null)
|
||||||
|
throw new NotImplementedException("Missing field `{0}` on `{1}`".F(x.Key.Trim(), self.GetType().Name));
|
||||||
|
field.SetValue(self, GetValue(field.FieldType, x.Value.Trim()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Load(object self, MiniYaml my)
|
||||||
|
{
|
||||||
|
foreach (var x in my.Nodes)
|
||||||
|
{
|
||||||
|
var field = self.GetType().GetField(x.Key.Trim());
|
||||||
|
if (field == null)
|
||||||
|
throw new NotImplementedException("Missing field `{0}` on `{1}`".F(x.Key.Trim(), self.GetType().Name));
|
||||||
|
field.SetValue(self, GetValue(field.FieldType, x.Value.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static object GetValue( Type fieldType, string x )
|
||||||
|
{
|
||||||
|
if (x != null) x = x.Trim();
|
||||||
|
if( fieldType == typeof( int ) )
|
||||||
|
return int.Parse( x );
|
||||||
|
|
||||||
|
else if (fieldType == typeof(float))
|
||||||
|
return float.Parse(x.Replace("%","")) * (x.Contains( '%' ) ? 0.01f : 1f);
|
||||||
|
|
||||||
|
else if (fieldType == typeof(string))
|
||||||
|
return x;
|
||||||
|
|
||||||
|
else if (fieldType.IsEnum)
|
||||||
|
return Enum.Parse(fieldType, x, true);
|
||||||
|
|
||||||
|
else if (fieldType == typeof(bool))
|
||||||
|
return ParseYesNo(x);
|
||||||
|
|
||||||
|
else if (fieldType.IsArray)
|
||||||
|
{
|
||||||
|
if (x == null)
|
||||||
|
return Array.CreateInstance(fieldType.GetElementType(), 0);
|
||||||
|
|
||||||
|
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
ret.SetValue(GetValue(fieldType.GetElementType(), parts[i].Trim()), i);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else if (fieldType == typeof(int2))
|
||||||
|
{
|
||||||
|
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw new InvalidOperationException("FieldLoader: don't know how to load field of type " + fieldType.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ParseYesNo( string p )
|
||||||
|
{
|
||||||
|
p = p.ToLowerInvariant();
|
||||||
|
if( p == "yes" ) return true;
|
||||||
|
if( p == "true" ) return true;
|
||||||
|
if( p == "no" ) return false;
|
||||||
|
if( p == "false" ) return false;
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FieldSaver
|
||||||
|
{
|
||||||
|
public static MiniYaml Save(object o)
|
||||||
|
{
|
||||||
|
return new MiniYaml(null, o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
|
||||||
|
.ToDictionary(
|
||||||
|
f => f.Name,
|
||||||
|
f => new MiniYaml(FormatValue(o, f))));
|
||||||
|
}
|
||||||
|
|
||||||
|
static string FormatValue(object o, FieldInfo f)
|
||||||
|
{
|
||||||
|
var v = f.GetValue(o);
|
||||||
|
return f.FieldType.IsArray
|
||||||
|
? string.Join(",", ((Array)v).OfType<object>().Select(a => a.ToString()).ToArray())
|
||||||
|
: v.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
138
OpenRA.FileFormats/FileSystem.cs
Normal file
138
OpenRA.FileFormats/FileSystem.cs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public static class FileSystem
|
||||||
|
{
|
||||||
|
static List<IFolder> mountedFolders = new List<IFolder>();
|
||||||
|
|
||||||
|
static Cache<uint, List<IFolder>> allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||||
|
|
||||||
|
static void MountInner(IFolder folder)
|
||||||
|
{
|
||||||
|
mountedFolders.Add(folder);
|
||||||
|
|
||||||
|
foreach( var hash in folder.AllFileHashes() )
|
||||||
|
{
|
||||||
|
var l = allFiles[hash];
|
||||||
|
if( !l.Contains( folder ) )
|
||||||
|
l.Add( folder );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Mount(string name)
|
||||||
|
{
|
||||||
|
name = name.ToLowerInvariant();
|
||||||
|
var optional = name.StartsWith("~");
|
||||||
|
if (optional) name = name.Substring(1);
|
||||||
|
|
||||||
|
var a = name.EndsWith(".mix")
|
||||||
|
? (Action)(() => FileSystem.MountInner(new Package(name)))
|
||||||
|
: () => FileSystem.MountInner(new Folder(name));
|
||||||
|
|
||||||
|
if (optional)
|
||||||
|
try { a(); }
|
||||||
|
catch { }
|
||||||
|
else
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void UnmountAll()
|
||||||
|
{
|
||||||
|
mountedFolders.Clear();
|
||||||
|
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename )
|
||||||
|
{
|
||||||
|
foreach( var folder in index[ PackageEntry.HashFilename( filename ) ] )
|
||||||
|
{
|
||||||
|
Stream s = folder.GetContent(filename);
|
||||||
|
if( s != null )
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream Open(string filename)
|
||||||
|
{
|
||||||
|
if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 )
|
||||||
|
{
|
||||||
|
var ret = GetFromCache( allFiles, filename );
|
||||||
|
if( ret != null )
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach( IFolder folder in mountedFolders )
|
||||||
|
{
|
||||||
|
Stream s = folder.GetContent(filename);
|
||||||
|
if( s != null )
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stream OpenWithExts( string filename, params string[] exts )
|
||||||
|
{
|
||||||
|
if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 )
|
||||||
|
{
|
||||||
|
foreach( var ext in exts )
|
||||||
|
{
|
||||||
|
var s = GetFromCache( allFiles, filename + ext );
|
||||||
|
if( s != null )
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach( var ext in exts )
|
||||||
|
{
|
||||||
|
foreach( IFolder folder in mountedFolders )
|
||||||
|
{
|
||||||
|
Stream s = folder.GetContent( filename + ext );
|
||||||
|
if( s != null )
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Exists(string filename)
|
||||||
|
{
|
||||||
|
foreach (var folder in mountedFolders)
|
||||||
|
{
|
||||||
|
var s = folder.GetContent(filename);
|
||||||
|
if (s != null)
|
||||||
|
{
|
||||||
|
s.Dispose();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
OpenRA.FileFormats/Folder.cs
Normal file
45
OpenRA.FileFormats/Folder.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Folder : IFolder
|
||||||
|
{
|
||||||
|
readonly string path;
|
||||||
|
|
||||||
|
public Folder(string path) { this.path = path; }
|
||||||
|
|
||||||
|
public Stream GetContent(string filename)
|
||||||
|
{
|
||||||
|
Log.Write( "GetContent from folder: {0}", filename );
|
||||||
|
try { return File.OpenRead( Path.Combine( path, filename ) ); }
|
||||||
|
catch { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<uint> AllFileHashes()
|
||||||
|
{
|
||||||
|
foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) )
|
||||||
|
yield return PackageEntry.HashFilename( filename );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
OpenRA.FileFormats/Format2.cs
Normal file
46
OpenRA.FileFormats/Format2.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public static class Format2
|
||||||
|
{
|
||||||
|
public static int DecodeInto(byte[] src, byte[] dest)
|
||||||
|
{
|
||||||
|
FastByteReader r = new FastByteReader(src);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (!r.Done())
|
||||||
|
{
|
||||||
|
byte cmd = r.ReadByte();
|
||||||
|
if (cmd == 0)
|
||||||
|
{
|
||||||
|
byte count = r.ReadByte();
|
||||||
|
while (count-- > 0)
|
||||||
|
dest[i++] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dest[i++] = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
OpenRA.FileFormats/Format40.cs
Normal file
88
OpenRA.FileFormats/Format40.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public static class Format40
|
||||||
|
{
|
||||||
|
public static int DecodeInto( byte[] src, byte[] dest )
|
||||||
|
{
|
||||||
|
var ctx = new FastByteReader(src);
|
||||||
|
int destIndex = 0;
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
byte i = ctx.ReadByte();
|
||||||
|
if( ( i & 0x80 ) == 0 )
|
||||||
|
{
|
||||||
|
int count = i & 0x7F;
|
||||||
|
if( count == 0 )
|
||||||
|
{
|
||||||
|
// case 6
|
||||||
|
count = ctx.ReadByte();
|
||||||
|
byte value = ctx.ReadByte();
|
||||||
|
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||||
|
dest[ destIndex ] ^= value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// case 5
|
||||||
|
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||||
|
dest[destIndex] ^= ctx.ReadByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int count = i & 0x7F;
|
||||||
|
if( count == 0 )
|
||||||
|
{
|
||||||
|
count = ctx.ReadWord();
|
||||||
|
if( count == 0 )
|
||||||
|
return destIndex;
|
||||||
|
|
||||||
|
if( ( count & 0x8000 ) == 0 )
|
||||||
|
{
|
||||||
|
// case 2
|
||||||
|
destIndex += ( count & 0x7FFF );
|
||||||
|
}
|
||||||
|
else if( ( count & 0x4000 ) == 0 )
|
||||||
|
{
|
||||||
|
// case 3
|
||||||
|
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
|
||||||
|
dest[destIndex] ^= ctx.ReadByte();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// case 4
|
||||||
|
byte value = ctx.ReadByte();
|
||||||
|
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
|
||||||
|
dest[ destIndex ] ^= value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// case 1
|
||||||
|
destIndex += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
135
OpenRA.FileFormats/Format80.cs
Normal file
135
OpenRA.FileFormats/Format80.cs
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
class FastByteReader
|
||||||
|
{
|
||||||
|
readonly byte[] src;
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
public FastByteReader(byte[] src)
|
||||||
|
{
|
||||||
|
this.src = src;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Done() { return offset >= src.Length; }
|
||||||
|
public byte ReadByte() { return src[offset++]; }
|
||||||
|
public int ReadWord()
|
||||||
|
{
|
||||||
|
int x = ReadByte();
|
||||||
|
return x | (ReadByte() << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(byte[] dest, int offset, int count)
|
||||||
|
{
|
||||||
|
Array.Copy(src, this.offset, dest, offset, count);
|
||||||
|
this.offset += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Format80
|
||||||
|
{
|
||||||
|
static void ReplicatePrevious( byte[] dest, int destIndex, int srcIndex, int count )
|
||||||
|
{
|
||||||
|
if( srcIndex > destIndex )
|
||||||
|
throw new NotImplementedException( string.Format( "srcIndex > destIndex {0} {1}", srcIndex, destIndex ) );
|
||||||
|
|
||||||
|
if( destIndex - srcIndex == 1 )
|
||||||
|
{
|
||||||
|
for( int i = 0 ; i < count ; i++ )
|
||||||
|
dest[ destIndex + i ] = dest[ destIndex - 1 ];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( int i = 0 ; i < count ; i++ )
|
||||||
|
dest[ destIndex + i ] = dest[ srcIndex + i ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int DecodeInto( byte[] src, byte[] dest )
|
||||||
|
{
|
||||||
|
var ctx = new FastByteReader(src);
|
||||||
|
int destIndex = 0;
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
byte i = ctx.ReadByte();
|
||||||
|
if( ( i & 0x80 ) == 0 )
|
||||||
|
{
|
||||||
|
// case 2
|
||||||
|
byte secondByte = ctx.ReadByte();
|
||||||
|
int count = ( ( i & 0x70 ) >> 4 ) + 3;
|
||||||
|
int rpos = ( ( i & 0xf ) << 8 ) + secondByte;
|
||||||
|
|
||||||
|
ReplicatePrevious( dest, destIndex, destIndex - rpos, count );
|
||||||
|
destIndex += count;
|
||||||
|
}
|
||||||
|
else if( ( i & 0x40 ) == 0 )
|
||||||
|
{
|
||||||
|
// case 1
|
||||||
|
int count = i & 0x3F;
|
||||||
|
if( count == 0 )
|
||||||
|
return destIndex;
|
||||||
|
|
||||||
|
ctx.CopyTo( dest, destIndex, count );
|
||||||
|
destIndex += count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int count3 = i & 0x3F;
|
||||||
|
if( count3 == 0x3E )
|
||||||
|
{
|
||||||
|
// case 4
|
||||||
|
int count = ctx.ReadWord();
|
||||||
|
byte color = ctx.ReadByte();
|
||||||
|
|
||||||
|
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||||
|
dest[ destIndex ] = color;
|
||||||
|
}
|
||||||
|
else if( count3 == 0x3F )
|
||||||
|
{
|
||||||
|
// case 5
|
||||||
|
int count = ctx.ReadWord();
|
||||||
|
int srcIndex = ctx.ReadWord();
|
||||||
|
if( srcIndex >= destIndex )
|
||||||
|
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
|
||||||
|
|
||||||
|
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||||
|
dest[ destIndex ] = dest[ srcIndex++ ];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// case 3
|
||||||
|
int count = count3 + 3;
|
||||||
|
int srcIndex = ctx.ReadWord();
|
||||||
|
if( srcIndex >= destIndex )
|
||||||
|
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
|
||||||
|
|
||||||
|
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||||
|
dest[ destIndex ] = dest[ srcIndex++ ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
OpenRA.FileFormats/Graphics/IGraphicsDevice.cs
Executable file
105
OpenRA.FileFormats/Graphics/IGraphicsDevice.cs
Executable file
@@ -0,0 +1,105 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats.Graphics
|
||||||
|
{
|
||||||
|
[AttributeUsage( AttributeTargets.Assembly )]
|
||||||
|
public class RendererAttribute : Attribute
|
||||||
|
{
|
||||||
|
public readonly Type Type;
|
||||||
|
|
||||||
|
public RendererAttribute( Type graphicsDeviceType )
|
||||||
|
{
|
||||||
|
if( !typeof( IGraphicsDevice ).IsAssignableFrom( graphicsDeviceType ) )
|
||||||
|
throw new InvalidOperationException( "Incorrect type in RendererAttribute" );
|
||||||
|
Type = graphicsDeviceType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IGraphicsDevice
|
||||||
|
{
|
||||||
|
IVertexBuffer<Vertex> CreateVertexBuffer( int length );
|
||||||
|
IIndexBuffer CreateIndexBuffer( int length );
|
||||||
|
ITexture CreateTexture( Bitmap bitmap );
|
||||||
|
IShader CreateShader( Stream stream );
|
||||||
|
|
||||||
|
Size WindowSize { get; }
|
||||||
|
|
||||||
|
void Begin();
|
||||||
|
void End();
|
||||||
|
void Clear( Color color );
|
||||||
|
void Present();
|
||||||
|
|
||||||
|
void DrawIndexedPrimitives( PrimitiveType type, Range<int> vertexRange, Range<int> indexRange );
|
||||||
|
void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives );
|
||||||
|
|
||||||
|
void EnableScissor( int left, int top, int width, int height );
|
||||||
|
void DisableScissor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IVertexBuffer<T>
|
||||||
|
{
|
||||||
|
void Bind();
|
||||||
|
void SetData( T[] vertices );
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IIndexBuffer
|
||||||
|
{
|
||||||
|
void Bind();
|
||||||
|
void SetData( ushort[] indices );
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IShader
|
||||||
|
{
|
||||||
|
void SetValue( string name, float x, float y );
|
||||||
|
void SetValue( string param, ITexture texture );
|
||||||
|
void Commit();
|
||||||
|
void Render( Action a );
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ITexture
|
||||||
|
{
|
||||||
|
void SetData( Bitmap bitmap );
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IFont
|
||||||
|
{
|
||||||
|
void DrawText( string text, int2 pos, Color c );
|
||||||
|
|
||||||
|
int2 Measure( string text );
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PrimitiveType
|
||||||
|
{
|
||||||
|
PointList,
|
||||||
|
LineList,
|
||||||
|
TriangleList,
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Range<T>
|
||||||
|
{
|
||||||
|
public readonly T Start, End;
|
||||||
|
public Range( T start, T end ) { Start = start; End = end; }
|
||||||
|
}
|
||||||
|
}
|
||||||
38
OpenRA.FileFormats/Graphics/Vertex.cs
Normal file
38
OpenRA.FileFormats/Graphics/Vertex.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats.Graphics
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct Vertex
|
||||||
|
{
|
||||||
|
public float x, y, z, u, v;
|
||||||
|
public float p, c;
|
||||||
|
|
||||||
|
public Vertex(float2 xy, float2 uv, float2 pc)
|
||||||
|
{
|
||||||
|
this.x = xy.X; this.y = xy.Y; this.z = 0;
|
||||||
|
this.u = uv.X; this.v = uv.Y;
|
||||||
|
this.p = pc.X; this.c = pc.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
OpenRA.FileFormats/IPaletteRemap.cs
Normal file
29
OpenRA.FileFormats/IPaletteRemap.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public interface IPaletteRemap
|
||||||
|
{
|
||||||
|
Color GetRemappedColor(Color original, int index);
|
||||||
|
}
|
||||||
|
}
|
||||||
161
OpenRA.FileFormats/IniFile.cs
Normal file
161
OpenRA.FileFormats/IniFile.cs
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class IniFile
|
||||||
|
{
|
||||||
|
Dictionary<string, IniSection> sections = new Dictionary<string, IniSection>();
|
||||||
|
|
||||||
|
public IniFile( Stream s )
|
||||||
|
{
|
||||||
|
Load( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IniFile( params Stream[] streams )
|
||||||
|
{
|
||||||
|
foreach( var s in streams )
|
||||||
|
Load( s );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load( Stream s )
|
||||||
|
{
|
||||||
|
StreamReader reader = new StreamReader( s );
|
||||||
|
IniSection currentSection = null;
|
||||||
|
|
||||||
|
while( !reader.EndOfStream )
|
||||||
|
{
|
||||||
|
string line = reader.ReadLine();
|
||||||
|
|
||||||
|
if( line.Length == 0 ) continue;
|
||||||
|
|
||||||
|
switch( line[ 0 ] )
|
||||||
|
{
|
||||||
|
case ';': break;
|
||||||
|
case '[': currentSection = ProcessSection( line ); break;
|
||||||
|
default: ProcessEntry( line, currentSection ); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Regex sectionPattern = new Regex( @"^\[([^]]*)\]" );
|
||||||
|
|
||||||
|
IniSection ProcessSection( string line )
|
||||||
|
{
|
||||||
|
Match m = sectionPattern.Match( line );
|
||||||
|
if( m == null || !m.Success )
|
||||||
|
return null;
|
||||||
|
string sectionName = m.Groups[ 1 ].Value.ToLowerInvariant();
|
||||||
|
|
||||||
|
IniSection ret;
|
||||||
|
if( !sections.TryGetValue( sectionName, out ret ) )
|
||||||
|
sections.Add( sectionName, ret = new IniSection( sectionName ) );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessEntry( string line, IniSection currentSection )
|
||||||
|
{
|
||||||
|
int comment = line.IndexOf( ';' );
|
||||||
|
if( comment >= 0 )
|
||||||
|
line = line.Substring( 0, comment );
|
||||||
|
|
||||||
|
line = line.Trim();
|
||||||
|
if( line.Length == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var key = line;
|
||||||
|
var value = "";
|
||||||
|
int eq = line.IndexOf( '=' );
|
||||||
|
if( eq >= 0 )
|
||||||
|
{
|
||||||
|
key = line.Substring( 0, eq );
|
||||||
|
value = line.Substring( eq + 1, line.Length - eq - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( currentSection == null )
|
||||||
|
throw new InvalidOperationException( "No current INI section" );
|
||||||
|
|
||||||
|
if( !currentSection.Contains( key ) )
|
||||||
|
currentSection.Add( key, value );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IniSection GetSection( string s )
|
||||||
|
{
|
||||||
|
return GetSection( s, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IniSection GetSection( string s, bool allowFail )
|
||||||
|
{
|
||||||
|
IniSection section;
|
||||||
|
if( sections.TryGetValue( s.ToLowerInvariant(), out section ) )
|
||||||
|
return section;
|
||||||
|
|
||||||
|
if( allowFail )
|
||||||
|
return new IniSection( s );
|
||||||
|
throw new InvalidOperationException( "Section does not exist in map or rules: " + s );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IniSection> Sections { get { return sections.Values; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IniSection : IEnumerable<KeyValuePair<string, string>>
|
||||||
|
{
|
||||||
|
public string Name { get; private set; }
|
||||||
|
Dictionary<string, string> values = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
public IniSection( string name )
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add( string key, string value )
|
||||||
|
{
|
||||||
|
values[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains( string key )
|
||||||
|
{
|
||||||
|
return values.ContainsKey( key );
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetValue( string key, string defaultValue )
|
||||||
|
{
|
||||||
|
string s;
|
||||||
|
return values.TryGetValue( key, out s ) ? s : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return values.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
OpenRA.FileFormats/Lazy.cs
Normal file
56
OpenRA.FileFormats/Lazy.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Lazy<T>
|
||||||
|
{
|
||||||
|
Func<T> p;
|
||||||
|
T value;
|
||||||
|
|
||||||
|
public Lazy(Func<T> p)
|
||||||
|
{
|
||||||
|
if (p == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
this.p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (p == null)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
value = p();
|
||||||
|
p = null;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Lazy
|
||||||
|
{
|
||||||
|
public static Lazy<T> New<T>(Func<T> p) { return new Lazy<T>(p); }
|
||||||
|
}
|
||||||
|
}
|
||||||
176
OpenRA.FileFormats/Map.cs
Normal file
176
OpenRA.FileFormats/Map.cs
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Map
|
||||||
|
{
|
||||||
|
public readonly string Title;
|
||||||
|
public readonly string Theater;
|
||||||
|
|
||||||
|
public readonly int XOffset;
|
||||||
|
public readonly int YOffset;
|
||||||
|
public int2 Offset { get { return new int2( XOffset, YOffset ); } }
|
||||||
|
|
||||||
|
public readonly int Width;
|
||||||
|
public readonly int Height;
|
||||||
|
public int2 Size { get { return new int2(Width, Height); } }
|
||||||
|
|
||||||
|
public readonly TileReference[ , ] MapTiles = new TileReference[ 128, 128 ];
|
||||||
|
public readonly List<TreeReference> Trees = new List<TreeReference>();
|
||||||
|
|
||||||
|
public readonly IEnumerable<int2> SpawnPoints;
|
||||||
|
|
||||||
|
static string Truncate( string s, int maxLength )
|
||||||
|
{
|
||||||
|
return s.Length <= maxLength ? s : s.Substring(0,maxLength );
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TileSuffix { get { return "." + Truncate(Theater, 3); } }
|
||||||
|
|
||||||
|
public Map(IniFile file)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 128; j++)
|
||||||
|
for (int i = 0; i < 128; i++)
|
||||||
|
MapTiles[i, j] = new TileReference();
|
||||||
|
|
||||||
|
IniSection basic = file.GetSection("Basic");
|
||||||
|
Title = basic.GetValue("Name", "(null)");
|
||||||
|
|
||||||
|
IniSection map = file.GetSection("Map");
|
||||||
|
Theater = Truncate(map.GetValue("Theater", "TEMPERATE"), 8);
|
||||||
|
|
||||||
|
XOffset = int.Parse(map.GetValue("X", "0"));
|
||||||
|
YOffset = int.Parse(map.GetValue("Y", "0"));
|
||||||
|
|
||||||
|
Width = int.Parse(map.GetValue("Width", "0"));
|
||||||
|
Height = int.Parse(map.GetValue("Height", "0"));
|
||||||
|
|
||||||
|
UnpackTileData(ReadPackedSection(file.GetSection("MapPack")));
|
||||||
|
UnpackOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
|
||||||
|
ReadTrees(file);
|
||||||
|
|
||||||
|
SpawnPoints = file.GetSection("Waypoints")
|
||||||
|
.Select(kv => Pair.New(int.Parse(kv.Key), new int2(int.Parse(kv.Value) % 128, int.Parse(kv.Value) / 128)))
|
||||||
|
.Where(a => a.First < 8)
|
||||||
|
.Select(a => a.Second)
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
static MemoryStream ReadPackedSection(IniSection mapPackSection)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 1; ; i++)
|
||||||
|
{
|
||||||
|
string line = mapPackSection.GetValue(i.ToString(), null);
|
||||||
|
if (line == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
sb.Append(line.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = Convert.FromBase64String(sb.ToString());
|
||||||
|
List<byte[]> chunks = new List<byte[]>();
|
||||||
|
BinaryReader reader = new BinaryReader(new MemoryStream(data));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
uint length = reader.ReadUInt32() & 0xdfffffff;
|
||||||
|
byte[] dest = new byte[8192];
|
||||||
|
byte[] src = reader.ReadBytes((int)length);
|
||||||
|
|
||||||
|
/*int actualLength =*/ Format80.DecodeInto(src, dest);
|
||||||
|
|
||||||
|
chunks.Add(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (EndOfStreamException) { }
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
foreach (byte[] chunk in chunks)
|
||||||
|
ms.Write(chunk, 0, chunk.Length);
|
||||||
|
|
||||||
|
ms.Position = 0;
|
||||||
|
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte ReadByte( Stream s )
|
||||||
|
{
|
||||||
|
int ret = s.ReadByte();
|
||||||
|
if( ret == -1 )
|
||||||
|
throw new NotImplementedException();
|
||||||
|
return (byte)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ushort ReadWord(Stream s)
|
||||||
|
{
|
||||||
|
ushort ret = ReadByte(s);
|
||||||
|
ret |= (ushort)(ReadByte(s) << 8);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnpackTileData( MemoryStream ms )
|
||||||
|
{
|
||||||
|
for( int i = 0 ; i < 128 ; i++ )
|
||||||
|
for( int j = 0 ; j < 128 ; j++ )
|
||||||
|
MapTiles[j, i].tile = ReadWord(ms);
|
||||||
|
|
||||||
|
for( int i = 0 ; i < 128 ; i++ )
|
||||||
|
for( int j = 0 ; j < 128 ; j++ )
|
||||||
|
{
|
||||||
|
MapTiles[j, i].image = (byte)ms.ReadByte();
|
||||||
|
if( MapTiles[ j, i ].tile == 0xff || MapTiles[ j, i ].tile == 0xffff )
|
||||||
|
MapTiles[ j, i ].image = (byte)( i % 4 + ( j % 4 ) * 4 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnpackOverlayData( MemoryStream ms )
|
||||||
|
{
|
||||||
|
for( int i = 0 ; i < 128 ; i++ )
|
||||||
|
for( int j = 0 ; j < 128 ; j++ )
|
||||||
|
MapTiles[ j, i ].overlay = ReadByte( ms );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadTrees( IniFile file )
|
||||||
|
{
|
||||||
|
IniSection terrain = file.GetSection( "TERRAIN", true );
|
||||||
|
if( terrain == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach( KeyValuePair<string, string> kv in terrain )
|
||||||
|
Trees.Add( new TreeReference( int.Parse( kv.Key ), kv.Value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsInMap(int x, int y)
|
||||||
|
{
|
||||||
|
return (x >= XOffset && y >= YOffset && x < XOffset + Width && y < YOffset + Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
168
OpenRA.FileFormats/MiniYaml.cs
Executable file
168
OpenRA.FileFormats/MiniYaml.cs
Executable file
@@ -0,0 +1,168 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
using MiniYamlNodes = Dictionary<string, MiniYaml>;
|
||||||
|
|
||||||
|
public class MiniYaml
|
||||||
|
{
|
||||||
|
public string Value;
|
||||||
|
public Dictionary<string, MiniYaml> Nodes = new Dictionary<string,MiniYaml>();
|
||||||
|
|
||||||
|
public MiniYaml( string value ) : this( value, new Dictionary<string, MiniYaml>() ) { }
|
||||||
|
|
||||||
|
public MiniYaml( string value, Dictionary<string, MiniYaml> nodes )
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
Nodes = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dictionary<string, MiniYaml> FromLines(string[] lines)
|
||||||
|
{
|
||||||
|
var levels = new List<Dictionary<string, MiniYaml>>();
|
||||||
|
levels.Add(new Dictionary<string, MiniYaml>());
|
||||||
|
|
||||||
|
foreach (var line in lines)
|
||||||
|
{
|
||||||
|
var t = line.TrimStart(' ', '\t');
|
||||||
|
if (t.Length == 0 || t[0] == '#')
|
||||||
|
continue;
|
||||||
|
var level = line.Length - t.Length;
|
||||||
|
|
||||||
|
if (levels.Count <= level)
|
||||||
|
throw new InvalidOperationException("Bad indent in miniyaml");
|
||||||
|
while (levels.Count > level + 1)
|
||||||
|
levels.RemoveAt(levels.Count - 1);
|
||||||
|
|
||||||
|
var colon = t.IndexOf(':');
|
||||||
|
var d = new Dictionary<string, MiniYaml>();
|
||||||
|
|
||||||
|
if (colon == -1)
|
||||||
|
levels[level].Add(t.Trim(), new MiniYaml(null, d));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var value = t.Substring(colon + 1).Trim();
|
||||||
|
if (value.Length == 0)
|
||||||
|
value = null;
|
||||||
|
levels[level].Add(t.Substring(0, colon).Trim(), new MiniYaml(value, d));
|
||||||
|
}
|
||||||
|
levels.Add(d);
|
||||||
|
}
|
||||||
|
return levels[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, MiniYaml> FromFile( string path )
|
||||||
|
{
|
||||||
|
return FromLines(File.ReadAllLines( path ));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, MiniYaml> FromStream(Stream s)
|
||||||
|
{
|
||||||
|
using (var reader = new StreamReader(s))
|
||||||
|
return FromString(reader.ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, MiniYaml> FromString(string text)
|
||||||
|
{
|
||||||
|
return FromLines(text.Split('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<string, MiniYaml> Merge( Dictionary<string, MiniYaml> a, Dictionary<string, MiniYaml> b )
|
||||||
|
{
|
||||||
|
if( a.Count == 0 )
|
||||||
|
return b;
|
||||||
|
if( b.Count == 0 )
|
||||||
|
return a;
|
||||||
|
|
||||||
|
var ret = new Dictionary<string, MiniYaml>();
|
||||||
|
|
||||||
|
var keys = a.Keys.Union( b.Keys ).ToList();
|
||||||
|
|
||||||
|
var noInherit = keys.Where( x => x.Length > 0 && x[ 0 ] == '-' ).Select( x => x.Substring( 1 ) ).ToList();
|
||||||
|
|
||||||
|
foreach( var key in keys )
|
||||||
|
{
|
||||||
|
MiniYaml aa, bb;
|
||||||
|
a.TryGetValue( key, out aa );
|
||||||
|
b.TryGetValue( key, out bb );
|
||||||
|
|
||||||
|
if( key.Length > 0 && key[ 0 ] == '-' )
|
||||||
|
continue;
|
||||||
|
else if( noInherit.Contains( key ) )
|
||||||
|
{
|
||||||
|
if( aa != null )
|
||||||
|
ret.Add( key, aa );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret.Add( key, Merge( aa, bb ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MiniYaml Merge( MiniYaml a, MiniYaml b )
|
||||||
|
{
|
||||||
|
if( a == null )
|
||||||
|
return b;
|
||||||
|
if( b == null )
|
||||||
|
return a;
|
||||||
|
|
||||||
|
return new MiniYaml( a.Value ?? b.Value, Merge( a.Nodes, b.Nodes ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> ToLines(string name)
|
||||||
|
{
|
||||||
|
yield return name + ": " + Value;
|
||||||
|
if (Nodes != null)
|
||||||
|
foreach (var line in Nodes.ToLines(false))
|
||||||
|
yield return "\t" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MiniYamlExts
|
||||||
|
{
|
||||||
|
public static void WriteToFile(this MiniYamlNodes y, string filename)
|
||||||
|
{
|
||||||
|
File.WriteAllLines(filename, y.ToLines(true).Select(x => x.TrimEnd()).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string WriteToString(this MiniYamlNodes y)
|
||||||
|
{
|
||||||
|
return string.Join("\n", y.ToLines(true).Select(x => x.TrimEnd()).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> ToLines(this MiniYamlNodes y, bool lowest)
|
||||||
|
{
|
||||||
|
foreach (var kv in y)
|
||||||
|
{
|
||||||
|
foreach (var line in kv.Value.ToLines(kv.Key))
|
||||||
|
yield return line;
|
||||||
|
if (lowest)
|
||||||
|
yield return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
106
OpenRA.FileFormats/OpenRA.FileFormats.csproj
Normal file
106
OpenRA.FileFormats/OpenRA.FileFormats.csproj
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>OpenRA.FileFormats</RootNamespace>
|
||||||
|
<AssemblyName>OpenRA.FileFormats</AssemblyName>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<OldToolsVersion>2.0</OldToolsVersion>
|
||||||
|
<UpgradeBackupLocation>
|
||||||
|
</UpgradeBackupLocation>
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Tao.Sdl, Version=1.2.13.0, Culture=neutral, PublicKeyToken=9c7a200e36c0094e, processorArchitecture=MSIL" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="AudLoader.cs" />
|
||||||
|
<Compile Include="Blowfish.cs" />
|
||||||
|
<Compile Include="BlowfishKeyProvider.cs" />
|
||||||
|
<Compile Include="Cache.cs" />
|
||||||
|
<Compile Include="Collections\Set.cs" />
|
||||||
|
<Compile Include="DisposableAction.cs" />
|
||||||
|
<Compile Include="Dune2ShpReader.cs" />
|
||||||
|
<Compile Include="Exts.cs" />
|
||||||
|
<Compile Include="FieldLoader.cs" />
|
||||||
|
<Compile Include="FileSystem.cs" />
|
||||||
|
<Compile Include="float2.cs" />
|
||||||
|
<Compile Include="Folder.cs" />
|
||||||
|
<Compile Include="Format2.cs" />
|
||||||
|
<Compile Include="Format40.cs" />
|
||||||
|
<Compile Include="Format80.cs" />
|
||||||
|
<Compile Include="Graphics\IGraphicsDevice.cs" />
|
||||||
|
<Compile Include="Graphics\Vertex.cs" />
|
||||||
|
<Compile Include="IniFile.cs" />
|
||||||
|
<Compile Include="int2.cs" />
|
||||||
|
<Compile Include="IPaletteRemap.cs" />
|
||||||
|
<Compile Include="Lazy.cs" />
|
||||||
|
<Compile Include="Map.cs" />
|
||||||
|
<Compile Include="MiniYaml.cs" />
|
||||||
|
<Compile Include="PackageEntry.cs" />
|
||||||
|
<Compile Include="Package.cs" />
|
||||||
|
<Compile Include="Pair.cs" />
|
||||||
|
<Compile Include="Palette.cs" />
|
||||||
|
<Compile Include="PlayerColorRemap.cs" />
|
||||||
|
<Compile Include="PriorityQueue.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ProtocolVersion.cs" />
|
||||||
|
<Compile Include="Session.cs" />
|
||||||
|
<Compile Include="ShpReader.cs" />
|
||||||
|
<Compile Include="ShroudPaletteRemap.cs" />
|
||||||
|
<Compile Include="SingleColorRemap.cs" />
|
||||||
|
<Compile Include="Support\Log.cs" />
|
||||||
|
<Compile Include="Support\Stopwatch.cs" />
|
||||||
|
<Compile Include="Support\Timer.cs" />
|
||||||
|
<Compile Include="Terrain.cs" />
|
||||||
|
<Compile Include="TileReference.cs" />
|
||||||
|
<Compile Include="TileSet.cs" />
|
||||||
|
<Compile Include="TreeReference.cs" />
|
||||||
|
<Compile Include="Tuple.cs" />
|
||||||
|
<Compile Include="TypeDictionary.cs" />
|
||||||
|
<Compile Include="Walkability.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
||||||
166
OpenRA.FileFormats/Package.cs
Normal file
166
OpenRA.FileFormats/Package.cs
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public interface IFolder
|
||||||
|
{
|
||||||
|
Stream GetContent(string filename);
|
||||||
|
IEnumerable<uint> AllFileHashes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Package : IFolder
|
||||||
|
{
|
||||||
|
readonly Dictionary<uint, PackageEntry> index;
|
||||||
|
readonly bool isRmix, isEncrypted;
|
||||||
|
readonly long dataStart;
|
||||||
|
readonly Stream s;
|
||||||
|
|
||||||
|
public Package(string filename)
|
||||||
|
{
|
||||||
|
s = FileSystem.Open(filename);
|
||||||
|
|
||||||
|
BinaryReader reader = new BinaryReader(s);
|
||||||
|
uint signature = reader.ReadUInt32();
|
||||||
|
|
||||||
|
isRmix = 0 == (signature & ~(uint)(MixFileFlags.Checksum | MixFileFlags.Encrypted));
|
||||||
|
|
||||||
|
if (isRmix)
|
||||||
|
{
|
||||||
|
isEncrypted = 0 != (signature & (uint)MixFileFlags.Encrypted);
|
||||||
|
if( isEncrypted )
|
||||||
|
{
|
||||||
|
index = ParseRaHeader( s, out dataStart ).ToDictionary(x => x.Hash);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s.Seek( 0, SeekOrigin.Begin );
|
||||||
|
|
||||||
|
isEncrypted = false;
|
||||||
|
index = ParseTdHeader(s, out dataStart).ToDictionary(x => x.Hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
const long headerStart = 84;
|
||||||
|
|
||||||
|
List<PackageEntry> ParseRaHeader(Stream s, out long dataStart)
|
||||||
|
{
|
||||||
|
BinaryReader reader = new BinaryReader(s);
|
||||||
|
byte[] keyblock = reader.ReadBytes(80);
|
||||||
|
byte[] blowfishKey = new BlowfishKeyProvider().DecryptKey(keyblock);
|
||||||
|
|
||||||
|
uint[] h = ReadUints(reader, 2);
|
||||||
|
|
||||||
|
Blowfish fish = new Blowfish(blowfishKey);
|
||||||
|
MemoryStream ms = Decrypt( h, fish );
|
||||||
|
BinaryReader reader2 = new BinaryReader(ms);
|
||||||
|
|
||||||
|
ushort numFiles = reader2.ReadUInt16();
|
||||||
|
uint datasize = reader2.ReadUInt32();
|
||||||
|
|
||||||
|
Console.WriteLine("{0} files, {1} kb", numFiles, datasize >> 10);
|
||||||
|
|
||||||
|
s.Position = headerStart;
|
||||||
|
reader = new BinaryReader(s);
|
||||||
|
|
||||||
|
int byteCount = 6 + numFiles * PackageEntry.Size;
|
||||||
|
h = ReadUints( reader, ( byteCount + 3 ) / 4 );
|
||||||
|
|
||||||
|
ms = Decrypt( h, fish );
|
||||||
|
|
||||||
|
dataStart = headerStart + byteCount + ( ( ~byteCount + 1 ) & 7 );
|
||||||
|
|
||||||
|
long ds;
|
||||||
|
return ParseTdHeader( ms, out ds );
|
||||||
|
}
|
||||||
|
|
||||||
|
static MemoryStream Decrypt( uint[] h, Blowfish fish )
|
||||||
|
{
|
||||||
|
uint[] decrypted = fish.Decrypt( h );
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
BinaryWriter writer = new BinaryWriter( ms );
|
||||||
|
foreach( uint t in decrypted )
|
||||||
|
writer.Write( t );
|
||||||
|
writer.Flush();
|
||||||
|
|
||||||
|
ms.Position = 0;
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint[] ReadUints(BinaryReader r, int count)
|
||||||
|
{
|
||||||
|
uint[] ret = new uint[count];
|
||||||
|
for (int i = 0; i < ret.Length; i++)
|
||||||
|
ret[i] = r.ReadUInt32();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PackageEntry> ParseTdHeader(Stream s, out long dataStart)
|
||||||
|
{
|
||||||
|
List<PackageEntry> items = new List<PackageEntry>();
|
||||||
|
|
||||||
|
BinaryReader reader = new BinaryReader(s);
|
||||||
|
ushort numFiles = reader.ReadUInt16();
|
||||||
|
/*uint dataSize = */reader.ReadUInt32();
|
||||||
|
|
||||||
|
for (int i = 0; i < numFiles; i++)
|
||||||
|
items.Add(new PackageEntry(reader));
|
||||||
|
|
||||||
|
dataStart = s.Position;
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream GetContent(uint hash)
|
||||||
|
{
|
||||||
|
PackageEntry e;
|
||||||
|
if (!index.TryGetValue(hash, out e))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
s.Seek( dataStart + e.Offset, SeekOrigin.Begin );
|
||||||
|
byte[] data = new byte[ e.Length ];
|
||||||
|
s.Read( data, 0, (int)e.Length );
|
||||||
|
return new MemoryStream(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream GetContent(string filename)
|
||||||
|
{
|
||||||
|
return GetContent(PackageEntry.HashFilename(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<uint> AllFileHashes()
|
||||||
|
{
|
||||||
|
return index.Keys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
enum MixFileFlags : uint
|
||||||
|
{
|
||||||
|
Checksum = 0x10000,
|
||||||
|
Encrypted = 0x20000,
|
||||||
|
}
|
||||||
|
}
|
||||||
80
OpenRA.FileFormats/PackageEntry.cs
Normal file
80
OpenRA.FileFormats/PackageEntry.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class PackageEntry
|
||||||
|
{
|
||||||
|
public readonly uint Hash;
|
||||||
|
public readonly uint Offset;
|
||||||
|
public readonly uint Length;
|
||||||
|
|
||||||
|
public PackageEntry(BinaryReader r)
|
||||||
|
{
|
||||||
|
Hash = r.ReadUInt32();
|
||||||
|
Offset = r.ReadUInt32();
|
||||||
|
Length = r.ReadUInt32();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string filename;
|
||||||
|
if (Names.TryGetValue(Hash, out filename))
|
||||||
|
return string.Format("{0} - offset 0x{1:x8} - length 0x{2:x8}", filename, Offset, Length);
|
||||||
|
else
|
||||||
|
return string.Format("0x{0:x8} - offset 0x{1:x8} - length 0x{2:x8}", Hash, Offset, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint HashFilename(string name)
|
||||||
|
{
|
||||||
|
if (name.Length > 12)
|
||||||
|
name = name.Substring(0, 12);
|
||||||
|
|
||||||
|
name = name.ToUpperInvariant();
|
||||||
|
if (name.Length % 4 != 0)
|
||||||
|
name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');
|
||||||
|
|
||||||
|
MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
|
||||||
|
BinaryReader reader = new BinaryReader(ms);
|
||||||
|
|
||||||
|
int len = name.Length >> 2;
|
||||||
|
uint result = 0;
|
||||||
|
|
||||||
|
while (len-- != 0)
|
||||||
|
result = ((result << 1) | (result >> 31)) + reader.ReadUInt32();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Dictionary<uint, string> Names = new Dictionary<uint,string>();
|
||||||
|
|
||||||
|
public static void AddStandardName(string s)
|
||||||
|
{
|
||||||
|
uint hash = HashFilename(s);
|
||||||
|
Names.Add(hash, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public const int Size = 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
75
OpenRA.FileFormats/Pair.cs
Normal file
75
OpenRA.FileFormats/Pair.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public struct Pair<T, U>
|
||||||
|
{
|
||||||
|
public T First;
|
||||||
|
public U Second;
|
||||||
|
|
||||||
|
public Pair(T first, U second)
|
||||||
|
{
|
||||||
|
First = first;
|
||||||
|
Second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEqualityComparer<T> tc = EqualityComparer<T>.Default;
|
||||||
|
static IEqualityComparer<U> uc = EqualityComparer<U>.Default;
|
||||||
|
|
||||||
|
public static bool operator ==(Pair<T, U> a, Pair<T, U> b)
|
||||||
|
{
|
||||||
|
return tc.Equals(a.First, b.First) && uc.Equals(a.Second, b.Second);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Pair<T, U> a, Pair<T, U> b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is Pair<T, U>))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (Pair<T, U>)obj == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return First.GetHashCode() ^ Second.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<T, U> WithFirst(T t) { return new Pair<T, U>(t, Second); }
|
||||||
|
public Pair<T, U> WithSecond(U u) { return new Pair<T, U>(First, u); }
|
||||||
|
|
||||||
|
public static T AsFirst(Pair<T, U> p) { return p.First; }
|
||||||
|
public static U AsSecond(Pair<T, U> p) { return p.Second; }
|
||||||
|
|
||||||
|
public Pair<U, T> Swap() { return Pair.New(Second, First); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Pair
|
||||||
|
{
|
||||||
|
public static Pair<T, U> New<T, U>(T t, U u) { return new Pair<T, U>(t, u); }
|
||||||
|
}
|
||||||
|
}
|
||||||
60
OpenRA.FileFormats/Palette.cs
Normal file
60
OpenRA.FileFormats/Palette.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Palette
|
||||||
|
{
|
||||||
|
List<Color> colors = new List<Color>();
|
||||||
|
|
||||||
|
public Color GetColor(int index)
|
||||||
|
{
|
||||||
|
return colors[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Palette(Stream s)
|
||||||
|
{
|
||||||
|
using (BinaryReader reader = new BinaryReader(s))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
byte r = (byte)(reader.ReadByte() << 2);
|
||||||
|
byte g = (byte)(reader.ReadByte() << 2);
|
||||||
|
byte b = (byte)(reader.ReadByte() << 2);
|
||||||
|
|
||||||
|
colors.Add(Color.FromArgb(r, g, b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
colors[0] = Color.FromArgb(0, 0, 0, 0);
|
||||||
|
colors[3] = Color.FromArgb(178, 0, 0, 0);
|
||||||
|
colors[4] = Color.FromArgb(140, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Palette(Palette p, IPaletteRemap r)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
colors.Add(r.GetRemappedColor(p.GetColor(i), i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file
50
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class PlayerColorRemap : IPaletteRemap
|
||||||
|
{
|
||||||
|
Dictionary<int, Color> remapColors;
|
||||||
|
|
||||||
|
public PlayerColorRemap(Stream s)
|
||||||
|
{
|
||||||
|
var yaml = MiniYaml.FromStream(s);
|
||||||
|
remapColors = yaml.ToDictionary(
|
||||||
|
y => int.Parse(y.Key),
|
||||||
|
y => ArrayToColor((int[])FieldLoader.GetValue(
|
||||||
|
typeof(int[]), y.Value.Value.Trim())));
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2], x[3]); }
|
||||||
|
|
||||||
|
public Color GetRemappedColor(Color original, int index)
|
||||||
|
{
|
||||||
|
Color c;
|
||||||
|
return remapColors.TryGetValue(index, out c)
|
||||||
|
? c : original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
113
OpenRA.FileFormats/PriorityQueue.cs
Normal file
113
OpenRA.FileFormats/PriorityQueue.cs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class PriorityQueue<T>
|
||||||
|
where T : IComparable<T>
|
||||||
|
{
|
||||||
|
List<T[]> items = new List<T[]>();
|
||||||
|
int level, index;
|
||||||
|
|
||||||
|
public PriorityQueue()
|
||||||
|
{
|
||||||
|
items.Add(new T[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(T item)
|
||||||
|
{
|
||||||
|
int addLevel = level;
|
||||||
|
int addIndex = index;
|
||||||
|
|
||||||
|
while (addLevel >= 1 && Above(addLevel, addIndex).CompareTo(item) > 0)
|
||||||
|
{
|
||||||
|
items[addLevel][addIndex] = Above(addLevel, addIndex);
|
||||||
|
--addLevel;
|
||||||
|
addIndex >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
items[addLevel][addIndex] = item;
|
||||||
|
|
||||||
|
if (++index >= (1 << level))
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
if (items.Count <= ++level)
|
||||||
|
items.Add(new T[1 << level]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Empty { get { return (level == 0); } }
|
||||||
|
|
||||||
|
T At(int level, int index) { return items[level][index]; }
|
||||||
|
T Above(int level, int index) { return items[level - 1][index >> 1]; }
|
||||||
|
|
||||||
|
T Last()
|
||||||
|
{
|
||||||
|
int lastLevel = level;
|
||||||
|
int lastIndex = index;
|
||||||
|
|
||||||
|
if (--lastIndex < 0)
|
||||||
|
lastIndex = (1 << --lastLevel) - 1;
|
||||||
|
|
||||||
|
return At(lastLevel, lastIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Pop()
|
||||||
|
{
|
||||||
|
if (level == 0 && index == 0)
|
||||||
|
throw new InvalidOperationException("Attempting to pop empty PriorityQueue");
|
||||||
|
|
||||||
|
T ret = At(0, 0);
|
||||||
|
BubbleInto(0, 0, Last());
|
||||||
|
if (--index < 0)
|
||||||
|
index = (1 << --level) - 1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BubbleInto(int intoLevel, int intoIndex, T val)
|
||||||
|
{
|
||||||
|
int downLevel = intoLevel + 1;
|
||||||
|
int downIndex = intoIndex << 1;
|
||||||
|
|
||||||
|
if (downLevel > level || (downLevel == level && downIndex >= index))
|
||||||
|
{
|
||||||
|
items[intoLevel][intoIndex] = val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downLevel <= level && downIndex < index - 1 &&
|
||||||
|
At(downLevel, downIndex).CompareTo(At(downLevel, downIndex + 1)) >= 0)
|
||||||
|
++downIndex;
|
||||||
|
|
||||||
|
if (val.CompareTo(At(downLevel, downIndex)) <= 0)
|
||||||
|
{
|
||||||
|
items[intoLevel][intoIndex] = val;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
items[intoLevel][intoIndex] = At(downLevel, downIndex);
|
||||||
|
BubbleInto(downLevel, downIndex, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
OpenRA.FileFormats/Properties/AssemblyInfo.cs
Normal file
36
OpenRA.FileFormats/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("OpenRA.FileFormats")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("OpenRA.FileFormats")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2007,2009,2010")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
28
OpenRA.FileFormats/ProtocolVersion.cs
Normal file
28
OpenRA.FileFormats/ProtocolVersion.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public static class ProtocolVersion
|
||||||
|
{
|
||||||
|
// you *must* increment this whenever you make an incompatible protocol change
|
||||||
|
public static readonly int Version = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
84
OpenRA.FileFormats/Session.cs
Normal file
84
OpenRA.FileFormats/Session.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Session
|
||||||
|
{
|
||||||
|
public List<Client> Clients = new List<Client>();
|
||||||
|
public Global GlobalSettings = new Global();
|
||||||
|
|
||||||
|
public enum ClientState
|
||||||
|
{
|
||||||
|
NotReady,
|
||||||
|
Downloading,
|
||||||
|
Ready
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Client
|
||||||
|
{
|
||||||
|
public int Index;
|
||||||
|
public int PaletteIndex;
|
||||||
|
public string Country;
|
||||||
|
public int SpawnPoint;
|
||||||
|
public string Name;
|
||||||
|
public ClientState State;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Global
|
||||||
|
{
|
||||||
|
public string Map = "scm12ea.ini";
|
||||||
|
public string[] Packages = {}; // filename:sha1 pairs.
|
||||||
|
public string[] Mods = { "ra" }; // mod names
|
||||||
|
public int OrderLatency = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Manifest
|
||||||
|
{
|
||||||
|
public readonly string[] Folders = { };
|
||||||
|
public readonly string[] Packages = { };
|
||||||
|
public readonly string[] LegacyRules = { };
|
||||||
|
public readonly string[] Rules = { };
|
||||||
|
public readonly string[] Sequences = { };
|
||||||
|
public readonly string[] Chrome = { };
|
||||||
|
public readonly string[] Assemblies = { };
|
||||||
|
|
||||||
|
public Manifest(string[] mods)
|
||||||
|
{
|
||||||
|
var yaml = mods
|
||||||
|
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
|
||||||
|
.Aggregate(MiniYaml.Merge);
|
||||||
|
|
||||||
|
Folders = YamlList(yaml, "Folders");
|
||||||
|
Packages = YamlList(yaml, "Packages");
|
||||||
|
LegacyRules = YamlList(yaml, "LegacyRules");
|
||||||
|
Rules = YamlList(yaml, "Rules");
|
||||||
|
Sequences = YamlList(yaml, "Sequences");
|
||||||
|
Chrome = YamlList(yaml, "Chrome");
|
||||||
|
Assemblies = YamlList(yaml, "Assemblies");
|
||||||
|
}
|
||||||
|
|
||||||
|
static string[] YamlList(Dictionary<string, MiniYaml> ys, string key) { return ys[key].Nodes.Keys.ToArray(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
177
OpenRA.FileFormats/ShpReader.cs
Normal file
177
OpenRA.FileFormats/ShpReader.cs
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class ImageHeader
|
||||||
|
{
|
||||||
|
public uint Offset;
|
||||||
|
public Format Format;
|
||||||
|
|
||||||
|
public uint RefOffset;
|
||||||
|
public Format RefFormat;
|
||||||
|
public ImageHeader RefImage;
|
||||||
|
|
||||||
|
public byte[] Image;
|
||||||
|
|
||||||
|
public ImageHeader( BinaryReader reader )
|
||||||
|
{
|
||||||
|
Offset = reader.ReadUInt32();
|
||||||
|
Format = (Format)( Offset >> 24 );
|
||||||
|
Offset &= 0xFFFFFF;
|
||||||
|
|
||||||
|
RefOffset = reader.ReadUInt16();
|
||||||
|
RefFormat = (Format)reader.ReadUInt16();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Format
|
||||||
|
{
|
||||||
|
Format20 = 0x20,
|
||||||
|
Format40 = 0x40,
|
||||||
|
Format80 = 0x80,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShpReader : IEnumerable<ImageHeader>
|
||||||
|
{
|
||||||
|
public readonly int ImageCount;
|
||||||
|
public readonly ushort Width;
|
||||||
|
public readonly ushort Height;
|
||||||
|
|
||||||
|
public Size Size { get { return new Size(Width, Height); } }
|
||||||
|
|
||||||
|
private readonly List<ImageHeader> headers = new List<ImageHeader>();
|
||||||
|
|
||||||
|
int recurseDepth = 0;
|
||||||
|
|
||||||
|
public ShpReader( Stream stream )
|
||||||
|
{
|
||||||
|
BinaryReader reader = new BinaryReader( stream );
|
||||||
|
|
||||||
|
ImageCount = reader.ReadUInt16();
|
||||||
|
reader.ReadUInt16();
|
||||||
|
reader.ReadUInt16();
|
||||||
|
Width = reader.ReadUInt16();
|
||||||
|
Height = reader.ReadUInt16();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
|
||||||
|
for( int i = 0 ; i < ImageCount ; i++ )
|
||||||
|
headers.Add( new ImageHeader( reader ) );
|
||||||
|
|
||||||
|
new ImageHeader( reader ); // end-of-file header
|
||||||
|
new ImageHeader( reader ); // all-zeroes header
|
||||||
|
|
||||||
|
Dictionary<uint, ImageHeader> offsets = new Dictionary<uint, ImageHeader>();
|
||||||
|
foreach( ImageHeader h in headers )
|
||||||
|
offsets.Add( h.Offset, h );
|
||||||
|
|
||||||
|
for( int i = 0 ; i < ImageCount ; i++ )
|
||||||
|
{
|
||||||
|
ImageHeader h = headers[ i ];
|
||||||
|
if( h.Format == Format.Format20 )
|
||||||
|
h.RefImage = headers[ i - 1 ];
|
||||||
|
|
||||||
|
else if( h.Format == Format.Format40 )
|
||||||
|
{
|
||||||
|
if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) )
|
||||||
|
throw new InvalidDataException( string.Format( "Reference doesnt point to image data {0}->{1}", h.Offset, h.RefOffset ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach( ImageHeader h in headers )
|
||||||
|
Decompress( stream, h );
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageHeader this[ int index ]
|
||||||
|
{
|
||||||
|
get { return headers[ index ]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Decompress( Stream stream, ImageHeader h )
|
||||||
|
{
|
||||||
|
if( recurseDepth > ImageCount )
|
||||||
|
throw new InvalidDataException( "Format20/40 headers contain infinite loop" );
|
||||||
|
|
||||||
|
switch( h.Format )
|
||||||
|
{
|
||||||
|
case Format.Format20:
|
||||||
|
case Format.Format40:
|
||||||
|
{
|
||||||
|
if( h.RefImage.Image == null )
|
||||||
|
{
|
||||||
|
++recurseDepth;
|
||||||
|
Decompress( stream, h.RefImage );
|
||||||
|
--recurseDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
h.Image = CopyImageData( h.RefImage.Image );
|
||||||
|
Format40.DecodeInto(ReadCompressedData(stream, h), h.Image);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Format.Format80:
|
||||||
|
{
|
||||||
|
byte[] imageBytes = new byte[ Width * Height ];
|
||||||
|
Format80.DecodeInto( ReadCompressedData( stream, h ), imageBytes );
|
||||||
|
h.Image = imageBytes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new InvalidDataException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte[] ReadCompressedData( Stream stream, ImageHeader h )
|
||||||
|
{
|
||||||
|
stream.Position = h.Offset;
|
||||||
|
// Actually, far too big. There's no length field with the correct length though :(
|
||||||
|
int compressedLength = (int)( stream.Length - stream.Position );
|
||||||
|
|
||||||
|
byte[] compressedBytes = new byte[ compressedLength ];
|
||||||
|
stream.Read( compressedBytes, 0, compressedLength );
|
||||||
|
|
||||||
|
//MemoryStream ms = new MemoryStream( compressedBytes );
|
||||||
|
return compressedBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] CopyImageData( byte[] baseImage )
|
||||||
|
{
|
||||||
|
byte[] imageData = new byte[ Width * Height ];
|
||||||
|
for( int i = 0 ; i < Width * Height ; i++ )
|
||||||
|
imageData[ i ] = baseImage[ i ];
|
||||||
|
|
||||||
|
return imageData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<ImageHeader> GetEnumerator()
|
||||||
|
{
|
||||||
|
return headers.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
OpenRA.FileFormats/ShroudPaletteRemap.cs
Normal file
48
OpenRA.FileFormats/ShroudPaletteRemap.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class ShroudPaletteRemap : IPaletteRemap
|
||||||
|
{
|
||||||
|
public Color GetRemappedColor(Color original, int index)
|
||||||
|
{
|
||||||
|
// false-color version for debug
|
||||||
|
|
||||||
|
//return new[] {
|
||||||
|
// Color.FromArgb(64,0,0,0), Color.Green,
|
||||||
|
// Color.Blue, Color.Yellow,
|
||||||
|
// Color.Green,
|
||||||
|
// Color.Red,
|
||||||
|
// Color.Purple,
|
||||||
|
// Color.Cyan}[index % 8];
|
||||||
|
|
||||||
|
return new[] {
|
||||||
|
Color.Transparent, Color.Green,
|
||||||
|
Color.Blue, Color.Yellow,
|
||||||
|
Color.Black,
|
||||||
|
Color.FromArgb(192,0,0,0),
|
||||||
|
Color.FromArgb(128,0,0,0),
|
||||||
|
Color.FromArgb(64,0,0,0)}[index % 8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
OpenRA.FileFormats/SingleColorRemap.cs
Normal file
38
OpenRA.FileFormats/SingleColorRemap.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class SingleColorRemap : IPaletteRemap
|
||||||
|
{
|
||||||
|
Color c;
|
||||||
|
public SingleColorRemap(Color c)
|
||||||
|
{
|
||||||
|
this.c = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GetRemappedColor(Color original, int index)
|
||||||
|
{
|
||||||
|
return original.A > 0 ? c : original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
OpenRA.FileFormats/Support/Log.cs
Executable file
39
OpenRA.FileFormats/Support/Log.cs
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public static class Log
|
||||||
|
{
|
||||||
|
static StreamWriter writer = File.CreateText("log.txt");
|
||||||
|
|
||||||
|
static Log()
|
||||||
|
{
|
||||||
|
writer.AutoFlush = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(string format, params object[] args)
|
||||||
|
{
|
||||||
|
writer.WriteLine(format, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
OpenRA.FileFormats/Support/Stopwatch.cs
Executable file
42
OpenRA.FileFormats/Support/Stopwatch.cs
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using Tao.Sdl;
|
||||||
|
namespace OpenRA.Support
|
||||||
|
{
|
||||||
|
public class Stopwatch
|
||||||
|
{
|
||||||
|
int start;
|
||||||
|
public Stopwatch()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double ElapsedTime()
|
||||||
|
{
|
||||||
|
return (1.0/1000.0) * (double)(Sdl.SDL_GetTicks() - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
start = Sdl.SDL_GetTicks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
OpenRA.FileFormats/Support/Timer.cs
Executable file
35
OpenRA.FileFormats/Support/Timer.cs
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.Support
|
||||||
|
{
|
||||||
|
public static class Timer
|
||||||
|
{
|
||||||
|
static Stopwatch sw = new Stopwatch();
|
||||||
|
static double lastTime = 0;
|
||||||
|
|
||||||
|
public static void Time( string message )
|
||||||
|
{
|
||||||
|
var time = sw.ElapsedTime();
|
||||||
|
Log.Write( message, time - lastTime );
|
||||||
|
lastTime = time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
OpenRA.FileFormats/Terrain.cs
Normal file
67
OpenRA.FileFormats/Terrain.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Terrain
|
||||||
|
{
|
||||||
|
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
|
||||||
|
|
||||||
|
public Terrain( Stream stream )
|
||||||
|
{
|
||||||
|
int Width, Height;
|
||||||
|
|
||||||
|
BinaryReader reader = new BinaryReader( stream );
|
||||||
|
Width = reader.ReadUInt16();
|
||||||
|
Height = reader.ReadUInt16();
|
||||||
|
|
||||||
|
if( Width != 24 || Height != 24 )
|
||||||
|
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||||
|
|
||||||
|
/*NumTiles = */reader.ReadUInt16();
|
||||||
|
reader.ReadUInt16();
|
||||||
|
/*XDim = */reader.ReadUInt16();
|
||||||
|
/*YDim = */reader.ReadUInt16();
|
||||||
|
/*uint FileSize = */reader.ReadUInt32();
|
||||||
|
uint ImgStart = reader.ReadUInt32();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
int IndexEnd = reader.ReadInt32();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
int IndexStart = reader.ReadInt32();
|
||||||
|
|
||||||
|
stream.Position = IndexStart;
|
||||||
|
|
||||||
|
foreach( byte b in new BinaryReader(stream).ReadBytes(IndexEnd - IndexStart) )
|
||||||
|
{
|
||||||
|
if (b != 255)
|
||||||
|
{
|
||||||
|
stream.Position = ImgStart + b * 24 * 24;
|
||||||
|
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(24 * 24));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TileBitmapBytes.Add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
OpenRA.FileFormats/TileReference.cs
Normal file
45
OpenRA.FileFormats/TileReference.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public struct TileReference
|
||||||
|
{
|
||||||
|
public ushort tile;
|
||||||
|
public byte image;
|
||||||
|
public byte overlay;
|
||||||
|
public byte smudge;
|
||||||
|
public byte density; /* used for ore/gems */
|
||||||
|
|
||||||
|
public override int GetHashCode() { return tile.GetHashCode() ^ image.GetHashCode(); }
|
||||||
|
|
||||||
|
public override bool Equals( object obj )
|
||||||
|
{
|
||||||
|
if( obj == null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TileReference r = (TileReference)obj;
|
||||||
|
return ( r.image == image && r.tile == tile );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==( TileReference a, TileReference b ) { return a.Equals( b ); }
|
||||||
|
public static bool operator !=( TileReference a, TileReference b ) { return !a.Equals( b ); }
|
||||||
|
}
|
||||||
|
}
|
||||||
109
OpenRA.FileFormats/TileSet.cs
Normal file
109
OpenRA.FileFormats/TileSet.cs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class TileSet
|
||||||
|
{
|
||||||
|
public readonly Dictionary<ushort, Terrain> tiles = new Dictionary<ushort, Terrain>();
|
||||||
|
|
||||||
|
public readonly Walkability Walkability = new Walkability();
|
||||||
|
public readonly Dictionary<ushort, TileTemplate> walk
|
||||||
|
= new Dictionary<ushort, TileTemplate>();
|
||||||
|
|
||||||
|
string NextLine( StreamReader reader )
|
||||||
|
{
|
||||||
|
string ret;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = reader.ReadLine();
|
||||||
|
if( ret == null )
|
||||||
|
return null;
|
||||||
|
ret = ret.Trim();
|
||||||
|
}
|
||||||
|
while( ret.Length == 0 || ret[ 0 ] == ';' );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileSet( string suffix )
|
||||||
|
{
|
||||||
|
Walkability = new Walkability();
|
||||||
|
|
||||||
|
char tileSetChar = char.ToUpperInvariant( suffix[ 1 ] );
|
||||||
|
StreamReader tileIdFile = new StreamReader( FileSystem.Open( "tileSet.til" ) );
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
string tileSetStr = NextLine( tileIdFile );
|
||||||
|
string countStr = NextLine( tileIdFile );
|
||||||
|
string startStr = NextLine( tileIdFile );
|
||||||
|
string pattern = NextLine( tileIdFile );
|
||||||
|
if( tileSetStr == null || countStr == null || startStr == null || pattern == null )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( tileSetStr.IndexOf( tileSetChar.ToString() ) == -1 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int count = int.Parse( countStr );
|
||||||
|
int start = int.Parse( startStr, NumberStyles.HexNumber );
|
||||||
|
for( int i = 0 ; i < count ; i++ )
|
||||||
|
{
|
||||||
|
string tilename = string.Format(pattern, i + 1);
|
||||||
|
|
||||||
|
if (!walk.ContainsKey((ushort)(start + i)))
|
||||||
|
walk.Add((ushort)(start + i), Walkability.GetWalkability(tilename));
|
||||||
|
|
||||||
|
using( Stream s = FileSystem.Open( tilename + suffix ) )
|
||||||
|
{
|
||||||
|
if( !tiles.ContainsKey( (ushort)( start + i ) ) )
|
||||||
|
tiles.Add( (ushort)( start + i ), new Terrain( s ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tileIdFile.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] GetBytes(TileReference r)
|
||||||
|
{
|
||||||
|
Terrain tile;
|
||||||
|
if( tiles.TryGetValue( r.tile, out tile ) )
|
||||||
|
return tile.TileBitmapBytes[ r.image ];
|
||||||
|
|
||||||
|
byte[] missingTile = new byte[ 24 * 24 ];
|
||||||
|
for( int i = 0 ; i < missingTile.Length ; i++ )
|
||||||
|
missingTile[ i ] = 0x36;
|
||||||
|
|
||||||
|
return missingTile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetWalkability(TileReference r)
|
||||||
|
{
|
||||||
|
if (r.tile == 0xff || r.tile == 0xffff)
|
||||||
|
r.image = 0;
|
||||||
|
|
||||||
|
return walk[r.tile].TerrainType[r.image];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
OpenRA.FileFormats/TreeReference.cs
Normal file
40
OpenRA.FileFormats/TreeReference.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public struct TreeReference
|
||||||
|
{
|
||||||
|
public readonly int X;
|
||||||
|
public readonly int Y;
|
||||||
|
public readonly string Image;
|
||||||
|
|
||||||
|
public TreeReference(int xy, string image)
|
||||||
|
{
|
||||||
|
X = xy % 128;
|
||||||
|
Y = xy / 128;
|
||||||
|
Image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point Location { get { return new Point(X, Y); } }
|
||||||
|
}
|
||||||
|
}
|
||||||
39
OpenRA.FileFormats/Tuple.cs
Normal file
39
OpenRA.FileFormats/Tuple.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class Tuple<A, B, C>
|
||||||
|
{
|
||||||
|
public A a;
|
||||||
|
public B b;
|
||||||
|
public C c;
|
||||||
|
|
||||||
|
public Tuple(A a, B b, C c) { this.a = a; this.b = b; this.c = c; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Tuple
|
||||||
|
{
|
||||||
|
public static Tuple<A, B, C> New<A, B, C>(A a, B b, C c)
|
||||||
|
{
|
||||||
|
return new Tuple<A, B, C>(a, b, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
115
OpenRA.FileFormats/TypeDictionary.cs
Normal file
115
OpenRA.FileFormats/TypeDictionary.cs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class TypeDictionary
|
||||||
|
{
|
||||||
|
Dictionary<Type, object> dataSingular = new Dictionary<Type, object>();
|
||||||
|
Dictionary<Type, List<object>> dataMultiple = new Dictionary<Type, List<object>>();
|
||||||
|
|
||||||
|
public void Add( object val )
|
||||||
|
{
|
||||||
|
var t = val.GetType();
|
||||||
|
|
||||||
|
foreach( var i in t.GetInterfaces() )
|
||||||
|
InnerAdd( i, val );
|
||||||
|
foreach( var tt in t.BaseTypes() )
|
||||||
|
InnerAdd( tt, val );
|
||||||
|
}
|
||||||
|
|
||||||
|
void InnerAdd( Type t, object val )
|
||||||
|
{
|
||||||
|
List<object> objs;
|
||||||
|
object obj;
|
||||||
|
|
||||||
|
if( dataMultiple.TryGetValue( t, out objs ) )
|
||||||
|
objs.Add( val );
|
||||||
|
else if( dataSingular.TryGetValue( t, out obj ) )
|
||||||
|
{
|
||||||
|
dataSingular.Remove( t );
|
||||||
|
dataMultiple.Add( t, new List<object> { obj, val } );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dataSingular.Add( t, val );
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains<T>()
|
||||||
|
{
|
||||||
|
return dataSingular.ContainsKey( typeof( T ) ) || dataMultiple.ContainsKey( typeof( T ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Get<T>()
|
||||||
|
{
|
||||||
|
if( dataMultiple.ContainsKey( typeof( T ) ) )
|
||||||
|
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||||
|
|
||||||
|
object ret;
|
||||||
|
if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
|
||||||
|
throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T)));
|
||||||
|
return (T)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetOrDefault<T>()
|
||||||
|
{
|
||||||
|
if( dataMultiple.ContainsKey( typeof( T ) ) )
|
||||||
|
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||||
|
|
||||||
|
object ret;
|
||||||
|
if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
|
||||||
|
return default( T );
|
||||||
|
return (T)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<T> WithInterface<T>()
|
||||||
|
{
|
||||||
|
List<object> objs;
|
||||||
|
object obj;
|
||||||
|
|
||||||
|
if( dataMultiple.TryGetValue( typeof( T ), out objs ) )
|
||||||
|
return objs.Cast<T>();
|
||||||
|
else if( dataSingular.TryGetValue( typeof( T ), out obj ) )
|
||||||
|
return new T[] { (T)obj };
|
||||||
|
else
|
||||||
|
return new T[ 0 ];
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<object> GetEnumerator()
|
||||||
|
{
|
||||||
|
return WithInterface<object>().GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TypeExts
|
||||||
|
{
|
||||||
|
public static IEnumerable<Type> BaseTypes( this Type t )
|
||||||
|
{
|
||||||
|
while( t != null )
|
||||||
|
{
|
||||||
|
yield return t;
|
||||||
|
t = t.BaseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
OpenRA.FileFormats/Walkability.cs
Normal file
73
OpenRA.FileFormats/Walkability.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.FileFormats
|
||||||
|
{
|
||||||
|
public class TileTemplate
|
||||||
|
{
|
||||||
|
public int Index; // not valid for `interior` stuff. only used for bridges.
|
||||||
|
public string Name;
|
||||||
|
public int2 Size;
|
||||||
|
public string Bridge;
|
||||||
|
public float HP;
|
||||||
|
public Dictionary<int, int> TerrainType = new Dictionary<int, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Walkability
|
||||||
|
{
|
||||||
|
Dictionary<string, TileTemplate> walkability
|
||||||
|
= new Dictionary<string,TileTemplate>();
|
||||||
|
|
||||||
|
public Walkability()
|
||||||
|
{
|
||||||
|
var file = new IniFile( FileSystem.Open( "templates.ini" ) );
|
||||||
|
|
||||||
|
foreach (var section in file.Sections)
|
||||||
|
{
|
||||||
|
var tile = new TileTemplate
|
||||||
|
{
|
||||||
|
Size = new int2(
|
||||||
|
int.Parse(section.GetValue("width", "0")),
|
||||||
|
int.Parse(section.GetValue("height", "0"))),
|
||||||
|
TerrainType = section
|
||||||
|
.Where(p => p.Key.StartsWith("tiletype"))
|
||||||
|
.ToDictionary(
|
||||||
|
p => int.Parse(p.Key.Substring(8)),
|
||||||
|
p => int.Parse(p.Value)),
|
||||||
|
Name = section.GetValue("Name", null).ToLowerInvariant(),
|
||||||
|
Bridge = section.GetValue("bridge", null),
|
||||||
|
HP = float.Parse(section.GetValue("hp", "0"))
|
||||||
|
};
|
||||||
|
tile.Index = -1;
|
||||||
|
int.TryParse(section.Name.Substring(3), out tile.Index);
|
||||||
|
|
||||||
|
walkability[tile.Name] = tile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileTemplate GetWalkability(string terrainName)
|
||||||
|
{
|
||||||
|
return walkability[terrainName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
113
OpenRA.FileFormats/float2.cs
Normal file
113
OpenRA.FileFormats/float2.cs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct float2
|
||||||
|
{
|
||||||
|
public float X, Y;
|
||||||
|
|
||||||
|
public float2(float x, float y) { X = x; Y = y; }
|
||||||
|
public float2(PointF p) { X = p.X; Y = p.Y; }
|
||||||
|
public float2(Point p) { X = p.X; Y = p.Y; }
|
||||||
|
public float2(Size p) { X = p.Width; Y = p.Height; }
|
||||||
|
public float2(SizeF p) { X = p.Width; Y = p.Height; }
|
||||||
|
|
||||||
|
public PointF ToPointF() { return new PointF(X, Y); }
|
||||||
|
public SizeF ToSizeF() { return new SizeF(X, Y); }
|
||||||
|
|
||||||
|
public static implicit operator float2(int2 src) { return new float2(src.X, src.Y); }
|
||||||
|
|
||||||
|
public static float2 operator +(float2 a, float2 b) { return new float2(a.X + b.X, a.Y + b.Y); }
|
||||||
|
public static float2 operator -(float2 a, float2 b) { return new float2(a.X - b.X, a.Y - b.Y); }
|
||||||
|
|
||||||
|
public static float2 operator -(float2 a) { return new float2(-a.X, -a.Y); }
|
||||||
|
|
||||||
|
public static float Lerp(float a, float b, float t) { return a + t * (b - a); }
|
||||||
|
|
||||||
|
public static float2 Lerp(float2 a, float2 b, float t)
|
||||||
|
{
|
||||||
|
return new float2(
|
||||||
|
Lerp(a.X, b.X, t),
|
||||||
|
Lerp(a.Y, b.Y, t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float2 Lerp(float2 a, float2 b, float2 t)
|
||||||
|
{
|
||||||
|
return new float2(
|
||||||
|
Lerp(a.X, b.X, t.X),
|
||||||
|
Lerp(a.Y, b.Y, t.Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float2 FromAngle(float a) { return new float2((float)Math.Sin(a), (float)Math.Cos(a)); }
|
||||||
|
|
||||||
|
static float Constrain(float x, float a, float b) { return x < a ? a : x > b ? b : x; }
|
||||||
|
|
||||||
|
public float2 Constrain(float2 min, float2 max)
|
||||||
|
{
|
||||||
|
return new float2(
|
||||||
|
Constrain(X, min.X, max.X),
|
||||||
|
Constrain(Y, min.Y, max.Y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
|
||||||
|
public static float2 operator *( float2 a, float2 b ) { return new float2( a.X * b.X, a.Y * b.Y ); }
|
||||||
|
public static float2 operator /( float2 a, float2 b ) { return new float2( a.X / b.X, a.Y / b.Y ); }
|
||||||
|
|
||||||
|
public static bool operator ==(float2 me, float2 other) { return (me.X == other.X && me.Y == other.Y); }
|
||||||
|
public static bool operator !=(float2 me, float2 other) { return !(me == other); }
|
||||||
|
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float2 o = (float2)obj;
|
||||||
|
return o == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly float2 Zero = new float2(0, 0);
|
||||||
|
|
||||||
|
public static bool WithinEpsilon(float2 a, float2 b, float e)
|
||||||
|
{
|
||||||
|
float2 d = a - b;
|
||||||
|
return Math.Abs(d.X) < e && Math.Abs(d.Y) < e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2 Sign() { return new float2(Math.Sign(X), Math.Sign(Y)); }
|
||||||
|
public static float Dot(float2 a, float2 b) { return a.X * b.X + a.Y * b.Y; }
|
||||||
|
public float2 Round() { return new float2((float)Math.Round(X), (float)Math.Round(Y)); }
|
||||||
|
|
||||||
|
public override string ToString() { return string.Format("({0},{1})", X, Y); }
|
||||||
|
public int2 ToInt2() { return new int2((int)X, (int)Y); }
|
||||||
|
|
||||||
|
public static float2 Max(float2 a, float2 b) { return new float2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
|
||||||
|
public static float2 Min(float2 a, float2 b) { return new float2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
|
||||||
|
|
||||||
|
public float LengthSquared { get { return X * X + Y * Y; } }
|
||||||
|
public float Length { get { return (float)Math.Sqrt(LengthSquared); } }
|
||||||
|
}
|
||||||
|
}
|
||||||
67
OpenRA.FileFormats/int2.cs
Normal file
67
OpenRA.FileFormats/int2.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public struct int2
|
||||||
|
{
|
||||||
|
public int X,Y;
|
||||||
|
|
||||||
|
public int2( int x, int y ) { this.X = x; this.Y = y; }
|
||||||
|
public int2( Point p ) { X = p.X; Y = p.Y; }
|
||||||
|
public int2( Size p ) { X = p.Width; Y = p.Height; }
|
||||||
|
|
||||||
|
public static int2 operator +(int2 a, int2 b) { return new int2(a.X + b.X, a.Y + b.Y); }
|
||||||
|
public static int2 operator -(int2 a, int2 b) { return new int2(a.X - b.X, a.Y - b.Y); }
|
||||||
|
public static int2 operator *(int a, int2 b) { return new int2(a * b.X, a * b.Y); }
|
||||||
|
public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); }
|
||||||
|
|
||||||
|
public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); }
|
||||||
|
public static bool operator !=(int2 me, int2 other) { return !(me == other); }
|
||||||
|
|
||||||
|
public int2 Sign() { return new int2(Math.Sign(X), Math.Sign(Y)); }
|
||||||
|
public int2 Abs() { return new int2( Math.Abs( X ), Math.Abs( Y ) ); }
|
||||||
|
public int LengthSquared { get { return X * X + Y * Y; } }
|
||||||
|
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
|
||||||
|
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
|
||||||
|
|
||||||
|
public static int2 Max(int2 a, int2 b) { return new int2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
|
||||||
|
public static int2 Min(int2 a, int2 b) { return new int2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int2 o = (int2)obj;
|
||||||
|
return o == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly int2 Zero = new int2(0, 0);
|
||||||
|
public Point ToPoint() { return new Point(X, Y); }
|
||||||
|
public PointF ToPointF() { return new PointF(X, Y); }
|
||||||
|
public float2 ToFloat2() { return new float2(X, Y); }
|
||||||
|
|
||||||
|
public override string ToString() { return string.Format("({0},{1})", X, Y); }
|
||||||
|
}
|
||||||
|
}
|
||||||
238
OpenRA.Game/Actor.cs
Executable file
238
OpenRA.Game/Actor.cs
Executable file
@@ -0,0 +1,238 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using OpenRA.Traits.Activities;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public class Actor
|
||||||
|
{
|
||||||
|
[Sync]
|
||||||
|
public readonly TypeDictionary traits = new TypeDictionary();
|
||||||
|
public readonly ActorInfo Info;
|
||||||
|
|
||||||
|
public readonly World World;
|
||||||
|
public readonly uint ActorID;
|
||||||
|
|
||||||
|
[Sync]
|
||||||
|
public int2 Location;
|
||||||
|
[Sync]
|
||||||
|
public Player Owner;
|
||||||
|
[Sync]
|
||||||
|
public int Health;
|
||||||
|
IActivity currentActivity;
|
||||||
|
|
||||||
|
public Actor( World world, string name, int2 location, Player owner )
|
||||||
|
{
|
||||||
|
World = world;
|
||||||
|
ActorID = world.NextAID();
|
||||||
|
Location = location;
|
||||||
|
CenterLocation = Traits.Util.CenterOfCell(Location);
|
||||||
|
Owner = owner;
|
||||||
|
|
||||||
|
if (name != null)
|
||||||
|
{
|
||||||
|
//Log.Write("Loading {0}",name.ToLowerInvariant());
|
||||||
|
Info = Rules.Info[name.ToLowerInvariant()];
|
||||||
|
Health = this.GetMaxHP();
|
||||||
|
|
||||||
|
foreach (var trait in Info.TraitsInConstructOrder())
|
||||||
|
traits.Add(trait.Create(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
while (currentActivity != null)
|
||||||
|
{
|
||||||
|
var a = currentActivity;
|
||||||
|
currentActivity = a.Tick(this) ?? new Idle();
|
||||||
|
if (a == currentActivity || currentActivity is Idle) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsIdle
|
||||||
|
{
|
||||||
|
get { return currentActivity == null || currentActivity is Idle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2 CenterLocation;
|
||||||
|
float2 SelectedSize
|
||||||
|
{
|
||||||
|
get // todo: inline into GetBounds
|
||||||
|
{
|
||||||
|
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||||
|
if (si != null && si.Bounds != null)
|
||||||
|
return new float2(si.Bounds[0], si.Bounds[1]);
|
||||||
|
|
||||||
|
var firstSprite = Render().FirstOrDefault();
|
||||||
|
if (firstSprite.Sprite == null) return float2.Zero;
|
||||||
|
return firstSprite.Sprite.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
var mods = traits.WithInterface<IRenderModifier>();
|
||||||
|
var sprites = traits.WithInterface<IRender>().SelectMany(x => x.Render(this));
|
||||||
|
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order Order( int2 xy, MouseInput mi )
|
||||||
|
{
|
||||||
|
if (Owner != World.LocalPlayer)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!World.Map.IsInMap(xy.X, xy.Y))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var underCursor = World.FindUnitsAtMouse(mi.Location).FirstOrDefault();
|
||||||
|
|
||||||
|
if (underCursor != null && !underCursor.traits.Contains<Selectable>())
|
||||||
|
underCursor = null;
|
||||||
|
|
||||||
|
return traits.WithInterface<IIssueOrder>()
|
||||||
|
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
|
||||||
|
.FirstOrDefault( x => x != null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public RectangleF GetBounds(bool useAltitude)
|
||||||
|
{
|
||||||
|
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||||
|
|
||||||
|
var size = SelectedSize;
|
||||||
|
var loc = CenterLocation - 0.5f * size;
|
||||||
|
|
||||||
|
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
|
||||||
|
loc += new float2(si.Bounds[2], si.Bounds[3]);
|
||||||
|
|
||||||
|
if (useAltitude)
|
||||||
|
{
|
||||||
|
var unit = traits.GetOrDefault<Unit>();
|
||||||
|
if (unit != null) loc -= new float2(0, unit.Altitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDead { get { return Health <= 0; } }
|
||||||
|
public bool IsInWorld { get; set; }
|
||||||
|
public bool RemoveOnDeath = true;
|
||||||
|
|
||||||
|
public DamageState GetDamageState()
|
||||||
|
{
|
||||||
|
if (Health <= 0)
|
||||||
|
return DamageState.Dead;
|
||||||
|
|
||||||
|
if (Health < this.GetMaxHP() * Rules.General.ConditionRed)
|
||||||
|
return DamageState.Quarter;
|
||||||
|
|
||||||
|
if (Health < this.GetMaxHP() * Rules.General.ConditionYellow)
|
||||||
|
return DamageState.Half;
|
||||||
|
|
||||||
|
if (Health < this.GetMaxHP() * 0.75)
|
||||||
|
return DamageState.ThreeQuarter;
|
||||||
|
|
||||||
|
return DamageState.Normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InflictDamage(Actor attacker, int damage, WarheadInfo warhead)
|
||||||
|
{
|
||||||
|
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
|
||||||
|
|
||||||
|
var oldState = GetDamageState();
|
||||||
|
|
||||||
|
/* apply the damage modifiers, if we have any. */
|
||||||
|
damage = (int)traits.WithInterface<IDamageModifier>().Aggregate(
|
||||||
|
(float)damage, (a, t) => t.GetDamageModifier() * a);
|
||||||
|
|
||||||
|
Health -= damage;
|
||||||
|
if (Health <= 0)
|
||||||
|
{
|
||||||
|
Health = 0;
|
||||||
|
if (attacker.Owner != null)
|
||||||
|
attacker.Owner.Kills++;
|
||||||
|
|
||||||
|
if (RemoveOnDeath)
|
||||||
|
World.AddFrameEndTask(w => w.Remove(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxHP = this.GetMaxHP();
|
||||||
|
|
||||||
|
if (Health > maxHP) Health = maxHP;
|
||||||
|
|
||||||
|
var newState = GetDamageState();
|
||||||
|
|
||||||
|
foreach (var nd in traits.WithInterface<INotifyDamage>())
|
||||||
|
nd.Damaged(this, new AttackInfo
|
||||||
|
{
|
||||||
|
Attacker = attacker,
|
||||||
|
Damage = damage,
|
||||||
|
DamageState = newState,
|
||||||
|
DamageStateChanged = newState != oldState,
|
||||||
|
Warhead = warhead
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void QueueActivity( IActivity nextActivity )
|
||||||
|
{
|
||||||
|
if( currentActivity == null )
|
||||||
|
{
|
||||||
|
currentActivity = nextActivity;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var act = currentActivity;
|
||||||
|
while( act.NextActivity != null )
|
||||||
|
{
|
||||||
|
act = act.NextActivity;
|
||||||
|
}
|
||||||
|
act.NextActivity = nextActivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CancelActivity()
|
||||||
|
{
|
||||||
|
if( currentActivity != null )
|
||||||
|
currentActivity.Cancel( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
// For pathdebug, et al
|
||||||
|
public IActivity GetCurrentActivity()
|
||||||
|
{
|
||||||
|
return currentActivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return (int)ActorID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals( object obj )
|
||||||
|
{
|
||||||
|
var o = obj as Actor;
|
||||||
|
return ( o != null && o.ActorID == ActorID );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
77
OpenRA.Game/Chat.cs
Normal file
77
OpenRA.Game/Chat.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
class Chat
|
||||||
|
{
|
||||||
|
const int logLength = 10;
|
||||||
|
|
||||||
|
public List<Tuple<Color, string, string>> recentLines = new List<Tuple<Color, string, string>>();
|
||||||
|
public string typing = "";
|
||||||
|
public bool isChatting = true;
|
||||||
|
|
||||||
|
public void Toggle()
|
||||||
|
{
|
||||||
|
if( isChatting && typing.Length > 0 )
|
||||||
|
Game.IssueOrder( Order.Chat( typing ) );
|
||||||
|
|
||||||
|
typing = "";
|
||||||
|
if( Game.orderManager.GameStarted )
|
||||||
|
isChatting ^= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
typing = "";
|
||||||
|
isChatting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TypeChar(char c)
|
||||||
|
{
|
||||||
|
if (c == '\b')
|
||||||
|
{
|
||||||
|
if (typing.Length > 0)
|
||||||
|
typing = typing.Remove(typing.Length - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
typing += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddLine(Player p, string text)
|
||||||
|
{
|
||||||
|
AddLine(p.Color, p.PlayerName, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddLine(Color c, string from, string text)
|
||||||
|
{
|
||||||
|
Log.Write( "Chat: {0}: {1}", from, text );
|
||||||
|
recentLines.Add(Tuple.New(c, from, text));
|
||||||
|
var eva = Game.world.LocalPlayer.PlayerActor.Info.Traits.Get<EvaAlertsInfo>();
|
||||||
|
Sound.Play(eva.ChatBeep);
|
||||||
|
while (recentLines.Count > logLength) recentLines.RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1214
OpenRA.Game/Chrome.cs
Normal file
1214
OpenRA.Game/Chrome.cs
Normal file
File diff suppressed because it is too large
Load Diff
114
OpenRA.Game/Combat.cs
Normal file
114
OpenRA.Game/Combat.cs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Effects;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
static class Combat /* some utility bits that are shared between various things */
|
||||||
|
{
|
||||||
|
public static void DoImpact(int2 loc, int2 visualLoc,
|
||||||
|
WeaponInfo weapon, ProjectileInfo projectile, WarheadInfo warhead, Actor firedBy)
|
||||||
|
{
|
||||||
|
var world = firedBy.World;
|
||||||
|
|
||||||
|
var targetTile = ((1f / Game.CellSize) * loc.ToFloat2()).ToInt2();
|
||||||
|
|
||||||
|
var isWater = world.IsWater(targetTile);
|
||||||
|
var hitWater = world.IsCellBuildable(targetTile, UnitMovementType.Float);
|
||||||
|
|
||||||
|
if (warhead.Explosion != 0)
|
||||||
|
world.AddFrameEndTask(
|
||||||
|
w => w.Add(new Explosion(w, visualLoc, warhead.Explosion, hitWater)));
|
||||||
|
|
||||||
|
var impactSound = warhead.ImpactSound;
|
||||||
|
if (hitWater && warhead.WaterImpactSound != null)
|
||||||
|
impactSound = warhead.WaterImpactSound;
|
||||||
|
if (impactSound != null) Sound.Play(impactSound + ".aud");
|
||||||
|
|
||||||
|
if (!isWater) world.Map.AddSmudge(targetTile, warhead);
|
||||||
|
if (warhead.Ore) world.Map.DestroyOre(targetTile.X, targetTile.Y);
|
||||||
|
|
||||||
|
var firepowerModifier = firedBy.traits
|
||||||
|
.WithInterface<IFirepowerModifier>()
|
||||||
|
.Select(a => a.GetFirepowerModifier())
|
||||||
|
.Product();
|
||||||
|
|
||||||
|
var maxSpread = GetMaximumSpread(weapon, warhead, firepowerModifier);
|
||||||
|
var hitActors = world.FindUnitsInCircle(loc, maxSpread);
|
||||||
|
|
||||||
|
foreach (var victim in hitActors)
|
||||||
|
victim.InflictDamage(firedBy,
|
||||||
|
(int)GetDamageToInflict(victim, loc, weapon, warhead, firepowerModifier), warhead);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float GetMaximumSpread(WeaponInfo weapon, WarheadInfo warhead, float modifier)
|
||||||
|
{
|
||||||
|
return (int)(warhead.Spread * Math.Log(Math.Abs(weapon.Damage * modifier), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static float GetDamageToInflict(Actor target, int2 loc, WeaponInfo weapon, WarheadInfo warhead, float modifier)
|
||||||
|
{
|
||||||
|
if (!WeaponValidForTarget(weapon, target))
|
||||||
|
return 0f;
|
||||||
|
|
||||||
|
var distance = (target.CenterLocation - loc).Length*1/24f;
|
||||||
|
var rawDamage = weapon.Damage * modifier * (float)Math.Exp(-distance / warhead.Spread);
|
||||||
|
var multiplier = warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor);
|
||||||
|
return rawDamage * multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool WeaponValidForTarget(WeaponInfo weapon, Actor target)
|
||||||
|
{
|
||||||
|
var projectile = Rules.ProjectileInfo[weapon.Projectile];
|
||||||
|
var warhead = Rules.WarheadInfo[weapon.Warhead];
|
||||||
|
var unit = target.traits.GetOrDefault<Unit>();
|
||||||
|
|
||||||
|
if (warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor) <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (target.traits.Contains<Submarine>())
|
||||||
|
return projectile.ASW;
|
||||||
|
|
||||||
|
if (unit != null && unit.Altitude > 0)
|
||||||
|
return projectile.AA;
|
||||||
|
|
||||||
|
if (projectile.UnderWater && !target.Info.Traits.Get<OwnedActorInfo>().WaterBound)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return projectile.AG;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasAnyValidWeapons(Actor self, Actor target)
|
||||||
|
{
|
||||||
|
var info = self.Info.Traits.Get<AttackBaseInfo>();
|
||||||
|
if (info.PrimaryWeapon != null &&
|
||||||
|
WeaponValidForTarget(self.GetPrimaryWeapon(), target)) return true;
|
||||||
|
if (info.SecondaryWeapon != null &&
|
||||||
|
WeaponValidForTarget(self.GetSecondaryWeapon(), target)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
146
OpenRA.Game/Controller.cs
Normal file
146
OpenRA.Game/Controller.cs
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Orders;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public class Controller : IHandleInput
|
||||||
|
{
|
||||||
|
public IOrderGenerator orderGenerator = new UnitOrderGenerator();
|
||||||
|
public Selection selection = new Selection();
|
||||||
|
|
||||||
|
public void CancelInputMode() { orderGenerator = new UnitOrderGenerator(); }
|
||||||
|
|
||||||
|
public bool ToggleInputMode<T>() where T : IOrderGenerator, new()
|
||||||
|
{
|
||||||
|
if (orderGenerator is T)
|
||||||
|
{
|
||||||
|
CancelInputMode();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
orderGenerator = new T();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyOrders(World world, float2 xy, MouseInput mi)
|
||||||
|
{
|
||||||
|
if (orderGenerator == null) return;
|
||||||
|
|
||||||
|
var orders = orderGenerator.Order(world, xy.ToInt2(), mi).ToArray();
|
||||||
|
Game.orderManager.IssueOrders( orders );
|
||||||
|
|
||||||
|
var voicedActor = orders.Select(o => o.Subject)
|
||||||
|
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.traits.Contains<Unit>());
|
||||||
|
|
||||||
|
var isMove = orders.Any(o => o.OrderString == "Move");
|
||||||
|
var isAttack = orders.Any( o => o.OrderString == "Attack" );
|
||||||
|
|
||||||
|
if (voicedActor != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(voicedActor.traits.GetOrDefault<IMovement>().CanEnterCell(xy.ToInt2()))
|
||||||
|
Sound.PlayVoice(isAttack ? "Attack" : "Move", voicedActor);
|
||||||
|
|
||||||
|
if (isMove)
|
||||||
|
world.Add(new Effects.MoveFlash(world, Game.CellSize * xy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float2 dragStart, dragEnd;
|
||||||
|
public bool HandleInput(World world, MouseInput mi)
|
||||||
|
{
|
||||||
|
var xy = Game.viewport.ViewToWorld(mi);
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
|
||||||
|
{
|
||||||
|
if (!(orderGenerator is PlaceBuildingOrderGenerator))
|
||||||
|
dragStart = dragEnd = xy;
|
||||||
|
ApplyOrders(world, xy, mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Move)
|
||||||
|
dragEnd = xy;
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up)
|
||||||
|
{
|
||||||
|
if (orderGenerator is UnitOrderGenerator)
|
||||||
|
{
|
||||||
|
var newSelection = world.SelectActorsInBox(Game.CellSize * dragStart, Game.CellSize * xy);
|
||||||
|
selection.Combine(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
|
||||||
|
}
|
||||||
|
|
||||||
|
dragStart = dragEnd = xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.None && mi.Event == MouseInputEvent.Move)
|
||||||
|
dragStart = dragEnd = xy;
|
||||||
|
|
||||||
|
if (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Down)
|
||||||
|
ApplyOrders(world, xy, mi);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<float2, float2>? SelectionBox
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (dragStart == dragEnd) return null;
|
||||||
|
return Pair.New(Game.CellSize * dragStart, Game.CellSize * dragEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2 MousePosition { get { return dragEnd; } }
|
||||||
|
Modifiers modifiers;
|
||||||
|
|
||||||
|
public string ChooseCursor( World world )
|
||||||
|
{
|
||||||
|
int sync = world.SyncHash();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var mi = new MouseInput
|
||||||
|
{
|
||||||
|
Location = ( Game.CellSize * MousePosition - Game.viewport.Location ).ToInt2(),
|
||||||
|
Button = MouseButton.Right,
|
||||||
|
Modifiers = modifiers
|
||||||
|
};
|
||||||
|
|
||||||
|
return orderGenerator.GetCursor( world, MousePosition.ToInt2(), mi );
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if( sync != world.SyncHash() )
|
||||||
|
throw new InvalidOperationException( "Desync in Controller.ChooseCursor" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetModifiers(Modifiers mods) { modifiers = mods; }
|
||||||
|
}
|
||||||
|
}
|
||||||
36
OpenRA.Game/Cursor.cs
Normal file
36
OpenRA.Game/Cursor.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public class Cursor
|
||||||
|
{
|
||||||
|
CursorSequence sequence;
|
||||||
|
public Cursor(string cursor)
|
||||||
|
{
|
||||||
|
sequence = SequenceProvider.GetCursorSequence(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite GetSprite(int frame) { return sequence.GetSprite(frame); }
|
||||||
|
public int2 GetHotspot() { return sequence.Hotspot; }
|
||||||
|
}
|
||||||
|
}
|
||||||
133
OpenRA.Game/Effects/Bullet.cs
Executable file
133
OpenRA.Game/Effects/Bullet.cs
Executable file
@@ -0,0 +1,133 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
public class Bullet : IEffect
|
||||||
|
{
|
||||||
|
readonly Player Owner;
|
||||||
|
readonly Actor FiredBy;
|
||||||
|
readonly WeaponInfo Weapon;
|
||||||
|
readonly ProjectileInfo Projectile;
|
||||||
|
readonly WarheadInfo Warhead;
|
||||||
|
readonly int2 Src;
|
||||||
|
readonly int2 Dest;
|
||||||
|
readonly int2 VisualDest;
|
||||||
|
readonly int SrcAltitude;
|
||||||
|
readonly int DestAltitude;
|
||||||
|
|
||||||
|
int t = 0;
|
||||||
|
Animation anim;
|
||||||
|
|
||||||
|
const int BaseBulletSpeed = 100; /* pixels / 40ms frame */
|
||||||
|
|
||||||
|
public Bullet(string weapon, Player owner, Actor firedBy,
|
||||||
|
int2 src, int2 dest, int srcAltitude, int destAltitude)
|
||||||
|
: this(Rules.WeaponInfo[weapon], owner, firedBy, src, dest, srcAltitude, destAltitude) { }
|
||||||
|
|
||||||
|
/* src, dest are *pixel* coords */
|
||||||
|
public Bullet(WeaponInfo weapon, Player owner, Actor firedBy,
|
||||||
|
int2 src, int2 dest, int srcAltitude, int destAltitude)
|
||||||
|
{
|
||||||
|
Owner = owner;
|
||||||
|
FiredBy = firedBy;
|
||||||
|
Src = src;
|
||||||
|
Dest = dest;
|
||||||
|
SrcAltitude = srcAltitude;
|
||||||
|
DestAltitude = destAltitude;
|
||||||
|
VisualDest = Dest + new int2(
|
||||||
|
firedBy.World.CosmeticRandom.Next(-10, 10),
|
||||||
|
firedBy.World.CosmeticRandom.Next(-10, 10));
|
||||||
|
Weapon = weapon;
|
||||||
|
Projectile = Rules.ProjectileInfo[Weapon.Projectile];
|
||||||
|
Warhead = Rules.WarheadInfo[Weapon.Warhead];
|
||||||
|
|
||||||
|
if (Projectile.Image != null && Projectile.Image != "none")
|
||||||
|
{
|
||||||
|
if (Projectile.Rotates)
|
||||||
|
anim = new Animation(Projectile.Image, () => Traits.Util.GetFacing((dest - src).ToFloat2(), 0));
|
||||||
|
else
|
||||||
|
anim = new Animation(Projectile.Image);
|
||||||
|
|
||||||
|
anim.PlayRepeating("idle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int TotalTime() { return (Dest - Src).Length * BaseBulletSpeed / Weapon.Speed; }
|
||||||
|
|
||||||
|
public void Tick( World world )
|
||||||
|
{
|
||||||
|
t += 40;
|
||||||
|
|
||||||
|
if (t > TotalTime()) /* remove finished bullets */
|
||||||
|
{
|
||||||
|
world.AddFrameEndTask(w => w.Remove(this));
|
||||||
|
Combat.DoImpact(Dest, VisualDest - new int2( 0, DestAltitude ),
|
||||||
|
Weapon, Projectile, Warhead, FiredBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Projectile.Trail != null)
|
||||||
|
{
|
||||||
|
var at = (float)t / TotalTime();
|
||||||
|
var altitude = float2.Lerp(SrcAltitude, DestAltitude, at);
|
||||||
|
var pos = float2.Lerp(Src.ToFloat2(), VisualDest.ToFloat2(), at)
|
||||||
|
- 0.5f * anim.Image.size - new float2(0, altitude);
|
||||||
|
|
||||||
|
var highPos = (Projectile.High || Projectile.Arcing)
|
||||||
|
? (pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at)))
|
||||||
|
: pos;
|
||||||
|
|
||||||
|
world.AddFrameEndTask(w => w.Add(
|
||||||
|
new Smoke(w, highPos.ToInt2(), Projectile.Trail)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const float height = .1f;
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
if (anim != null)
|
||||||
|
{
|
||||||
|
var at = (float)t / TotalTime();
|
||||||
|
|
||||||
|
var altitude = float2.Lerp(SrcAltitude, DestAltitude, at);
|
||||||
|
var pos = float2.Lerp( Src.ToFloat2(), VisualDest.ToFloat2(), at)
|
||||||
|
- 0.5f * anim.Image.size - new float2( 0, altitude );
|
||||||
|
|
||||||
|
if (Projectile.High || Projectile.Arcing)
|
||||||
|
{
|
||||||
|
if (Projectile.Shadow)
|
||||||
|
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow");
|
||||||
|
|
||||||
|
var highPos = pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at));
|
||||||
|
|
||||||
|
yield return new Renderable(anim.Image, highPos - .5f * anim.Image.size, Owner.Palette);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, Projectile.UnderWater ? "shadow" : Owner.Palette);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
OpenRA.Game/Effects/Corpse.cs
Executable file
50
OpenRA.Game/Effects/Corpse.cs
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class Corpse : IEffect
|
||||||
|
{
|
||||||
|
readonly Animation anim;
|
||||||
|
readonly float2 pos;
|
||||||
|
readonly Player owner;
|
||||||
|
|
||||||
|
public Corpse(Actor fromActor, int death)
|
||||||
|
{
|
||||||
|
anim = new Animation(fromActor.traits.GetOrDefault<RenderSimple>().GetImage(fromActor));
|
||||||
|
anim.PlayThen("die{0}".F(death + 1),
|
||||||
|
() => fromActor.World.AddFrameEndTask(w => w.Remove(this)));
|
||||||
|
|
||||||
|
pos = fromActor.CenterLocation;
|
||||||
|
owner = fromActor.Owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick( World world ) { anim.Tick(); }
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, owner.Palette);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
OpenRA.Game/Effects/DelayedAction.cs
Executable file
46
OpenRA.Game/Effects/DelayedAction.cs
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
public class DelayedAction : IEffect
|
||||||
|
{
|
||||||
|
Action a;
|
||||||
|
int delay;
|
||||||
|
|
||||||
|
public DelayedAction(int delay, Action a)
|
||||||
|
{
|
||||||
|
this.a = a;
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick( World world )
|
||||||
|
{
|
||||||
|
if (--delay <= 0)
|
||||||
|
world.AddFrameEndTask(w => { w.Remove(this); a(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render() { yield break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
50
OpenRA.Game/Effects/Explosion.cs
Executable file
50
OpenRA.Game/Effects/Explosion.cs
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
public class Explosion : IEffect
|
||||||
|
{
|
||||||
|
Animation anim;
|
||||||
|
int2 pos;
|
||||||
|
|
||||||
|
public Explosion( World world, int2 pixelPos, int style, bool isWater)
|
||||||
|
{
|
||||||
|
this.pos = pixelPos;
|
||||||
|
var variantSuffix = isWater ? "w" : "";
|
||||||
|
anim = new Animation("explosion");
|
||||||
|
anim.PlayThen(style.ToString() + variantSuffix,
|
||||||
|
() => world.AddFrameEndTask(w => w.Remove(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick( World world ) { anim.Tick(); }
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "effect");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player Owner { get { return null; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
52
OpenRA.Game/Effects/FlashTarget.cs
Executable file
52
OpenRA.Game/Effects/FlashTarget.cs
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class FlashTarget : IEffect
|
||||||
|
{
|
||||||
|
Actor target;
|
||||||
|
int remainingTicks = 4;
|
||||||
|
|
||||||
|
public FlashTarget(Actor target)
|
||||||
|
{
|
||||||
|
this.target = target;
|
||||||
|
foreach (var e in target.World.Effects.OfType<FlashTarget>().Where(a => a.target == target).ToArray())
|
||||||
|
target.World.Remove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick( World world )
|
||||||
|
{
|
||||||
|
if (--remainingTicks == 0)
|
||||||
|
world.AddFrameEndTask(w => w.Remove(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
if (remainingTicks % 2 == 0)
|
||||||
|
foreach (var r in target.Render())
|
||||||
|
yield return r.WithPalette("highlight");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
OpenRA.Game/Effects/IEffect.cs
Executable file
31
OpenRA.Game/Effects/IEffect.cs
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
public interface IEffect
|
||||||
|
{
|
||||||
|
void Tick( World world );
|
||||||
|
IEnumerable<Renderable> Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
64
OpenRA.Game/Effects/LaserZap.cs
Normal file
64
OpenRA.Game/Effects/LaserZap.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class LaserZap : IEffect
|
||||||
|
{
|
||||||
|
readonly int2 from, to;
|
||||||
|
readonly int radius;
|
||||||
|
int timeUntilRemove = 10; // # of frames
|
||||||
|
int totalTime = 10;
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
public LaserZap(int2 from, int2 to, int radius, Color color)
|
||||||
|
{
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.color = color;
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick(World world)
|
||||||
|
{
|
||||||
|
if (timeUntilRemove <= 0)
|
||||||
|
world.AddFrameEndTask(w => w.Remove(this));
|
||||||
|
--timeUntilRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
int alpha = (int)((1-(float)(totalTime-timeUntilRemove)/totalTime)*255);
|
||||||
|
Color rc = Color.FromArgb(alpha,color);
|
||||||
|
|
||||||
|
float2 unit = 1.0f/(from - to).Length*(from - to).ToFloat2();
|
||||||
|
float2 norm = new float2(-unit.Y, unit.X);
|
||||||
|
|
||||||
|
for (int i = -radius; i < radius; i++)
|
||||||
|
Game.world.WorldRenderer.lineRenderer.DrawLine(from + i * norm, to + i * norm, rc, rc);
|
||||||
|
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
OpenRA.Game/Effects/Missile.cs
Executable file
114
OpenRA.Game/Effects/Missile.cs
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class Missile : IEffect
|
||||||
|
{
|
||||||
|
readonly Actor FiredBy;
|
||||||
|
readonly WeaponInfo Weapon;
|
||||||
|
readonly ProjectileInfo Projectile;
|
||||||
|
readonly WarheadInfo Warhead;
|
||||||
|
float2 Pos;
|
||||||
|
readonly Actor Target;
|
||||||
|
readonly Animation anim;
|
||||||
|
int Facing;
|
||||||
|
int t;
|
||||||
|
int Altitude;
|
||||||
|
|
||||||
|
public Missile(WeaponInfo weapon, Player owner, Actor firedBy,
|
||||||
|
int2 src, Actor target, int altitude, int facing)
|
||||||
|
{
|
||||||
|
Weapon = weapon;
|
||||||
|
Projectile = Rules.ProjectileInfo[Weapon.Projectile];
|
||||||
|
Warhead = Rules.WarheadInfo[Weapon.Warhead];
|
||||||
|
FiredBy = firedBy;
|
||||||
|
Target = target;
|
||||||
|
Pos = src.ToFloat2();
|
||||||
|
Altitude = altitude;
|
||||||
|
Facing = facing;
|
||||||
|
|
||||||
|
if (Projectile.Image != null && Projectile.Image != "none")
|
||||||
|
{
|
||||||
|
if (Projectile.Rotates)
|
||||||
|
anim = new Animation(Projectile.Image, () => Facing);
|
||||||
|
else
|
||||||
|
anim = new Animation(Projectile.Image);
|
||||||
|
|
||||||
|
anim.PlayRepeating("idle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MissileCloseEnough = 7;
|
||||||
|
const float Scale = .2f;
|
||||||
|
|
||||||
|
public void Tick( World world )
|
||||||
|
{
|
||||||
|
t += 40;
|
||||||
|
|
||||||
|
var targetUnit = Target.traits.GetOrDefault<Unit>();
|
||||||
|
var targetAltitude = targetUnit != null ? targetUnit.Altitude : 0;
|
||||||
|
Altitude += Math.Sign(targetAltitude - Altitude);
|
||||||
|
|
||||||
|
Traits.Util.TickFacing(ref Facing,
|
||||||
|
Traits.Util.GetFacing(Target.CenterLocation - Pos, Facing),
|
||||||
|
Projectile.ROT);
|
||||||
|
|
||||||
|
anim.Tick();
|
||||||
|
|
||||||
|
var dist = Target.CenterLocation - Pos;
|
||||||
|
if (dist.LengthSquared < MissileCloseEnough * MissileCloseEnough || Target.IsDead)
|
||||||
|
Explode(world);
|
||||||
|
|
||||||
|
var speed = Scale * Weapon.Speed * ((targetAltitude > 0 && Weapon.TurboBoost) ? 1.5f : 1f);
|
||||||
|
|
||||||
|
var angle = Facing / 128f * Math.PI;
|
||||||
|
var move = speed * -float2.FromAngle((float)angle);
|
||||||
|
Pos += move;
|
||||||
|
|
||||||
|
if (Projectile.Trail != null)
|
||||||
|
world.AddFrameEndTask(w => w.Add(
|
||||||
|
new Smoke(w, (Pos - 1.5f * move - new int2( 0, Altitude )).ToInt2(), Projectile.Trail)));
|
||||||
|
|
||||||
|
if (Projectile.RangeLimit != 0 && t > Projectile.RangeLimit * 40)
|
||||||
|
Explode(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Explode(World world)
|
||||||
|
{
|
||||||
|
world.AddFrameEndTask(w => w.Remove(this));
|
||||||
|
|
||||||
|
if (t > Projectile.Arm * 40) /* don't blow up in our launcher's face! */
|
||||||
|
Combat.DoImpact(Pos.ToInt2(), Pos.ToInt2(), Weapon, Projectile, Warhead, FiredBy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
yield return new Renderable(anim.Image, Pos - 0.5f * anim.Image.size - new float2(0, Altitude), "effect");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
OpenRA.Game/Effects/MoveFlash.cs
Executable file
47
OpenRA.Game/Effects/MoveFlash.cs
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class MoveFlash : IEffect
|
||||||
|
{
|
||||||
|
Animation anim = new Animation("moveflsh");
|
||||||
|
float2 pos;
|
||||||
|
|
||||||
|
public MoveFlash( World world, float2 pos )
|
||||||
|
{
|
||||||
|
this.pos = pos;
|
||||||
|
anim.PlayThen( "idle",
|
||||||
|
() => world.AddFrameEndTask(
|
||||||
|
w => w.Remove( this ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick( World world ) { anim.Tick(); }
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
OpenRA.Game/Effects/RepairIndicator.cs
Executable file
47
OpenRA.Game/Effects/RepairIndicator.cs
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class RepairIndicator : IEffect
|
||||||
|
{
|
||||||
|
int framesLeft = (int)(Rules.General.RepairRate * 25 * 60 / 2);
|
||||||
|
Actor a;
|
||||||
|
Animation anim = new Animation("select");
|
||||||
|
|
||||||
|
public RepairIndicator(Actor a) { this.a = a; anim.PlayRepeating("repair"); }
|
||||||
|
|
||||||
|
public void Tick( World world )
|
||||||
|
{
|
||||||
|
if (--framesLeft == 0 || a.IsDead)
|
||||||
|
world.AddFrameEndTask(w => w.Remove(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
yield return new Renderable(anim.Image,
|
||||||
|
a.CenterLocation - .5f * anim.Image.size, "chrome");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
OpenRA.Game/Effects/Smoke.cs
Executable file
50
OpenRA.Game/Effects/Smoke.cs
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class Smoke : IEffect
|
||||||
|
{
|
||||||
|
readonly int2 pos;
|
||||||
|
readonly Animation anim;
|
||||||
|
|
||||||
|
public Smoke(World world, int2 pos, string trail)
|
||||||
|
{
|
||||||
|
this.pos = pos;
|
||||||
|
anim = new Animation(trail);
|
||||||
|
anim.PlayThen("idle",
|
||||||
|
() => world.AddFrameEndTask(w => w.Remove(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick( World world )
|
||||||
|
{
|
||||||
|
anim.Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "effect");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
104
OpenRA.Game/Effects/TeslaZap.cs
Executable file
104
OpenRA.Game/Effects/TeslaZap.cs
Executable file
@@ -0,0 +1,104 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Effects
|
||||||
|
{
|
||||||
|
class TeslaZap : IEffect
|
||||||
|
{
|
||||||
|
readonly int2 from, to;
|
||||||
|
readonly Sequence tesla;
|
||||||
|
int timeUntilRemove = 2; // # of frames
|
||||||
|
|
||||||
|
public TeslaZap( int2 from, int2 to )
|
||||||
|
{
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
this.tesla = SequenceProvider.GetSequence( "litning", "bright" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick( World world )
|
||||||
|
{
|
||||||
|
if( timeUntilRemove <= 0 )
|
||||||
|
world.AddFrameEndTask( w => w.Remove( this ) );
|
||||||
|
--timeUntilRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Renderable> Render()
|
||||||
|
{
|
||||||
|
if( from.X < to.X )
|
||||||
|
return DrawZap( from, to, tesla );
|
||||||
|
else if( from.X > to.X || from.Y > to.Y )
|
||||||
|
return DrawZap( to, from, tesla );
|
||||||
|
else
|
||||||
|
return DrawZap( from, to, tesla );
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<Renderable> DrawZap( int2 from, int2 to, Sequence tesla )
|
||||||
|
{
|
||||||
|
int2 d = to - from;
|
||||||
|
if( d.X < 8 )
|
||||||
|
{
|
||||||
|
var prev = new int2( 0, 0 );
|
||||||
|
var y = d.Y;
|
||||||
|
while( y >= prev.Y + 8 )
|
||||||
|
{
|
||||||
|
yield return new Renderable( tesla.GetSprite( 2 ), (float2)( from + prev - new int2( 0, 8 ) ), "effect");
|
||||||
|
prev.Y += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var prev = new int2( 0, 0 );
|
||||||
|
for( int i = 1 ; i < d.X ; i += 8 )
|
||||||
|
{
|
||||||
|
var y = i * d.Y / d.X;
|
||||||
|
if( y <= prev.Y - 8 )
|
||||||
|
{
|
||||||
|
yield return new Renderable(tesla.GetSprite(3), (float2)(from + prev - new int2(8, 16)), "effect");
|
||||||
|
prev.Y -= 8;
|
||||||
|
while( y <= prev.Y - 8 )
|
||||||
|
{
|
||||||
|
yield return new Renderable(tesla.GetSprite(2), (float2)(from + prev - new int2(0, 16)), "effect");
|
||||||
|
prev.Y -= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( y >= prev.Y + 8 )
|
||||||
|
{
|
||||||
|
yield return new Renderable(tesla.GetSprite(0), (float2)(from + prev - new int2(8, 8)), "effect");
|
||||||
|
prev.Y += 8;
|
||||||
|
while( y >= prev.Y + 8 )
|
||||||
|
{
|
||||||
|
yield return new Renderable(tesla.GetSprite(2), (float2)(from + prev - new int2(0, 8)), "effect");
|
||||||
|
prev.Y += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
yield return new Renderable(tesla.GetSprite(1), (float2)(from + prev - new int2(8, 8)), "effect");
|
||||||
|
|
||||||
|
prev.X += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
90
OpenRA.Game/Exts.cs
Normal file
90
OpenRA.Game/Exts.cs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public static class Exts
|
||||||
|
{
|
||||||
|
public static bool HasModifier(this Modifiers k, Modifiers mod)
|
||||||
|
{
|
||||||
|
return (k & mod) == mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> xs, IEnumerable<T> ys)
|
||||||
|
{
|
||||||
|
// this is probably a shockingly-slow way to do this, but it's concise.
|
||||||
|
return xs.Except(ys).Concat(ys.Except(xs));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Product(this IEnumerable<float> xs)
|
||||||
|
{
|
||||||
|
return xs.Aggregate(1f, (a, x) => a * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WeaponInfo GetPrimaryWeapon(this Actor self)
|
||||||
|
{
|
||||||
|
var info = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
|
||||||
|
if (info == null) return null;
|
||||||
|
|
||||||
|
var weapon = info.PrimaryWeapon;
|
||||||
|
if (weapon == null) return null;
|
||||||
|
|
||||||
|
return Rules.WeaponInfo[weapon];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WeaponInfo GetSecondaryWeapon(this Actor self)
|
||||||
|
{
|
||||||
|
var info = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
|
||||||
|
if (info == null) return null;
|
||||||
|
|
||||||
|
var weapon = info.SecondaryWeapon;
|
||||||
|
if (weapon == null) return null;
|
||||||
|
|
||||||
|
return Rules.WeaponInfo[weapon];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetMaxHP(this Actor self)
|
||||||
|
{
|
||||||
|
var oai = self.Info.Traits.GetOrDefault<OwnedActorInfo>();
|
||||||
|
if (oai == null) return 0;
|
||||||
|
return oai.HP;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
|
||||||
|
where V : new()
|
||||||
|
{
|
||||||
|
return d.GetOrAdd( k, _ => new V() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k, Func<K, V> createFn )
|
||||||
|
{
|
||||||
|
V ret;
|
||||||
|
if( !d.TryGetValue( k, out ret ) )
|
||||||
|
d.Add( k, ret = createFn( k ) );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
427
OpenRA.Game/Game.cs
Normal file
427
OpenRA.Game/Game.cs
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Network;
|
||||||
|
using OpenRA.Support;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
using Timer = OpenRA.Support.Timer;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public static class Game
|
||||||
|
{
|
||||||
|
public static readonly int CellSize = 24;
|
||||||
|
|
||||||
|
public static World world;
|
||||||
|
internal static Viewport viewport;
|
||||||
|
public static Controller controller;
|
||||||
|
internal static Chrome chrome;
|
||||||
|
public static UserSettings Settings;
|
||||||
|
|
||||||
|
internal static OrderManager orderManager;
|
||||||
|
|
||||||
|
public static bool skipMakeAnims = true;
|
||||||
|
|
||||||
|
internal static Renderer renderer;
|
||||||
|
static int2 clientSize;
|
||||||
|
static string mapName;
|
||||||
|
internal static Session LobbyInfo = new Session();
|
||||||
|
static bool changePending;
|
||||||
|
|
||||||
|
public static void LoadModPackages(Manifest manifest)
|
||||||
|
{
|
||||||
|
FileSystem.UnmountAll();
|
||||||
|
Timer.Time("reset: {0}");
|
||||||
|
|
||||||
|
foreach (var dir in manifest.Folders) FileSystem.Mount(dir);
|
||||||
|
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||||
|
|
||||||
|
Timer.Time("mount temporary packages: {0}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ChangeMap(string mapName)
|
||||||
|
{
|
||||||
|
Timer.Time( "----ChangeMap" );
|
||||||
|
|
||||||
|
var manifest = new Manifest(LobbyInfo.GlobalSettings.Mods);
|
||||||
|
Timer.Time( "manifest: {0}" );
|
||||||
|
|
||||||
|
Game.changePending = false;
|
||||||
|
Game.mapName = mapName;
|
||||||
|
SheetBuilder.Initialize(renderer);
|
||||||
|
|
||||||
|
LoadModPackages(manifest);
|
||||||
|
|
||||||
|
Rules.LoadRules(mapName, manifest);
|
||||||
|
Timer.Time( "load rules: {0}" );
|
||||||
|
|
||||||
|
world = null; // trying to access the old world will NRE, rather than silently doing it wrong.
|
||||||
|
|
||||||
|
Player.ResetPlayerColorList();
|
||||||
|
ChromeProvider.Initialize(manifest.Chrome);
|
||||||
|
|
||||||
|
world = new World();
|
||||||
|
|
||||||
|
Game.world.ActorAdded += a =>
|
||||||
|
{
|
||||||
|
if (a.Owner != null && a.Info.Traits.Contains<OwnedActorInfo>())
|
||||||
|
a.Owner.Shroud.Explore(a);
|
||||||
|
};
|
||||||
|
Timer.Time( "world: {0}" );
|
||||||
|
|
||||||
|
SequenceProvider.Initialize(manifest.Sequences);
|
||||||
|
viewport = new Viewport(clientSize, Game.world.Map.Offset, Game.world.Map.Offset + Game.world.Map.Size, renderer);
|
||||||
|
Timer.Time( "ChromeProv, SeqProv, viewport: {0}" );
|
||||||
|
|
||||||
|
skipMakeAnims = true;
|
||||||
|
foreach (var treeReference in Game.world.Map.Trees)
|
||||||
|
world.CreateActor(treeReference.Image, new int2(treeReference.Location), null);
|
||||||
|
Timer.Time( "trees: {0}" );
|
||||||
|
|
||||||
|
world.LoadMapActors(Rules.AllRules);
|
||||||
|
skipMakeAnims = false;
|
||||||
|
Timer.Time( "map actors: {0}" );
|
||||||
|
|
||||||
|
chrome = new Chrome(renderer);
|
||||||
|
Timer.Time( "chrome: {0}" );
|
||||||
|
|
||||||
|
Timer.Time( "----end ChangeMap" );
|
||||||
|
chat.AddLine(Color.White, "Debug", "Map change {0} -> {1}".F(Game.mapName, mapName));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Initialize(string mapName, Renderer renderer, int2 clientSize, int localPlayer, Controller controller)
|
||||||
|
{
|
||||||
|
|
||||||
|
Game.renderer = renderer;
|
||||||
|
Game.clientSize = clientSize;
|
||||||
|
|
||||||
|
// todo
|
||||||
|
Sound.Initialize();
|
||||||
|
PerfHistory.items["render"].hasNormalTick = false;
|
||||||
|
PerfHistory.items["batches"].hasNormalTick = false;
|
||||||
|
PerfHistory.items["text"].hasNormalTick = false;
|
||||||
|
Game.controller = controller;
|
||||||
|
|
||||||
|
ChangeMap(mapName);
|
||||||
|
|
||||||
|
if (Settings.Replay != "")
|
||||||
|
throw new NotImplementedException();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var connection = (string.IsNullOrEmpty(Settings.NetworkHost))
|
||||||
|
? new EchoConnection()
|
||||||
|
: new NetworkConnection( Settings.NetworkHost, Settings.NetworkPort );
|
||||||
|
orderManager = new OrderManager(connection, "replay.rep");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lastTime = Environment.TickCount;
|
||||||
|
|
||||||
|
public static void ResetTimer()
|
||||||
|
{
|
||||||
|
lastTime = Environment.TickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int RenderFrame = 0;
|
||||||
|
|
||||||
|
internal static Chat chat = new Chat();
|
||||||
|
|
||||||
|
public static void Tick()
|
||||||
|
{
|
||||||
|
if (changePending && PackageDownloader.IsIdle())
|
||||||
|
{
|
||||||
|
ChangeMap(LobbyInfo.GlobalSettings.Map);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int t = Environment.TickCount;
|
||||||
|
int dt = t - lastTime;
|
||||||
|
if (dt >= Settings.Timestep)
|
||||||
|
{
|
||||||
|
using (new PerfSample("tick_time"))
|
||||||
|
{
|
||||||
|
lastTime += Settings.Timestep;
|
||||||
|
chrome.Tick( world );
|
||||||
|
|
||||||
|
orderManager.TickImmediate( world );
|
||||||
|
|
||||||
|
if (orderManager.IsReadyForNextFrame)
|
||||||
|
{
|
||||||
|
orderManager.Tick(world);
|
||||||
|
controller.orderGenerator.Tick(world);
|
||||||
|
controller.selection.Tick(world);
|
||||||
|
|
||||||
|
world.Tick();
|
||||||
|
|
||||||
|
PerfHistory.Tick();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (orderManager.FrameNumber == 0)
|
||||||
|
lastTime = Environment.TickCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using (new PerfSample("render"))
|
||||||
|
{
|
||||||
|
++RenderFrame;
|
||||||
|
viewport.DrawRegions( world );
|
||||||
|
}
|
||||||
|
|
||||||
|
PerfHistory.items["render"].Tick();
|
||||||
|
PerfHistory.items["batches"].Tick();
|
||||||
|
PerfHistory.items["text"].Tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SyncLobbyInfo(string data)
|
||||||
|
{
|
||||||
|
var session = new Session();
|
||||||
|
session.GlobalSettings.Mods = Settings.InitialMods;
|
||||||
|
|
||||||
|
var ys = MiniYaml.FromString(data);
|
||||||
|
foreach (var y in ys)
|
||||||
|
{
|
||||||
|
if (y.Key == "GlobalSettings")
|
||||||
|
{
|
||||||
|
FieldLoader.Load(session.GlobalSettings, y.Value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index;
|
||||||
|
if (!int.TryParse(y.Key, out index))
|
||||||
|
continue; // not a player.
|
||||||
|
|
||||||
|
var client = new Session.Client();
|
||||||
|
FieldLoader.Load(client, y.Value);
|
||||||
|
session.Clients.Add(client);
|
||||||
|
|
||||||
|
world.players[index].SyncFromLobby(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
LobbyInfo = session;
|
||||||
|
|
||||||
|
if (Game.orderManager.Connection.ConnectionState == ConnectionState.Connected)
|
||||||
|
world.SetLocalPlayer(Game.orderManager.Connection.LocalClientId);
|
||||||
|
|
||||||
|
if (Game.orderManager.FramesAhead != LobbyInfo.GlobalSettings.OrderLatency
|
||||||
|
&& !Game.orderManager.GameStarted)
|
||||||
|
{
|
||||||
|
Game.orderManager.FramesAhead = LobbyInfo.GlobalSettings.OrderLatency;
|
||||||
|
Game.chat.AddLine(Color.White, "Server",
|
||||||
|
"Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PackageDownloader.SetPackageList(LobbyInfo.GlobalSettings.Packages)
|
||||||
|
|| mapName != LobbyInfo.GlobalSettings.Map)
|
||||||
|
changePending = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void IssueOrder(Order o) { orderManager.IssueOrder(o); } /* avoid exposing the OM to mod code */
|
||||||
|
|
||||||
|
public static void StartGame()
|
||||||
|
{
|
||||||
|
Game.chat.Reset();
|
||||||
|
|
||||||
|
var taken = LobbyInfo.Clients.Where(c => c.SpawnPoint != 0)
|
||||||
|
.Select(c => world.Map.SpawnPoints.ElementAt(c.SpawnPoint - 1)).ToList();
|
||||||
|
|
||||||
|
var available = world.Map.SpawnPoints.Except(taken).ToList();
|
||||||
|
|
||||||
|
foreach (var client in LobbyInfo.Clients)
|
||||||
|
{
|
||||||
|
var sp = (client.SpawnPoint == 0)
|
||||||
|
? ChooseSpawnPoint(available, taken)
|
||||||
|
: world.Map.SpawnPoints.ElementAt(client.SpawnPoint - 1);
|
||||||
|
|
||||||
|
foreach (var ssu in world.players[client.Index].PlayerActor
|
||||||
|
.traits.WithInterface<IOnGameStart>())
|
||||||
|
ssu.SpawnStartingUnits(world.players[client.Index], sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Game.viewport.GoToStartLocation( Game.world.LocalPlayer );
|
||||||
|
orderManager.StartGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int2 ChooseSpawnPoint(List<int2> available, List<int2> taken)
|
||||||
|
{
|
||||||
|
if (available.Count == 0)
|
||||||
|
throw new InvalidOperationException("No free spawnpoint.");
|
||||||
|
|
||||||
|
var n = taken.Count == 0
|
||||||
|
? world.SharedRandom.Next(available.Count)
|
||||||
|
: available // pick the most distant spawnpoint from everyone else
|
||||||
|
.Select((k,i) => Pair.New(k,i))
|
||||||
|
.OrderByDescending(a => taken.Sum(t => (t - a.First).LengthSquared))
|
||||||
|
.Select(a => a.Second)
|
||||||
|
.First();
|
||||||
|
|
||||||
|
var sp = available[n];
|
||||||
|
available.RemoveAt(n);
|
||||||
|
taken.Add(sp);
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int2 lastPos;
|
||||||
|
public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Modifiers modifierKeys)
|
||||||
|
{
|
||||||
|
int sync = Game.world.SyncHash();
|
||||||
|
|
||||||
|
if (ev == MouseInputEvent.Down)
|
||||||
|
lastPos = new int2(e.Location);
|
||||||
|
|
||||||
|
if (ev == MouseInputEvent.Move && (e.Button == MouseButtons.Middle || e.Button == (MouseButtons.Left | MouseButtons.Right)))
|
||||||
|
{
|
||||||
|
var p = new int2(e.Location);
|
||||||
|
viewport.Scroll(lastPos - p);
|
||||||
|
lastPos = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game.viewport.DispatchMouseInput( world,
|
||||||
|
new MouseInput
|
||||||
|
{
|
||||||
|
Button = (MouseButton)(int)e.Button,
|
||||||
|
Event = ev,
|
||||||
|
Location = new int2(e.Location),
|
||||||
|
Modifiers = modifierKeys,
|
||||||
|
});
|
||||||
|
|
||||||
|
if( sync != Game.world.SyncHash() )
|
||||||
|
throw new InvalidOperationException( "Desync in DispatchMouseInput" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleKeyDown( KeyEventArgs e )
|
||||||
|
{
|
||||||
|
//int sync = Game.world.SyncHash();
|
||||||
|
|
||||||
|
|
||||||
|
//if( sync != Game.world.SyncHash() )
|
||||||
|
// throw new InvalidOperationException( "Desync in OnKeyDown" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsHost
|
||||||
|
{
|
||||||
|
get { return orderManager.Connection.LocalClientId == 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleKeyPress( KeyPressEventArgs e, Modifiers modifiers )
|
||||||
|
{
|
||||||
|
int sync = Game.world.SyncHash();
|
||||||
|
|
||||||
|
if( e.KeyChar == '\r' )
|
||||||
|
Game.chat.Toggle();
|
||||||
|
else if( Game.chat.isChatting )
|
||||||
|
Game.chat.TypeChar( e.KeyChar );
|
||||||
|
else
|
||||||
|
if( e.KeyChar >= '0' && e.KeyChar <= '9' )
|
||||||
|
Game.controller.selection.DoControlGroup( world,
|
||||||
|
e.KeyChar - '0', modifiers );
|
||||||
|
|
||||||
|
if( sync != Game.world.SyncHash() )
|
||||||
|
throw new InvalidOperationException( "Desync in OnKeyPress" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleModifierKeys(Modifiers mods)
|
||||||
|
{
|
||||||
|
controller.SetModifiers(mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Size GetResolution(Settings settings)
|
||||||
|
{
|
||||||
|
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||||
|
if (Game.Settings.Width > 0 && Game.Settings.Height > 0)
|
||||||
|
{
|
||||||
|
desktopResolution.Width = Game.Settings.Width;
|
||||||
|
desktopResolution.Height = Game.Settings.Height;
|
||||||
|
}
|
||||||
|
return new Size(
|
||||||
|
desktopResolution.Width,
|
||||||
|
desktopResolution.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PreInit(Settings settings)
|
||||||
|
{
|
||||||
|
while (!Directory.Exists("mods"))
|
||||||
|
{
|
||||||
|
var current = Directory.GetCurrentDirectory();
|
||||||
|
if (Directory.GetDirectoryRoot(current) == current)
|
||||||
|
throw new InvalidOperationException("Unable to load MIX files.");
|
||||||
|
Directory.SetCurrentDirectory("..");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LoadUserSettings(settings);
|
||||||
|
Game.LobbyInfo.GlobalSettings.Mods = Game.Settings.InitialMods;
|
||||||
|
|
||||||
|
// Load the default mod to access required files
|
||||||
|
Game.LoadModPackages(new Manifest(Game.LobbyInfo.GlobalSettings.Mods));
|
||||||
|
|
||||||
|
UiOverlay.ShowUnitDebug = Game.Settings.UnitDebug;
|
||||||
|
WorldRenderer.ShowUnitPaths = Game.Settings.PathDebug;
|
||||||
|
Renderer.SheetSize = Game.Settings.SheetSize;
|
||||||
|
|
||||||
|
bool windowed = !Game.Settings.Fullscreen;
|
||||||
|
var resolution = GetResolution(settings);
|
||||||
|
renderer = new Renderer(resolution, windowed);
|
||||||
|
resolution = renderer.Resolution;
|
||||||
|
|
||||||
|
var controller = new Controller(); /* a bit of insane input routing */
|
||||||
|
|
||||||
|
Game.Initialize(Game.Settings.Map, renderer, new int2(resolution), Game.Settings.Player, controller);
|
||||||
|
|
||||||
|
// ShowCursor(false);
|
||||||
|
Game.ResetTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadUserSettings(Settings settings)
|
||||||
|
{
|
||||||
|
Game.Settings = new UserSettings();
|
||||||
|
var settingsFile = settings.GetValue("settings", "settings.ini");
|
||||||
|
FileSystem.Mount("./");
|
||||||
|
if (FileSystem.Exists(settingsFile))
|
||||||
|
FieldLoader.Load(Game.Settings,
|
||||||
|
new IniFile(FileSystem.Open(settingsFile)).GetSection("Settings"));
|
||||||
|
FileSystem.UnmountAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool quit;
|
||||||
|
internal static void Run()
|
||||||
|
{
|
||||||
|
while (!quit)
|
||||||
|
{
|
||||||
|
Game.Tick();
|
||||||
|
Application.DoEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Exit()
|
||||||
|
{
|
||||||
|
quit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
139
OpenRA.Game/GameRules/ActorInfo.cs
Normal file
139
OpenRA.Game/GameRules/ActorInfo.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class ActorInfo
|
||||||
|
{
|
||||||
|
public readonly string Name;
|
||||||
|
public readonly string Category;
|
||||||
|
public readonly TypeDictionary Traits = new TypeDictionary();
|
||||||
|
|
||||||
|
public ActorInfo( string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||||
|
{
|
||||||
|
var mergedNode = MergeWithParent( node, allUnits ).Nodes;
|
||||||
|
|
||||||
|
Name = name;
|
||||||
|
MiniYaml categoryNode;
|
||||||
|
if( mergedNode.TryGetValue( "Category", out categoryNode ) )
|
||||||
|
Category = categoryNode.Value;
|
||||||
|
|
||||||
|
foreach( var t in mergedNode )
|
||||||
|
if( t.Key != "Inherits" && t.Key != "Category" )
|
||||||
|
Traits.Add( LoadTraitInfo( t.Key, t.Value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||||
|
{
|
||||||
|
MiniYaml inherits;
|
||||||
|
node.Nodes.TryGetValue( "Inherits", out inherits );
|
||||||
|
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
MiniYaml parent;
|
||||||
|
allUnits.TryGetValue( inherits.Value, out parent );
|
||||||
|
if( parent == null )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MiniYaml MergeWithParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||||
|
{
|
||||||
|
var parent = GetParent( node, allUnits );
|
||||||
|
if( parent != null )
|
||||||
|
return MiniYaml.Merge( node, MergeWithParent( parent, allUnits ) );
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Pair<Assembly, string>[] ModAssemblies;
|
||||||
|
public static void LoadModAssemblies(Manifest m)
|
||||||
|
{
|
||||||
|
var asms = new List<Pair<Assembly, string>>();
|
||||||
|
|
||||||
|
// all the core stuff is in this assembly
|
||||||
|
asms.Add(Pair.New(typeof(ITraitInfo).Assembly, typeof(ITraitInfo).Namespace));
|
||||||
|
|
||||||
|
// add the mods
|
||||||
|
foreach (var a in m.Assemblies)
|
||||||
|
asms.Add(Pair.New(Assembly.LoadFile(Path.GetFullPath(a)), Path.GetFileNameWithoutExtension(a)));
|
||||||
|
ModAssemblies = asms.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ITraitInfo LoadTraitInfo(string traitName, MiniYaml my)
|
||||||
|
{
|
||||||
|
if (traitName.Contains('@'))
|
||||||
|
traitName = traitName.Substring(0, traitName.IndexOf('@'));
|
||||||
|
|
||||||
|
foreach (var mod in ModAssemblies)
|
||||||
|
{
|
||||||
|
var fullTypeName = mod.Second + "." + traitName + "Info";
|
||||||
|
var info = (ITraitInfo)mod.First.CreateInstance(fullTypeName);
|
||||||
|
if (info == null) continue;
|
||||||
|
FieldLoader.Load(info, my);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException("Cannot locate trait: {0}".F(traitName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ITraitInfo> TraitsInConstructOrder()
|
||||||
|
{
|
||||||
|
var ret = new List<ITraitInfo>();
|
||||||
|
var t = Traits.WithInterface<ITraitInfo>().ToList();
|
||||||
|
int index = 0;
|
||||||
|
while( t.Count != 0 )
|
||||||
|
{
|
||||||
|
if( index >= t.Count )
|
||||||
|
throw new InvalidOperationException( "Trait prerequisites not satisfied (or prerequisite loop)" );
|
||||||
|
|
||||||
|
var prereqs = PrerequisitesOf( t[ index ] );
|
||||||
|
if( prereqs.Count == 0 || prereqs.All( n => ret.Any( x => x.GetType().IsSubclassOf( n ) ) ) )
|
||||||
|
{
|
||||||
|
ret.Add( t[ index ] );
|
||||||
|
t.RemoveAt( index );
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Type> PrerequisitesOf( ITraitInfo info )
|
||||||
|
{
|
||||||
|
return info
|
||||||
|
.GetType()
|
||||||
|
.GetInterfaces()
|
||||||
|
.Where( t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof( ITraitPrerequisite<> ) )
|
||||||
|
.Select( t => t.GetGenericArguments()[ 0 ] )
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
OpenRA.Game/GameRules/Footprint.cs
Normal file
74
OpenRA.Game/GameRules/Footprint.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
static class Footprint
|
||||||
|
{
|
||||||
|
public static IEnumerable<int2> Tiles( string name, BuildingInfo buildingInfo, int2 topLeft )
|
||||||
|
{
|
||||||
|
var dim = buildingInfo.Dimensions;
|
||||||
|
|
||||||
|
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x));
|
||||||
|
if (buildingInfo.Bib)
|
||||||
|
{
|
||||||
|
dim.Y += 1;
|
||||||
|
footprint = footprint.Concat(new char[dim.X]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TilesWhere( name, dim, footprint.ToArray(), a => a != '_' ).Select( t => t + topLeft );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<int2> Tiles(Actor a, Traits.Building building)
|
||||||
|
{
|
||||||
|
return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<int2> UnpathableTiles( string name, BuildingInfo buildingInfo, int2 position )
|
||||||
|
{
|
||||||
|
var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray();
|
||||||
|
foreach( var tile in TilesWhere( name, buildingInfo.Dimensions, footprint, a => a == 'x' ) )
|
||||||
|
yield return tile + position;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IEnumerable<int2> TilesWhere( string name, int2 dim, char[] footprint, Func<char, bool> cond )
|
||||||
|
{
|
||||||
|
if( footprint.Length != dim.X * dim.Y )
|
||||||
|
throw new InvalidOperationException( "Invalid footprint for " + name );
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for( int y = 0 ; y < dim.Y ; y++ )
|
||||||
|
for( int x = 0 ; x < dim.X ; x++ )
|
||||||
|
if( cond( footprint[ index++ ] ) )
|
||||||
|
yield return new int2( x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int2 AdjustForBuildingSize( BuildingInfo buildingInfo )
|
||||||
|
{
|
||||||
|
var dim = buildingInfo.Dimensions;
|
||||||
|
return new int2( dim.X / 2, dim.Y > 1 ? ( dim.Y + 1 ) / 2 : 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
112
OpenRA.Game/GameRules/GeneralInfo.cs
Normal file
112
OpenRA.Game/GameRules/GeneralInfo.cs
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class GeneralInfo
|
||||||
|
{
|
||||||
|
/* Special Weapons */
|
||||||
|
public readonly float GapRegenInterval =0;
|
||||||
|
public readonly int BadgerBombCount = 1;
|
||||||
|
|
||||||
|
/* Chrono Side Effects */
|
||||||
|
public readonly float QuakeChance = 0;
|
||||||
|
public readonly float QuakeDamage = 0; /* percent */
|
||||||
|
public readonly float VortexChance = 0;
|
||||||
|
public readonly int VortexDamage = 0;
|
||||||
|
public readonly int VortexRange = 0;
|
||||||
|
public readonly int VortexSpeed = 0;
|
||||||
|
|
||||||
|
/* Repair & Refit */
|
||||||
|
public readonly float RefundPercent = 0;
|
||||||
|
public readonly float ReloadRate = 0;
|
||||||
|
public readonly float RepairPercent = 0;
|
||||||
|
public readonly float RepairRate = 0;
|
||||||
|
public readonly int RepairStep = 0;
|
||||||
|
public readonly float URepairPercent = 0;
|
||||||
|
public readonly int URepairStep = 0;
|
||||||
|
|
||||||
|
/* Combat & Damage */
|
||||||
|
public readonly float TurboBoost = 1.5f;
|
||||||
|
public readonly float BallisticScatter = 0;
|
||||||
|
public readonly float C4Delay = 0;
|
||||||
|
public readonly float ExpSpread = 0;
|
||||||
|
public readonly int FireSupress = 0;
|
||||||
|
public readonly float HomingScatter = 0;
|
||||||
|
public readonly int MaxDamage = 0;
|
||||||
|
public readonly int MinDamage = 0;
|
||||||
|
public readonly bool OreExplosive = false;
|
||||||
|
public readonly bool PlayerAutoCrush = false;
|
||||||
|
public readonly bool PlayerReturnFire = false;
|
||||||
|
public readonly bool PlayerScatter = false;
|
||||||
|
public readonly bool TreeTargeting = false;
|
||||||
|
public readonly int Incoming = 0;
|
||||||
|
|
||||||
|
/* Income & Production */
|
||||||
|
public readonly float BuildSpeed = 0;
|
||||||
|
public readonly float BuildupTime = 0;
|
||||||
|
public readonly int GemValue = 0;
|
||||||
|
public readonly int GoldValue = 0;
|
||||||
|
public readonly float OreTruckRate = 0;
|
||||||
|
public readonly bool SeparateAircraft = true;
|
||||||
|
public readonly float SurvivorRate = 0;
|
||||||
|
|
||||||
|
/* Audo/Visual Map Controls */
|
||||||
|
public readonly bool AllyReveal = true;
|
||||||
|
public readonly float ConditionRed = 0;
|
||||||
|
public readonly float ConditionYellow = 0;
|
||||||
|
public readonly int DropZoneRadius = 0;
|
||||||
|
public readonly bool EnemyHealth = true;
|
||||||
|
public readonly int Gravity = 0;
|
||||||
|
public readonly float IdleActionFrequency = 0;
|
||||||
|
public readonly float MessageDelay = 0;
|
||||||
|
public readonly float MovieTime = 0;
|
||||||
|
public readonly bool NamedCivilians = false;
|
||||||
|
public readonly float SavourDelay = 0;
|
||||||
|
public readonly int ShroudRate = 0;
|
||||||
|
public readonly int SpeakDelay = 0;
|
||||||
|
public readonly int TimerWarning = 0;
|
||||||
|
public readonly bool FlashLowPower = false;
|
||||||
|
|
||||||
|
/* Computer & Movement Controls */
|
||||||
|
public readonly bool CurleyShuffle = false;
|
||||||
|
public readonly float BaseBias = 0;
|
||||||
|
public readonly float BaseDefenseDelay = 0;
|
||||||
|
public readonly float CloseEnough = 0;
|
||||||
|
public readonly int DamageDelay = 0;
|
||||||
|
public readonly int GameSpeeBias = 0;
|
||||||
|
public readonly int LZScanRadius = 0;
|
||||||
|
public readonly bool MineAware = false;
|
||||||
|
public readonly float Stray = 0;
|
||||||
|
public readonly float SubmergeDelay = 0;
|
||||||
|
public readonly float SuspendDelay = 0;
|
||||||
|
public readonly int SuspendPriority = 0;
|
||||||
|
public readonly float TeamDelay = 0;
|
||||||
|
|
||||||
|
/* Misc */
|
||||||
|
[Obsolete]
|
||||||
|
public readonly bool FineDiffControl = false;
|
||||||
|
|
||||||
|
/* OpenRA-specific */
|
||||||
|
public readonly int LowPowerSlowdown = 3; /* build time multiplier */
|
||||||
|
}
|
||||||
|
}
|
||||||
51
OpenRA.Game/GameRules/InfoLoader.cs
Normal file
51
OpenRA.Game/GameRules/InfoLoader.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class InfoLoader<T> : IEnumerable<KeyValuePair<string, T>>
|
||||||
|
{
|
||||||
|
readonly Dictionary<string, T> infos = new Dictionary<string, T>();
|
||||||
|
|
||||||
|
public InfoLoader(params Pair<string, Func<string,T>>[] srcs)
|
||||||
|
{
|
||||||
|
foreach (var src in srcs)
|
||||||
|
foreach (var name in Rules.Categories[src.First])
|
||||||
|
{
|
||||||
|
var t = src.Second(name);
|
||||||
|
FieldLoader.Load(t, Rules.AllRules.GetSection(name));
|
||||||
|
infos[name] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T this[string name]
|
||||||
|
{
|
||||||
|
get { return infos[name.ToLowerInvariant()]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<string, T>> GetEnumerator() { return infos.GetEnumerator(); }
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() { return infos.GetEnumerator(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
45
OpenRA.Game/GameRules/ProjectileInfo.cs
Normal file
45
OpenRA.Game/GameRules/ProjectileInfo.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class ProjectileInfo
|
||||||
|
{
|
||||||
|
public readonly bool AA = false;
|
||||||
|
public readonly bool AG = true;
|
||||||
|
public readonly bool ASW = false;
|
||||||
|
public readonly bool Arcing = false;
|
||||||
|
public readonly int Arm = 0;
|
||||||
|
public readonly bool Degenerates = false;
|
||||||
|
public readonly bool High = false;
|
||||||
|
public readonly string Image = null;
|
||||||
|
public readonly bool Inaccurate = false;
|
||||||
|
public readonly bool Parachuted = false;
|
||||||
|
public readonly bool Proximity = false;
|
||||||
|
public readonly int ROT = 0;
|
||||||
|
public readonly bool Rotates = false;
|
||||||
|
public readonly bool Shadow = true;
|
||||||
|
public readonly bool UnderWater = false;
|
||||||
|
public readonly int RangeLimit = 0;
|
||||||
|
|
||||||
|
// OpenRA-specific:
|
||||||
|
public readonly string Trail = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
82
OpenRA.Game/GameRules/Rules.cs
Executable file
82
OpenRA.Game/GameRules/Rules.cs
Executable file
@@ -0,0 +1,82 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.GameRules;
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public static class Rules
|
||||||
|
{
|
||||||
|
public static IniFile AllRules;
|
||||||
|
public static Dictionary<string, List<string>> Categories = new Dictionary<string, List<string>>();
|
||||||
|
public static InfoLoader<WeaponInfo> WeaponInfo;
|
||||||
|
public static InfoLoader<WarheadInfo> WarheadInfo;
|
||||||
|
public static InfoLoader<ProjectileInfo> ProjectileInfo;
|
||||||
|
public static InfoLoader<VoiceInfo> VoiceInfo;
|
||||||
|
public static GeneralInfo General;
|
||||||
|
public static TechTree TechTree;
|
||||||
|
|
||||||
|
public static Dictionary<string, ActorInfo> Info;
|
||||||
|
|
||||||
|
public static void LoadRules(string map, Manifest m)
|
||||||
|
{
|
||||||
|
var legacyRules = m.LegacyRules.Reverse().ToList();
|
||||||
|
legacyRules.Insert(0, map);
|
||||||
|
AllRules = new IniFile(legacyRules.Select(a => FileSystem.Open(a)).ToArray());
|
||||||
|
|
||||||
|
General = new GeneralInfo();
|
||||||
|
FieldLoader.Load(General, AllRules.GetSection("General"));
|
||||||
|
|
||||||
|
LoadCategories(
|
||||||
|
"Weapon",
|
||||||
|
"Warhead",
|
||||||
|
"Projectile",
|
||||||
|
"Voice");
|
||||||
|
|
||||||
|
WeaponInfo = new InfoLoader<WeaponInfo>(
|
||||||
|
Pair.New<string, Func<string, WeaponInfo>>("Weapon", _ => new WeaponInfo()));
|
||||||
|
WarheadInfo = new InfoLoader<WarheadInfo>(
|
||||||
|
Pair.New<string, Func<string, WarheadInfo>>("Warhead", _ => new WarheadInfo()));
|
||||||
|
ProjectileInfo = new InfoLoader<ProjectileInfo>(
|
||||||
|
Pair.New<string, Func<string, ProjectileInfo>>("Projectile", _ => new ProjectileInfo()));
|
||||||
|
VoiceInfo = new InfoLoader<VoiceInfo>(
|
||||||
|
Pair.New<string, Func<string, VoiceInfo>>("Voice", _ => new VoiceInfo()));
|
||||||
|
|
||||||
|
var yamlRules = m.Rules.Reverse().Select(a => MiniYaml.FromFile(a)).Aggregate(MiniYaml.Merge);
|
||||||
|
|
||||||
|
ActorInfo.LoadModAssemblies(m);
|
||||||
|
Info = new Dictionary<string, ActorInfo>();
|
||||||
|
foreach( var kv in yamlRules )
|
||||||
|
Info.Add(kv.Key.ToLowerInvariant(), new ActorInfo(kv.Key.ToLowerInvariant(), kv.Value, yamlRules));
|
||||||
|
|
||||||
|
TechTree = new TechTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadCategories(params string[] types)
|
||||||
|
{
|
||||||
|
foreach (var t in types)
|
||||||
|
Categories[t] = AllRules.GetSection(t + "Types").Select(x => x.Key.ToLowerInvariant()).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
100
OpenRA.Game/GameRules/TechTree.cs
Executable file
100
OpenRA.Game/GameRules/TechTree.cs
Executable file
@@ -0,0 +1,100 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class TechTree
|
||||||
|
{
|
||||||
|
readonly Cache<string, List<ActorInfo>> producesIndex = new Cache<string, List<ActorInfo>>(x => new List<ActorInfo>());
|
||||||
|
|
||||||
|
public TechTree()
|
||||||
|
{
|
||||||
|
foreach( var info in Rules.Info.Values )
|
||||||
|
{
|
||||||
|
var pi = info.Traits.GetOrDefault<ProductionInfo>();
|
||||||
|
if (pi != null)
|
||||||
|
foreach( var p in pi.Produces )
|
||||||
|
producesIndex[ p ].Add( info );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cache<string, List<Actor>> GatherBuildings( Player player )
|
||||||
|
{
|
||||||
|
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
|
||||||
|
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
|
||||||
|
{
|
||||||
|
ret[ b.Info.Name ].Add( b );
|
||||||
|
var buildable = b.Info.Traits.GetOrDefault<BuildableInfo>();
|
||||||
|
if( buildable != null )
|
||||||
|
foreach( var alt in buildable.AlternateName )
|
||||||
|
ret[ alt ].Add( b );
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanBuild( ActorInfo info, Player player, Cache<string, List<Actor>> playerBuildings )
|
||||||
|
{
|
||||||
|
var bi = info.Traits.GetOrDefault<BuildableInfo>();
|
||||||
|
if( bi == null ) return false;
|
||||||
|
|
||||||
|
if( !bi.Owner.Contains( player.Country.Race ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach( var p in bi.Prerequisites )
|
||||||
|
if( playerBuildings[ p ].Count == 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( producesIndex[ info.Category ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
|
||||||
|
{
|
||||||
|
var playerBuildings = GatherBuildings( player );
|
||||||
|
foreach( var unit in AllBuildables( player, categories ) )
|
||||||
|
if( CanBuild( unit, player, playerBuildings ) )
|
||||||
|
yield return unit.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ActorInfo> AllBuildables(Player player, params string[] categories)
|
||||||
|
{
|
||||||
|
return Rules.Info.Values
|
||||||
|
.Where( x => x.Name[ 0 ] != '^' )
|
||||||
|
.Where( x => categories.Contains( x.Category ) )
|
||||||
|
.Where( x => x.Traits.Contains<BuildableInfo>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ActorInfo> UnitBuiltAt( ActorInfo info )
|
||||||
|
{
|
||||||
|
var builtAt = info.Traits.Get<BuildableInfo>().BuiltAt;
|
||||||
|
if( builtAt.Length != 0 )
|
||||||
|
return builtAt.Select( x => Rules.Info[ x.ToLowerInvariant() ] );
|
||||||
|
else
|
||||||
|
return producesIndex[ info.Category ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
53
OpenRA.Game/GameRules/UserSettings.cs
Normal file
53
OpenRA.Game/GameRules/UserSettings.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class UserSettings
|
||||||
|
{
|
||||||
|
// Debug settings
|
||||||
|
public readonly bool UnitDebug = false;
|
||||||
|
public readonly bool PathDebug = false;
|
||||||
|
public readonly bool PerfGraph = true;
|
||||||
|
|
||||||
|
// Window settings
|
||||||
|
public readonly int Width = 0;
|
||||||
|
public readonly int Height = 0;
|
||||||
|
public readonly bool Fullscreen = false;
|
||||||
|
|
||||||
|
// Internal game settings
|
||||||
|
public readonly int Timestep = 40;
|
||||||
|
public readonly int SheetSize = 512;
|
||||||
|
|
||||||
|
// External game settings
|
||||||
|
public readonly string NetworkHost = "";
|
||||||
|
public readonly int NetworkPort = 0;
|
||||||
|
public readonly string Map = "scm12ea.ini";
|
||||||
|
public readonly int Player = 1;
|
||||||
|
public readonly string Replay = "";
|
||||||
|
public readonly string PlayerName = "";
|
||||||
|
public readonly string[] InitialMods = { "ra" };
|
||||||
|
|
||||||
|
// Gameplay options
|
||||||
|
// TODO: These need to die
|
||||||
|
public readonly bool RepairRequiresConyard = true;
|
||||||
|
public readonly bool PowerDownBuildings = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
74
OpenRA.Game/GameRules/VoiceInfo.cs
Normal file
74
OpenRA.Game/GameRules/VoiceInfo.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class VoiceInfo
|
||||||
|
{
|
||||||
|
public readonly string[] SovietVariants = { ".aud" };
|
||||||
|
public readonly string[] AlliedVariants = { ".aud" };
|
||||||
|
public readonly string[] Select = { };
|
||||||
|
public readonly string[] Move = { };
|
||||||
|
public readonly string[] Attack = null;
|
||||||
|
public readonly string[] Die = { };
|
||||||
|
|
||||||
|
public readonly Lazy<Dictionary<string, VoicePool>> Pools;
|
||||||
|
|
||||||
|
public VoiceInfo()
|
||||||
|
{
|
||||||
|
Pools = Lazy.New(() =>
|
||||||
|
new Dictionary<string, VoicePool>
|
||||||
|
{
|
||||||
|
{ "Select", new VoicePool(Select) },
|
||||||
|
{ "Move", new VoicePool(Move) },
|
||||||
|
{ "Attack", new VoicePool( Attack ?? Move ) },
|
||||||
|
{ "Die", new VoicePool(Die) },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VoicePool
|
||||||
|
{
|
||||||
|
readonly string[] clips;
|
||||||
|
readonly List<string> liveclips = new List<string>();
|
||||||
|
|
||||||
|
public VoicePool(params string[] clips)
|
||||||
|
{
|
||||||
|
this.clips = clips;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetNext()
|
||||||
|
{
|
||||||
|
if (liveclips.Count == 0)
|
||||||
|
liveclips.AddRange(clips);
|
||||||
|
|
||||||
|
if (liveclips.Count == 0)
|
||||||
|
return null; /* avoid crashing if there's no clips at all */
|
||||||
|
|
||||||
|
var i = Game.world.CosmeticRandom.Next(liveclips.Count);
|
||||||
|
var s = liveclips[i];
|
||||||
|
liveclips.RemoveAt(i);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
OpenRA.Game/GameRules/WarheadInfo.cs
Normal file
46
OpenRA.Game/GameRules/WarheadInfo.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class WarheadInfo
|
||||||
|
{
|
||||||
|
public readonly int Spread = 1;
|
||||||
|
public readonly float[] Verses = { 1, 1, 1, 1, 1 };
|
||||||
|
public readonly bool Wall = false;
|
||||||
|
public readonly bool Wood = false;
|
||||||
|
public readonly bool Ore = false;
|
||||||
|
public readonly int Explosion = 0;
|
||||||
|
public readonly int InfDeath = 0;
|
||||||
|
public readonly string ImpactSound = null;
|
||||||
|
public readonly string WaterImpactSound = null;
|
||||||
|
|
||||||
|
public float EffectivenessAgainst(ArmorType at) { return Verses[ (int)at ]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ArmorType
|
||||||
|
{
|
||||||
|
none = 0,
|
||||||
|
wood = 1,
|
||||||
|
light = 2,
|
||||||
|
heavy = 3,
|
||||||
|
concrete = 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
41
OpenRA.Game/GameRules/WeaponInfo.cs
Executable file
41
OpenRA.Game/GameRules/WeaponInfo.cs
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
namespace OpenRA.GameRules
|
||||||
|
{
|
||||||
|
public class WeaponInfo
|
||||||
|
{
|
||||||
|
public readonly int Burst = 1;
|
||||||
|
public readonly bool Charges = false;
|
||||||
|
public readonly int Damage = 0;
|
||||||
|
public readonly string Projectile = "Invisible";
|
||||||
|
public readonly int ROF = 1; // in 1/15 second units.
|
||||||
|
public readonly float Range = 0;
|
||||||
|
public readonly string Report = null;
|
||||||
|
public readonly int Speed = -1;
|
||||||
|
public readonly bool TurboBoost = false;
|
||||||
|
public readonly string Warhead = null;
|
||||||
|
|
||||||
|
public readonly bool RenderAsTesla = false;
|
||||||
|
public readonly bool RenderAsLaser = false;
|
||||||
|
public readonly bool UsePlayerColor = true;
|
||||||
|
public readonly int BeamRadius = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
150
OpenRA.Game/Graphics/Animation.cs
Normal file
150
OpenRA.Game/Graphics/Animation.cs
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
public class Animation
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
public Sequence CurrentSequence { get; private set; }
|
||||||
|
int frame = 0;
|
||||||
|
bool backwards = false;
|
||||||
|
bool tickAlways;
|
||||||
|
|
||||||
|
Func<int> facingFunc;
|
||||||
|
|
||||||
|
public string Name { get { return name; } }
|
||||||
|
|
||||||
|
public Animation( string name )
|
||||||
|
: this( name, () => 0 )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Animation( string name, Func<int> facingFunc )
|
||||||
|
{
|
||||||
|
this.name = name.ToLowerInvariant();
|
||||||
|
this.tickFunc = () => { };
|
||||||
|
this.facingFunc = facingFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite Image
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return backwards
|
||||||
|
? CurrentSequence.GetSprite(CurrentSequence.End - frame - 1, facingFunc())
|
||||||
|
: CurrentSequence.GetSprite(frame, facingFunc());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Play( string sequenceName )
|
||||||
|
{
|
||||||
|
PlayThen(sequenceName, () => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayRepeating( string sequenceName )
|
||||||
|
{
|
||||||
|
PlayThen( sequenceName, () => PlayRepeating( CurrentSequence.Name ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReplaceAnim(string sequenceName)
|
||||||
|
{
|
||||||
|
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||||
|
frame %= CurrentSequence.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayThen( string sequenceName, Action after )
|
||||||
|
{
|
||||||
|
after = after ?? ( () => { } );
|
||||||
|
backwards = false;
|
||||||
|
tickAlways = false;
|
||||||
|
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
|
||||||
|
frame = 0;
|
||||||
|
tickFunc = () =>
|
||||||
|
{
|
||||||
|
++frame;
|
||||||
|
if( frame >= CurrentSequence.Length )
|
||||||
|
{
|
||||||
|
frame = CurrentSequence.Length - 1;
|
||||||
|
tickFunc = () => { };
|
||||||
|
after();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayBackwardsThen(string sequenceName, Action after)
|
||||||
|
{
|
||||||
|
PlayThen(sequenceName, after);
|
||||||
|
backwards = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayFetchIndex( string sequenceName, Func<int> func )
|
||||||
|
{
|
||||||
|
backwards = false;
|
||||||
|
tickAlways = true;
|
||||||
|
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
|
||||||
|
frame = func();
|
||||||
|
tickFunc = () => frame = func();
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeUntilNextFrame;
|
||||||
|
Action tickFunc;
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
Tick( 40 ); // tick one frame
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasSequence(string seq) { return SequenceProvider.HasSequence( name, seq ); }
|
||||||
|
|
||||||
|
public void Tick( int t )
|
||||||
|
{
|
||||||
|
if( tickAlways )
|
||||||
|
tickFunc();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeUntilNextFrame -= t;
|
||||||
|
while( timeUntilNextFrame <= 0 )
|
||||||
|
{
|
||||||
|
tickFunc();
|
||||||
|
timeUntilNextFrame += 40; // 25 fps == 40 ms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangeImage(string newImage)
|
||||||
|
{
|
||||||
|
newImage = newImage.ToLowerInvariant();
|
||||||
|
|
||||||
|
if (name != newImage)
|
||||||
|
{
|
||||||
|
name = newImage.ToLowerInvariant();
|
||||||
|
ReplaceAnim(CurrentSequence.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sequence GetSequence( string sequenceName )
|
||||||
|
{
|
||||||
|
return SequenceProvider.GetSequence( name, sequenceName );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
97
OpenRA.Game/Graphics/ChromeProvider.cs
Normal file
97
OpenRA.Game/Graphics/ChromeProvider.cs
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
static class ChromeProvider
|
||||||
|
{
|
||||||
|
static Dictionary<string, Dictionary<string, MappedImage>> collections;
|
||||||
|
static Dictionary<string, Sheet> cachedSheets;
|
||||||
|
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
|
||||||
|
|
||||||
|
public static void Initialize(params string[] chromeFiles)
|
||||||
|
{
|
||||||
|
collections = new Dictionary<string, Dictionary<string, MappedImage>>();
|
||||||
|
cachedSheets = new Dictionary<string, Sheet>();
|
||||||
|
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
||||||
|
|
||||||
|
foreach (var f in chromeFiles)
|
||||||
|
LoadChromeSource(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadChromeSource(string filename)
|
||||||
|
{
|
||||||
|
XmlDocument document = new XmlDocument();
|
||||||
|
document.Load(FileSystem.Open(filename));
|
||||||
|
foreach (XmlElement eCollection in document.SelectNodes("/chrome/collection"))
|
||||||
|
LoadChromeForCollection(eCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadChromeForCollection(XmlElement eCollection)
|
||||||
|
{
|
||||||
|
string elementName = eCollection.GetAttribute("name");
|
||||||
|
string defaultSrc = (eCollection.HasAttribute("src") ? eCollection.GetAttribute("src") : null);
|
||||||
|
|
||||||
|
var images = eCollection.SelectNodes("./image").OfType<XmlElement>()
|
||||||
|
.Select(e => new MappedImage(defaultSrc, e))
|
||||||
|
.ToDictionary(s => s.Name);
|
||||||
|
|
||||||
|
collections.Add(elementName, images);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sprite GetImage(Renderer renderer, string collection, string image)
|
||||||
|
{
|
||||||
|
// Cached sprite
|
||||||
|
if (cachedSprites.ContainsKey(collection) && cachedSprites[collection].ContainsKey(image))
|
||||||
|
return cachedSprites[collection][image];
|
||||||
|
|
||||||
|
MappedImage mi;
|
||||||
|
try { mi = collections[collection][image]; }
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Collection `{0}` does not have an image `{1}`".F(collection, image));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cached sheet
|
||||||
|
Sheet sheet;
|
||||||
|
if (cachedSheets.ContainsKey(mi.Src))
|
||||||
|
sheet = cachedSheets[mi.Src];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sheet = new Sheet(renderer, mi.Src);
|
||||||
|
cachedSheets.Add(mi.Src, sheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the sprite
|
||||||
|
if (!cachedSprites.ContainsKey(collection))
|
||||||
|
cachedSprites.Add(collection, new Dictionary<string, Sprite>());
|
||||||
|
cachedSprites[collection].Add(image, mi.GetImage(renderer, sheet));
|
||||||
|
|
||||||
|
return cachedSprites[collection][image];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
61
OpenRA.Game/Graphics/CursorSequence.cs
Normal file
61
OpenRA.Game/Graphics/CursorSequence.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class CursorSequence
|
||||||
|
{
|
||||||
|
readonly int start, length;
|
||||||
|
|
||||||
|
public int Start { get { return start; } }
|
||||||
|
public int End { get { return start + length; } }
|
||||||
|
public int Length { get { return length; } }
|
||||||
|
|
||||||
|
public readonly int2 Hotspot;
|
||||||
|
|
||||||
|
Sprite[] sprites;
|
||||||
|
|
||||||
|
public CursorSequence(string cursorSrc, XmlElement e)
|
||||||
|
{
|
||||||
|
sprites = CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||||
|
|
||||||
|
start = int.Parse(e.GetAttribute("start"));
|
||||||
|
|
||||||
|
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||||
|
length = sprites.Length - start;
|
||||||
|
else if (e.HasAttribute("length"))
|
||||||
|
length = int.Parse(e.GetAttribute("length"));
|
||||||
|
else if (e.HasAttribute("end"))
|
||||||
|
length = int.Parse(e.GetAttribute("end")) - start;
|
||||||
|
else
|
||||||
|
length = 1;
|
||||||
|
|
||||||
|
int.TryParse( e.GetAttribute("x"), out Hotspot.X );
|
||||||
|
int.TryParse( e.GetAttribute("y"), out Hotspot.Y );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite GetSprite(int frame)
|
||||||
|
{
|
||||||
|
return sprites[(frame % length) + start];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
OpenRA.Game/Graphics/CursorSheetBuilder.cs
Normal file
48
OpenRA.Game/Graphics/CursorSheetBuilder.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
static class CursorSheetBuilder
|
||||||
|
{
|
||||||
|
static Cache<string, Sprite[]> cursors = new Cache<string, Sprite[]>(LoadCursors);
|
||||||
|
static readonly string[] exts = { ".shp" };
|
||||||
|
|
||||||
|
static Sprite[] LoadCursors(string filename)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||||
|
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, a.Size)).ToArray();
|
||||||
|
}
|
||||||
|
catch (IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp
|
||||||
|
{
|
||||||
|
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||||
|
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||||
|
}
|
||||||
|
}
|
||||||
86
OpenRA.Game/Graphics/HardwarePalette.cs
Normal file
86
OpenRA.Game/Graphics/HardwarePalette.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class HardwarePalette : Sheet
|
||||||
|
{
|
||||||
|
public const int MaxPalettes = 64;
|
||||||
|
int allocated = 0;
|
||||||
|
|
||||||
|
// We need to store the Palettes themselves for the remap palettes to work
|
||||||
|
// We should probably try to fix this somehow
|
||||||
|
static Dictionary<string, Palette> palettes;
|
||||||
|
static Dictionary<string, int> indices;
|
||||||
|
public HardwarePalette(Renderer renderer, Map map)
|
||||||
|
: base(renderer,new Size(256, MaxPalettes))
|
||||||
|
{
|
||||||
|
palettes = new Dictionary<string, Palette>();
|
||||||
|
indices = new Dictionary<string, int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Palette GetPalette(string name)
|
||||||
|
{
|
||||||
|
try { return palettes[name]; }
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Palette `{0}` does not exist".F(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetPaletteIndex(string name)
|
||||||
|
{
|
||||||
|
try { return indices[name]; }
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Palette `{0}` does not exist".F(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int AddPalette(string name, Palette p)
|
||||||
|
{
|
||||||
|
palettes.Add(name, p);
|
||||||
|
indices.Add(name, allocated);
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
this[new Point(i, allocated)] = p.GetColor(i);
|
||||||
|
}
|
||||||
|
return allocated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(IEnumerable<IPaletteModifier> paletteMods)
|
||||||
|
{
|
||||||
|
var b = new Bitmap(Bitmap);
|
||||||
|
foreach (var mod in paletteMods)
|
||||||
|
mod.AdjustPalette(b);
|
||||||
|
|
||||||
|
Texture.SetData(b);
|
||||||
|
Game.renderer.PaletteTexture = Texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
89
OpenRA.Game/Graphics/LineRenderer.cs
Normal file
89
OpenRA.Game/Graphics/LineRenderer.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.FileFormats.Graphics;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class LineRenderer
|
||||||
|
{
|
||||||
|
Renderer renderer;
|
||||||
|
IVertexBuffer<Vertex> vertexBuffer;
|
||||||
|
IIndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */
|
||||||
|
|
||||||
|
const int linesPerBatch = 1024;
|
||||||
|
|
||||||
|
Vertex[] vertices = new Vertex[ 2 * linesPerBatch ];
|
||||||
|
ushort[] indices = new ushort[ 2 * linesPerBatch ];
|
||||||
|
int lines = 0;
|
||||||
|
int nv = 0, ni = 0;
|
||||||
|
|
||||||
|
public LineRenderer( Renderer renderer )
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
vertexBuffer = renderer.Device.CreateVertexBuffer(vertices.Length );
|
||||||
|
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
if( lines > 0 )
|
||||||
|
{
|
||||||
|
renderer.LineShader.Render( () =>
|
||||||
|
{
|
||||||
|
vertexBuffer.SetData( vertices );
|
||||||
|
indexBuffer.SetData( indices );
|
||||||
|
renderer.DrawBatch( vertexBuffer, indexBuffer,
|
||||||
|
nv, ni / 2, null, PrimitiveType.LineList );
|
||||||
|
} );
|
||||||
|
|
||||||
|
nv = 0; ni = 0;
|
||||||
|
lines = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawLine( float2 start, float2 end, Color startColor, Color endColor )
|
||||||
|
{
|
||||||
|
indices[ ni++ ] = (ushort)nv;
|
||||||
|
|
||||||
|
vertices[ nv++ ] = new Vertex( start,
|
||||||
|
new float2( startColor.R / 255.0f, startColor.G / 255.0f ),
|
||||||
|
new float2( startColor.B / 255.0f, startColor.A / 255.0f ) );
|
||||||
|
|
||||||
|
indices[ ni++ ] = (ushort)nv;
|
||||||
|
|
||||||
|
vertices[ nv++ ] = new Vertex( end,
|
||||||
|
new float2( endColor.R / 255.0f, endColor.G / 255.0f ),
|
||||||
|
new float2( endColor.B / 255.0f, endColor.A / 255.0f ) );
|
||||||
|
|
||||||
|
if( ++lines >= linesPerBatch )
|
||||||
|
Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FillRect( RectangleF r, Color color )
|
||||||
|
{
|
||||||
|
for (float y = r.Top; y < r.Bottom; y++)
|
||||||
|
{
|
||||||
|
DrawLine(new float2(r.Left, y), new float2(r.Right, y), color, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
OpenRA.Game/Graphics/MappedImage.cs
Normal file
51
OpenRA.Game/Graphics/MappedImage.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class MappedImage
|
||||||
|
{
|
||||||
|
readonly Rectangle rect;
|
||||||
|
public readonly string Src;
|
||||||
|
public readonly string Name;
|
||||||
|
|
||||||
|
public MappedImage(string defaultSrc, XmlElement e)
|
||||||
|
{
|
||||||
|
Src = (e.HasAttribute("src")) ? e.GetAttribute("src") : defaultSrc;
|
||||||
|
Name = e.GetAttribute("name");
|
||||||
|
if (Src == null)
|
||||||
|
throw new InvalidDataException("Image src missing");
|
||||||
|
|
||||||
|
rect = new Rectangle(int.Parse(e.GetAttribute("x")),
|
||||||
|
int.Parse(e.GetAttribute("y")),
|
||||||
|
int.Parse(e.GetAttribute("width")),
|
||||||
|
int.Parse(e.GetAttribute("height")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite GetImage(Renderer r, Sheet s)
|
||||||
|
{
|
||||||
|
return new Sprite(s, rect, TextureChannel.Alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
213
OpenRA.Game/Graphics/Minimap.cs
Normal file
213
OpenRA.Game/Graphics/Minimap.cs
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class Minimap
|
||||||
|
{
|
||||||
|
readonly World world;
|
||||||
|
Sheet sheet, mapOnlySheet;
|
||||||
|
SpriteRenderer rgbaRenderer;
|
||||||
|
LineRenderer lineRenderer;
|
||||||
|
Sprite sprite, mapOnlySprite;
|
||||||
|
Bitmap terrain, oreLayer;
|
||||||
|
Rectangle bounds;
|
||||||
|
|
||||||
|
Sprite ownedSpawnPoint;
|
||||||
|
Sprite unownedSpawnPoint;
|
||||||
|
|
||||||
|
const int alpha = 230;
|
||||||
|
|
||||||
|
public void Tick() { }
|
||||||
|
|
||||||
|
public Minimap(World world, Renderer r)
|
||||||
|
{
|
||||||
|
this.world = world;
|
||||||
|
sheet = new Sheet(r, new Size(128, 128));
|
||||||
|
mapOnlySheet = new Sheet(r, new Size(128, 128));
|
||||||
|
|
||||||
|
lineRenderer = new LineRenderer(r);
|
||||||
|
rgbaRenderer = new SpriteRenderer(r, true, r.RgbaSpriteShader);
|
||||||
|
var size = Math.Max(world.Map.Width, world.Map.Height);
|
||||||
|
var dw = (size - world.Map.Width) / 2;
|
||||||
|
var dh = (size - world.Map.Height) / 2;
|
||||||
|
|
||||||
|
bounds = new Rectangle(world.Map.Offset.X - dw, world.Map.Offset.Y - dh, size, size);
|
||||||
|
|
||||||
|
sprite = new Sprite(sheet, bounds, TextureChannel.Alpha);
|
||||||
|
mapOnlySprite = new Sprite(mapOnlySheet, bounds, TextureChannel.Alpha);
|
||||||
|
|
||||||
|
shroudColor = Color.FromArgb(alpha, Color.Black);
|
||||||
|
|
||||||
|
ownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "owned");
|
||||||
|
unownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "unowned");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Rectangle MakeMinimapBounds(Map m)
|
||||||
|
{
|
||||||
|
var size = Math.Max(m.Width, m.Height);
|
||||||
|
var dw = (size - m.Width) / 2;
|
||||||
|
var dh = (size - m.Height) / 2;
|
||||||
|
|
||||||
|
return new Rectangle(m.Offset.X - dw, m.Offset.Y - dh, size, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Cache<string, Color[]> terrainTypeColors = new Cache<string, Color[]>(
|
||||||
|
theater =>
|
||||||
|
{
|
||||||
|
var pal = Game.world.WorldRenderer.GetPalette("terrain");
|
||||||
|
return new[] {
|
||||||
|
theater == "snow" ? 0xe3 :0x1a,
|
||||||
|
0x63, 0x2f, 0x1f, 0x14, 0x64, 0x1f, 0x68, 0x6b, 0x6d, 0x88 }
|
||||||
|
.Select(a => Color.FromArgb(alpha, pal.GetColor(a))).ToArray();
|
||||||
|
});
|
||||||
|
|
||||||
|
static Color shroudColor;
|
||||||
|
|
||||||
|
public void InvalidateOre() { oreLayer = null; }
|
||||||
|
|
||||||
|
public static Bitmap RenderTerrainBitmap(Map map, TileSet tileset)
|
||||||
|
{
|
||||||
|
var colors = terrainTypeColors[map.Theater.ToLowerInvariant()];
|
||||||
|
var terrain = new Bitmap(128, 128);
|
||||||
|
for (var y = 0; y < 128; y++)
|
||||||
|
for (var x = 0; x < 128; x++)
|
||||||
|
terrain.SetPixel(x, y, map.IsInMap(x, y)
|
||||||
|
? colors[tileset.GetWalkability(map.MapTiles[x, y])]
|
||||||
|
: shroudColor);
|
||||||
|
return terrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap RenderTerrainBitmapWithSpawnPoints(Map map, TileSet tileset)
|
||||||
|
{
|
||||||
|
/* todo: do this a bit nicer */
|
||||||
|
|
||||||
|
var terrain = RenderTerrainBitmap(map, tileset);
|
||||||
|
foreach (var sp in map.SpawnPoints)
|
||||||
|
terrain.SetPixel(sp.X, sp.Y, Color.White);
|
||||||
|
|
||||||
|
return terrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (terrain == null)
|
||||||
|
terrain = RenderTerrainBitmap(world.Map, world.TileSet);
|
||||||
|
|
||||||
|
if (oreLayer == null)
|
||||||
|
{
|
||||||
|
var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()];
|
||||||
|
oreLayer = new Bitmap(terrain);
|
||||||
|
for (var y = world.Map.YOffset; y < world.Map.YOffset + world.Map.Height; y++)
|
||||||
|
for (var x = world.Map.XOffset; x < world.Map.XOffset + world.Map.Width; x++)
|
||||||
|
if (world.Map.ContainsResource(new int2(x, y)))
|
||||||
|
oreLayer.SetPixel(x, y, colors[(int)TerrainMovementType.Ore]);
|
||||||
|
}
|
||||||
|
|
||||||
|
mapOnlySheet.Texture.SetData(oreLayer);
|
||||||
|
|
||||||
|
if (!world.Queries.OwnedBy[world.LocalPlayer].WithTrait<ProvidesRadar>().Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bitmap = new Bitmap(oreLayer);
|
||||||
|
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||||
|
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()];
|
||||||
|
int* c = (int*)bitmapData.Scan0;
|
||||||
|
|
||||||
|
foreach (var a in world.Queries.WithTrait<Unit>().Where( a => a.Actor.Owner != null ))
|
||||||
|
*(c + (a.Actor.Location.Y * bitmapData.Stride >> 2) + a.Actor.Location.X) =
|
||||||
|
Color.FromArgb(alpha, a.Actor.Owner.Color).ToArgb();
|
||||||
|
|
||||||
|
for (var y = world.Map.YOffset; y < world.Map.YOffset + world.Map.Height; y++)
|
||||||
|
for (var x = world.Map.XOffset; x < world.Map.XOffset + world.Map.Width; x++)
|
||||||
|
{
|
||||||
|
if (!world.LocalPlayer.Shroud.DisplayOnRadar(x, y))
|
||||||
|
{
|
||||||
|
*(c + (y * bitmapData.Stride >> 2) + x) = shroudColor.ToArgb();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var b = world.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt(new int2(x, y));
|
||||||
|
if (b != null)
|
||||||
|
*(c + (y * bitmapData.Stride >> 2) + x) =
|
||||||
|
(b.Owner != null ? Color.FromArgb(alpha, b.Owner.Color) : colors[4]).ToArgb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap.UnlockBits(bitmapData);
|
||||||
|
sheet.Texture.SetData(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(RectangleF rect, bool mapOnly)
|
||||||
|
{
|
||||||
|
rgbaRenderer.DrawSprite(mapOnly ? mapOnlySprite : sprite,
|
||||||
|
new float2(rect.X, rect.Y), "chrome", new float2(rect.Width, rect.Height));
|
||||||
|
rgbaRenderer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int2 TransformCellToMinimapPixel(RectangleF viewRect, int2 p)
|
||||||
|
{
|
||||||
|
var fx = (float)(p.X - bounds.X) / bounds.Width;
|
||||||
|
var fy = (float)(p.Y - bounds.Y) / bounds.Height;
|
||||||
|
|
||||||
|
return new int2(
|
||||||
|
(int)(viewRect.Width * fx + viewRect.Left) - 8,
|
||||||
|
(int)(viewRect.Height * fy + viewRect.Top) - 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawSpawnPoints(RectangleF rect)
|
||||||
|
{
|
||||||
|
var points = world.Map.SpawnPoints
|
||||||
|
.Select( (sp,i) => Pair.New(sp,world.players.Values.FirstOrDefault(
|
||||||
|
p => p.SpawnPointIndex == i + 1 ) ))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var p in points)
|
||||||
|
{
|
||||||
|
var pos = TransformCellToMinimapPixel(rect, p.First);
|
||||||
|
|
||||||
|
if (p.Second == null)
|
||||||
|
rgbaRenderer.DrawSprite(unownedSpawnPoint, pos, "chrome");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineRenderer.FillRect(new RectangleF(
|
||||||
|
Game.viewport.Location.X + pos.X + 2,
|
||||||
|
Game.viewport.Location.Y + pos.Y + 2,
|
||||||
|
12, 12), p.Second.Color);
|
||||||
|
|
||||||
|
rgbaRenderer.DrawSprite(ownedSpawnPoint, pos, "chrome");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lineRenderer.Flush();
|
||||||
|
rgbaRenderer.Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
114
OpenRA.Game/Graphics/OverlayRenderer.cs
Executable file
114
OpenRA.Game/Graphics/OverlayRenderer.cs
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class OverlayRenderer
|
||||||
|
{
|
||||||
|
static string[] overlaySpriteNames =
|
||||||
|
{
|
||||||
|
"sbag", "cycl", "brik", "fenc", "wood",
|
||||||
|
"gold01", "gold02", "gold03", "gold04",
|
||||||
|
"gem01", "gem02", "gem03", "gem04",
|
||||||
|
"v12", "v13", "v14", "v15", "v16", "v17", "v18",
|
||||||
|
"fpls", "wcrate", "scrate", "barb", "sbag",
|
||||||
|
};
|
||||||
|
|
||||||
|
static string[] smudgeSpriteNames =
|
||||||
|
{
|
||||||
|
"bib3", "bib2", "bib1", "sc1", "sc2", "sc3", "sc4", "sc5", "sc6",
|
||||||
|
"cr1", "cr2", "cr3", "cr4", "cr5", "cr6",
|
||||||
|
};
|
||||||
|
|
||||||
|
readonly Sprite[][] overlaySprites;
|
||||||
|
readonly Sprite[] smudgeSprites;
|
||||||
|
|
||||||
|
SpriteRenderer spriteRenderer;
|
||||||
|
Map map;
|
||||||
|
|
||||||
|
public OverlayRenderer( Renderer renderer, Map map )
|
||||||
|
{
|
||||||
|
this.spriteRenderer = new SpriteRenderer( renderer, true );
|
||||||
|
this.map = map;
|
||||||
|
|
||||||
|
overlaySprites = overlaySpriteNames.Select(f => SpriteSheetBuilder.LoadAllSprites(f)).ToArray();
|
||||||
|
smudgeSprites = smudgeSpriteNames.SelectMany(f => SpriteSheetBuilder.LoadAllSprites(f)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
var shroud = Game.world.LocalPlayer.Shroud;
|
||||||
|
|
||||||
|
for (int y = map.YOffset; y < map.YOffset + map.Height; y++)
|
||||||
|
for (int x = map.XOffset; x < map.XOffset + map.Width; x++)
|
||||||
|
{
|
||||||
|
if (!shroud.IsExplored(new int2(x,y))) continue;
|
||||||
|
|
||||||
|
var tr = map.MapTiles[x,y];
|
||||||
|
if (tr.smudge != 0 && tr.smudge <= smudgeSprites.Length)
|
||||||
|
{
|
||||||
|
var location = new int2(x, y);
|
||||||
|
spriteRenderer.DrawSprite(smudgeSprites[tr.smudge - 1],
|
||||||
|
Game.CellSize * (float2)location, "terrain");
|
||||||
|
}
|
||||||
|
|
||||||
|
var o = tr.overlay;
|
||||||
|
if (o < overlaySprites.Length)
|
||||||
|
{
|
||||||
|
var location = new int2(x, y);
|
||||||
|
var sprites = overlaySprites[o];
|
||||||
|
var spriteIndex = 0;
|
||||||
|
if (Ore.overlayIsFence[o]) spriteIndex = NearbyFences(x, y);
|
||||||
|
else if (Ore.overlayIsOre[o]) spriteIndex = map.MapTiles[x,y].density - 1;
|
||||||
|
else if (Ore.overlayIsGems[o]) spriteIndex = map.MapTiles[x,y].density - 1;
|
||||||
|
spriteRenderer.DrawSprite(sprites[spriteIndex],
|
||||||
|
Game.CellSize * (float2)location, "terrain");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spriteRenderer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFence( int x, int y )
|
||||||
|
{
|
||||||
|
var o = map.MapTiles[ x, y ].overlay;
|
||||||
|
if (o < Ore.overlayIsFence.Length)
|
||||||
|
return Ore.overlayIsFence[o];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NearbyFences( int x, int y )
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if( IsFence( x, y - 1 ) )
|
||||||
|
ret |= 1;
|
||||||
|
if( IsFence( x + 1, y ) )
|
||||||
|
ret |= 2;
|
||||||
|
if( IsFence( x, y + 1 ) )
|
||||||
|
ret |= 4;
|
||||||
|
if( IsFence( x - 1, y ) )
|
||||||
|
ret |= 8;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
134
OpenRA.Game/Graphics/Renderer.cs
Normal file
134
OpenRA.Game/Graphics/Renderer.cs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.FileFormats.Graphics;
|
||||||
|
using OpenRA.Support;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
internal class Renderer
|
||||||
|
{
|
||||||
|
internal static int SheetSize;
|
||||||
|
|
||||||
|
readonly IGraphicsDevice device;
|
||||||
|
|
||||||
|
public IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||||
|
public IShader LineShader { get; private set; }
|
||||||
|
public IShader RgbaSpriteShader { get; private set; }
|
||||||
|
public IShader WorldSpriteShader { get; private set; }
|
||||||
|
|
||||||
|
public ITexture PaletteTexture;
|
||||||
|
|
||||||
|
public readonly SpriteFont RegularFont, BoldFont;
|
||||||
|
|
||||||
|
public Size Resolution { get { return device.WindowSize; } }
|
||||||
|
|
||||||
|
public Renderer(Size resolution, bool windowed)
|
||||||
|
{
|
||||||
|
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowed, false );
|
||||||
|
|
||||||
|
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
|
||||||
|
LineShader = device.CreateShader(FileSystem.Open("shaders/line.fx"));
|
||||||
|
RgbaSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-rgba.fx"));
|
||||||
|
WorldSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-shp.fx"));
|
||||||
|
|
||||||
|
// RegularFont = device.CreateFont( "FreeSans.ttf" );
|
||||||
|
// BoldFont = device.CreateFont( "FreeSansBold.ttf" );
|
||||||
|
|
||||||
|
RegularFont = new SpriteFont(this, "FreeSans.ttf", 14);
|
||||||
|
BoldFont = new SpriteFont(this, "FreeSansBold.ttf", 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, bool windowed, bool vsync )
|
||||||
|
{
|
||||||
|
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
|
||||||
|
{
|
||||||
|
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( bool ), typeof( bool ) } )
|
||||||
|
.Invoke( new object[] { width, height, windowed, vsync } );
|
||||||
|
}
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IGraphicsDevice Device { get { return device; } }
|
||||||
|
|
||||||
|
public void BeginFrame(float2 r1, float2 r2, float2 scroll)
|
||||||
|
{
|
||||||
|
device.Begin();
|
||||||
|
device.Clear(Color.Black);
|
||||||
|
|
||||||
|
SetShaderParams( SpriteShader, r1, r2, scroll );
|
||||||
|
SetShaderParams( LineShader, r1, r2, scroll );
|
||||||
|
SetShaderParams( RgbaSpriteShader, r1, r2, scroll );
|
||||||
|
SetShaderParams( WorldSpriteShader, r1, r2, scroll );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
|
||||||
|
{
|
||||||
|
s.SetValue( "Palette", PaletteTexture );
|
||||||
|
s.SetValue( "Scroll", scroll.X, scroll.Y );
|
||||||
|
s.SetValue( "r1", r1.X, r1.Y );
|
||||||
|
s.SetValue( "r2", r2.X, r2.Y );
|
||||||
|
s.Commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndFrame()
|
||||||
|
{
|
||||||
|
device.End();
|
||||||
|
device.Present();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||||
|
Range<int> vertexRange, Range<int> indexRange, ITexture texture, PrimitiveType type, IShader shader)
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
shader.SetValue("DiffuseTexture", texture);
|
||||||
|
shader.Commit();
|
||||||
|
|
||||||
|
vertices.Bind();
|
||||||
|
indices.Bind();
|
||||||
|
|
||||||
|
device.DrawIndexedPrimitives(type, vertexRange, indexRange);
|
||||||
|
|
||||||
|
PerfHistory.Increment("batches", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||||
|
int vertexPool, int numPrimitives, ITexture texture, PrimitiveType type)
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
SpriteShader.SetValue("DiffuseTexture", texture);
|
||||||
|
SpriteShader.Commit();
|
||||||
|
|
||||||
|
vertices.Bind();
|
||||||
|
indices.Bind();
|
||||||
|
|
||||||
|
device.DrawIndexedPrimitives(type, vertexPool, numPrimitives);
|
||||||
|
|
||||||
|
PerfHistory.Increment("batches", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
70
OpenRA.Game/Graphics/Sequence.cs
Normal file
70
OpenRA.Game/Graphics/Sequence.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
public class Sequence
|
||||||
|
{
|
||||||
|
readonly Sprite[] sprites;
|
||||||
|
readonly int start, length, facings;
|
||||||
|
|
||||||
|
public readonly string Name;
|
||||||
|
public int Start { get { return start; } }
|
||||||
|
public int End { get { return start + length; } }
|
||||||
|
public int Length { get { return length; } }
|
||||||
|
public int Facings { get { return facings; } }
|
||||||
|
|
||||||
|
public Sequence(string unit, XmlElement e)
|
||||||
|
{
|
||||||
|
string srcOverride = e.GetAttribute("src");
|
||||||
|
Name = e.GetAttribute("name");
|
||||||
|
|
||||||
|
sprites = SpriteSheetBuilder.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
|
||||||
|
start = int.Parse(e.GetAttribute("start"));
|
||||||
|
|
||||||
|
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||||
|
length = sprites.Length - Start;
|
||||||
|
else if (e.HasAttribute("length"))
|
||||||
|
length = int.Parse(e.GetAttribute("length"));
|
||||||
|
else if (e.HasAttribute("end"))
|
||||||
|
length = int.Parse(e.GetAttribute("end")) - int.Parse(e.GetAttribute("start"));
|
||||||
|
else
|
||||||
|
length = 1;
|
||||||
|
|
||||||
|
if( e.HasAttribute( "facings" ) )
|
||||||
|
facings = int.Parse( e.GetAttribute( "facings" ) );
|
||||||
|
else
|
||||||
|
facings = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite GetSprite( int frame )
|
||||||
|
{
|
||||||
|
return GetSprite( frame, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite GetSprite(int frame, int facing)
|
||||||
|
{
|
||||||
|
var f = Traits.Util.QuantizeFacing( facing, facings );
|
||||||
|
return sprites[ (f * length) + ( frame % length ) + start ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
101
OpenRA.Game/Graphics/SequenceProvider.cs
Normal file
101
OpenRA.Game/Graphics/SequenceProvider.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
static class SequenceProvider
|
||||||
|
{
|
||||||
|
static Dictionary<string, Dictionary<string, Sequence>> units;
|
||||||
|
static Dictionary<string, CursorSequence> cursors;
|
||||||
|
|
||||||
|
public static void Initialize(params string[] sequenceFiles)
|
||||||
|
{
|
||||||
|
units = new Dictionary<string, Dictionary<string, Sequence>>();
|
||||||
|
cursors = new Dictionary<string, CursorSequence>();
|
||||||
|
|
||||||
|
foreach (var f in sequenceFiles)
|
||||||
|
LoadSequenceSource(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadSequenceSource(string filename)
|
||||||
|
{
|
||||||
|
XmlDocument document = new XmlDocument();
|
||||||
|
document.Load(FileSystem.Open(filename));
|
||||||
|
|
||||||
|
foreach (XmlElement eUnit in document.SelectNodes("/sequences/unit"))
|
||||||
|
LoadSequencesForUnit(eUnit);
|
||||||
|
|
||||||
|
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||||
|
LoadSequencesForCursor(eCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||||
|
{
|
||||||
|
string cursorSrc = eCursor.GetAttribute("src");
|
||||||
|
|
||||||
|
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
|
||||||
|
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, eSequence));
|
||||||
|
|
||||||
|
Log.Write("* LoadSequencesForCursor() done");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LoadSequencesForUnit(XmlElement eUnit)
|
||||||
|
{
|
||||||
|
string unitName = eUnit.GetAttribute("name");
|
||||||
|
Log.Write("Loading sequence {0}", unitName);
|
||||||
|
var sequences = eUnit.SelectNodes("./sequence").OfType<XmlElement>()
|
||||||
|
.Select(e => new Sequence(unitName, e))
|
||||||
|
.ToDictionary(s => s.Name);
|
||||||
|
|
||||||
|
units.Add(unitName, sequences);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||||
|
{
|
||||||
|
try { return units[unitName][sequenceName]; }
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasSequence(string unit, string seq)
|
||||||
|
{
|
||||||
|
return units[unit].ContainsKey(seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CursorSequence GetCursorSequence(string cursor)
|
||||||
|
{
|
||||||
|
try { return cursors[cursor]; }
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
OpenRA.Game/Graphics/Sheet.cs
Normal file
72
OpenRA.Game/Graphics/Sheet.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.FileFormats.Graphics;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
public class Sheet
|
||||||
|
{
|
||||||
|
readonly Renderer renderer;
|
||||||
|
protected readonly Bitmap bitmap;
|
||||||
|
|
||||||
|
ITexture texture;
|
||||||
|
|
||||||
|
internal Sheet(Renderer renderer, Size size)
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
this.bitmap = new Bitmap(size.Width, size.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Sheet(Renderer renderer, string filename)
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
this.bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resolve()
|
||||||
|
{
|
||||||
|
texture = renderer.Device.CreateTexture(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITexture Texture
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (texture == null)
|
||||||
|
Resolve();
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size Size { get { return bitmap.Size; } }
|
||||||
|
|
||||||
|
protected Color this[Point p]
|
||||||
|
{
|
||||||
|
get { return bitmap.GetPixel(p.X, p.Y); }
|
||||||
|
set { bitmap.SetPixel(p.X, p.Y, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bitmap Bitmap { get { return bitmap; } } // for perf
|
||||||
|
}
|
||||||
|
}
|
||||||
119
OpenRA.Game/Graphics/SheetBuilder.cs
Normal file
119
OpenRA.Game/Graphics/SheetBuilder.cs
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class SheetBuilder
|
||||||
|
{
|
||||||
|
public static SheetBuilder SharedInstance;
|
||||||
|
public static void Initialize(Renderer r)
|
||||||
|
{
|
||||||
|
SharedInstance = new SheetBuilder(r, TextureChannel.Red);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SheetBuilder(Renderer r, TextureChannel ch)
|
||||||
|
{
|
||||||
|
renderer = r;
|
||||||
|
current = null;
|
||||||
|
rowHeight = 0;
|
||||||
|
channel = null;
|
||||||
|
initialChannel = ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite Add(byte[] src, Size size)
|
||||||
|
{
|
||||||
|
Sprite rect = Allocate(size);
|
||||||
|
Util.FastCopyIntoChannel(rect, src);
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite Add(Size size, byte paletteIndex)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[size.Width * size.Height];
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
data[i] = paletteIndex;
|
||||||
|
|
||||||
|
return Add(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sheet NewSheet() { return new Sheet( renderer, new Size( Renderer.SheetSize, Renderer.SheetSize ) ); }
|
||||||
|
|
||||||
|
Renderer renderer;
|
||||||
|
Sheet current = null;
|
||||||
|
int rowHeight = 0;
|
||||||
|
Point p;
|
||||||
|
TextureChannel? channel = null;
|
||||||
|
TextureChannel initialChannel;
|
||||||
|
|
||||||
|
TextureChannel? NextChannel(TextureChannel? t)
|
||||||
|
{
|
||||||
|
if (t == null)
|
||||||
|
return initialChannel;
|
||||||
|
|
||||||
|
switch (t.Value)
|
||||||
|
{
|
||||||
|
case TextureChannel.Red: return TextureChannel.Green;
|
||||||
|
case TextureChannel.Green: return TextureChannel.Blue;
|
||||||
|
case TextureChannel.Blue: return TextureChannel.Alpha;
|
||||||
|
case TextureChannel.Alpha: return null;
|
||||||
|
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Sprite Allocate(Size imageSize)
|
||||||
|
{
|
||||||
|
if (current == null)
|
||||||
|
{
|
||||||
|
current = NewSheet();
|
||||||
|
channel = NextChannel(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageSize.Width + p.X > current.Size.Width)
|
||||||
|
{
|
||||||
|
p = new Point(0, p.Y + rowHeight);
|
||||||
|
rowHeight = imageSize.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageSize.Height > rowHeight)
|
||||||
|
rowHeight = imageSize.Height;
|
||||||
|
|
||||||
|
if (p.Y + imageSize.Height > current.Size.Height)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (null == (channel = NextChannel(channel)))
|
||||||
|
{
|
||||||
|
current = NewSheet();
|
||||||
|
channel = NextChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
rowHeight = imageSize.Height;
|
||||||
|
p = new Point(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite rect = new Sprite(current, new Rectangle(p, imageSize), channel.Value);
|
||||||
|
p.X += imageSize.Width;
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
71
OpenRA.Game/Graphics/Sprite.cs
Normal file
71
OpenRA.Game/Graphics/Sprite.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
public class Sprite
|
||||||
|
{
|
||||||
|
public readonly Rectangle bounds;
|
||||||
|
public readonly Sheet sheet;
|
||||||
|
public readonly TextureChannel channel;
|
||||||
|
public readonly RectangleF uv;
|
||||||
|
public readonly float2 size;
|
||||||
|
|
||||||
|
readonly float2[] uvhax;
|
||||||
|
|
||||||
|
internal Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel)
|
||||||
|
{
|
||||||
|
this.bounds = bounds;
|
||||||
|
this.sheet = sheet;
|
||||||
|
this.channel = channel;
|
||||||
|
|
||||||
|
uv = new RectangleF(
|
||||||
|
(float)(bounds.Left) / sheet.Size.Width,
|
||||||
|
(float)(bounds.Top) / sheet.Size.Height,
|
||||||
|
(float)(bounds.Width) / sheet.Size.Width,
|
||||||
|
(float)(bounds.Height) / sheet.Size.Height);
|
||||||
|
|
||||||
|
uvhax = new float2[]
|
||||||
|
{
|
||||||
|
new float2( uv.Left, uv.Top ),
|
||||||
|
new float2( uv.Right, uv.Top ),
|
||||||
|
new float2( uv.Left, uv.Bottom ),
|
||||||
|
new float2( uv.Right, uv.Bottom ),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.size = new float2(bounds.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2 FastMapTextureCoords( int k )
|
||||||
|
{
|
||||||
|
return uvhax[ k ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TextureChannel
|
||||||
|
{
|
||||||
|
Red = 0,
|
||||||
|
Green = 1,
|
||||||
|
Blue = 2,
|
||||||
|
Alpha = 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
116
OpenRA.Game/Graphics/SpriteFont.cs
Normal file
116
OpenRA.Game/Graphics/SpriteFont.cs
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using Tao.FreeType;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class SpriteFont
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
public SpriteFont(Renderer r, string name, int size)
|
||||||
|
{
|
||||||
|
this.size = size;
|
||||||
|
|
||||||
|
if (0 != FT.FT_New_Face(library, name, 0, out face))
|
||||||
|
throw new InvalidOperationException("FT_New_Face failed");
|
||||||
|
|
||||||
|
FT.FT_Set_Pixel_Sizes(face, 0, (uint)size);
|
||||||
|
glyphs = new Cache<char, GlyphInfo>(CreateGlyph);
|
||||||
|
|
||||||
|
// setup a 1-channel SheetBuilder for our private use
|
||||||
|
if (builder == null) builder = new SheetBuilder(r, TextureChannel.Alpha);
|
||||||
|
|
||||||
|
// precache glyphs for U+0020 - U+007f
|
||||||
|
for (var n = (char)0x20; n < (char)0x7f; n++)
|
||||||
|
if (glyphs[n] == null)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawText(SpriteRenderer r, string text, float2 location, Color c)
|
||||||
|
{
|
||||||
|
location.Y += size; // baseline vs top
|
||||||
|
|
||||||
|
var p = location;
|
||||||
|
foreach (var s in text)
|
||||||
|
{
|
||||||
|
if (s == '\n')
|
||||||
|
{
|
||||||
|
location.Y += size;
|
||||||
|
p = location;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var g = glyphs[s];
|
||||||
|
r.DrawSprite(g.Sprite,
|
||||||
|
new float2(
|
||||||
|
(int)Math.Round(p.X + g.Offset.X, 0),
|
||||||
|
p.Y + g.Offset.Y),
|
||||||
|
"chrome");
|
||||||
|
p.X += g.Advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int2 Measure(string text)
|
||||||
|
{
|
||||||
|
return new int2((int)text.Split( '\n' ).Max( s => s.Sum(a => glyphs[a].Advance)), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache<char, GlyphInfo> glyphs;
|
||||||
|
IntPtr face;
|
||||||
|
|
||||||
|
GlyphInfo CreateGlyph(char c)
|
||||||
|
{
|
||||||
|
var index = FT.FT_Get_Char_Index(face, (uint)c);
|
||||||
|
FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER);
|
||||||
|
|
||||||
|
var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
|
||||||
|
var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec));
|
||||||
|
|
||||||
|
var s = builder.Allocate(new Size(_glyph.metrics.width >> 6, _glyph.metrics.height >> 6));
|
||||||
|
|
||||||
|
var g = new GlyphInfo
|
||||||
|
{
|
||||||
|
Sprite = s,
|
||||||
|
Advance = _glyph.metrics.horiAdvance / 64f,
|
||||||
|
Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top }
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var p = (byte*)_glyph.bitmap.buffer;
|
||||||
|
|
||||||
|
for (var j = 0; j < s.size.Y; j++)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < s.size.X; i++)
|
||||||
|
if (p[i] != 0)
|
||||||
|
s.sheet.Bitmap.SetPixel(i + s.bounds.Left, j + s.bounds.Top,
|
||||||
|
Color.FromArgb(p[i], 0xff, 0xff, 0xff));
|
||||||
|
|
||||||
|
p += _glyph.bitmap.pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SpriteFont()
|
||||||
|
{
|
||||||
|
FT.FT_Init_FreeType(out library);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IntPtr library;
|
||||||
|
static SheetBuilder builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GlyphInfo
|
||||||
|
{
|
||||||
|
public float Advance;
|
||||||
|
public int2 Offset;
|
||||||
|
public Sprite Sprite;
|
||||||
|
}
|
||||||
|
}
|
||||||
91
OpenRA.Game/Graphics/SpriteRenderer.cs
Normal file
91
OpenRA.Game/Graphics/SpriteRenderer.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using OpenRA.FileFormats.Graphics;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class SpriteRenderer
|
||||||
|
{
|
||||||
|
IVertexBuffer<Vertex> vertexBuffer;
|
||||||
|
IIndexBuffer indexBuffer;
|
||||||
|
Renderer renderer;
|
||||||
|
IShader shader;
|
||||||
|
|
||||||
|
const int spritesPerBatch = 1024;
|
||||||
|
|
||||||
|
Vertex[] vertices = new Vertex[4 * spritesPerBatch];
|
||||||
|
ushort[] indices = new ushort[6 * spritesPerBatch];
|
||||||
|
Sheet currentSheet = null;
|
||||||
|
int sprites = 0;
|
||||||
|
int nv = 0, ni = 0;
|
||||||
|
|
||||||
|
public SpriteRenderer(Renderer renderer, bool allowAlpha, IShader shader)
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
this.shader = shader;
|
||||||
|
|
||||||
|
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||||
|
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SpriteRenderer(Renderer renderer, bool allowAlpha)
|
||||||
|
: this(renderer, allowAlpha, renderer.SpriteShader) { }
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
if (sprites > 0)
|
||||||
|
{
|
||||||
|
shader.SetValue( "DiffuseTexture", currentSheet.Texture );
|
||||||
|
shader.Render(() =>
|
||||||
|
{
|
||||||
|
vertexBuffer.SetData(vertices);
|
||||||
|
indexBuffer.SetData(indices);
|
||||||
|
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||||
|
new Range<int>(0, nv),
|
||||||
|
new Range<int>(0, ni),
|
||||||
|
currentSheet.Texture, PrimitiveType.TriangleList,
|
||||||
|
shader);
|
||||||
|
});
|
||||||
|
|
||||||
|
nv = 0; ni = 0;
|
||||||
|
currentSheet = null;
|
||||||
|
sprites = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawSprite(Sprite s, float2 location, string palette)
|
||||||
|
{
|
||||||
|
DrawSprite(s, location, palette, s.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawSprite(Sprite s, float2 location, string palette, float2 size)
|
||||||
|
{
|
||||||
|
if (s.sheet != currentSheet)
|
||||||
|
Flush();
|
||||||
|
|
||||||
|
currentSheet = s.sheet;
|
||||||
|
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, Game.world.WorldRenderer.GetPaletteIndex(palette), nv, ni, size);
|
||||||
|
nv += 4; ni += 6;
|
||||||
|
if (++sprites >= spritesPerBatch)
|
||||||
|
Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
OpenRA.Game/Graphics/SpriteSheetBuilder.cs
Normal file
50
OpenRA.Game/Graphics/SpriteSheetBuilder.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
static class SpriteSheetBuilder
|
||||||
|
{
|
||||||
|
public static void Initialize( Map map )
|
||||||
|
{
|
||||||
|
exts = new[] {
|
||||||
|
"." + map.Theater.Substring( 0, 3 ).ToLowerInvariant(),
|
||||||
|
".shp",
|
||||||
|
".tem",
|
||||||
|
".sno",
|
||||||
|
".int" };
|
||||||
|
sprites = new Cache<string, Sprite[]>( LoadSprites );
|
||||||
|
}
|
||||||
|
|
||||||
|
static Cache<string, Sprite[]> sprites;
|
||||||
|
static string[] exts;
|
||||||
|
|
||||||
|
static Sprite[] LoadSprites(string filename)
|
||||||
|
{
|
||||||
|
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||||
|
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||||
|
}
|
||||||
|
}
|
||||||
110
OpenRA.Game/Graphics/TerrainRenderer.cs
Normal file
110
OpenRA.Game/Graphics/TerrainRenderer.cs
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.FileFormats.Graphics;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
class TerrainRenderer
|
||||||
|
{
|
||||||
|
IVertexBuffer<Vertex> vertexBuffer;
|
||||||
|
IIndexBuffer indexBuffer;
|
||||||
|
Sheet terrainSheet;
|
||||||
|
|
||||||
|
Renderer renderer;
|
||||||
|
Map map;
|
||||||
|
OverlayRenderer overlayRenderer;
|
||||||
|
|
||||||
|
public TerrainRenderer(World world, Renderer renderer, WorldRenderer wr)
|
||||||
|
{
|
||||||
|
this.renderer = renderer;
|
||||||
|
this.map = world.Map;
|
||||||
|
|
||||||
|
Size tileSize = new Size( Game.CellSize, Game.CellSize );
|
||||||
|
|
||||||
|
var tileMapping = new Cache<TileReference, Sprite>(
|
||||||
|
x => SheetBuilder.SharedInstance.Add(world.TileSet.GetBytes(x), tileSize));
|
||||||
|
|
||||||
|
Vertex[] vertices = new Vertex[4 * map.Height * map.Width];
|
||||||
|
ushort[] indices = new ushort[6 * map.Height * map.Width];
|
||||||
|
|
||||||
|
int nv = 0;
|
||||||
|
int ni = 0;
|
||||||
|
for( int j = map.YOffset ; j < map.YOffset + map.Height ; j++ )
|
||||||
|
for( int i = map.XOffset ; i < map.XOffset + map.Width; i++ )
|
||||||
|
{
|
||||||
|
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
||||||
|
// TODO: The zero below should explicitly refer to the terrain palette, but this code is called
|
||||||
|
// before the palettes are created
|
||||||
|
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni, tile.size);
|
||||||
|
nv += 4;
|
||||||
|
ni += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
terrainSheet = tileMapping[map.MapTiles[map.XOffset, map.YOffset]].sheet;
|
||||||
|
|
||||||
|
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||||
|
vertexBuffer.SetData( vertices );
|
||||||
|
|
||||||
|
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||||
|
indexBuffer.SetData( indices );
|
||||||
|
|
||||||
|
overlayRenderer = new OverlayRenderer( renderer, map );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw( Viewport viewport )
|
||||||
|
{
|
||||||
|
int indicesPerRow = map.Width * 6;
|
||||||
|
int verticesPerRow = map.Width * 4;
|
||||||
|
|
||||||
|
int visibleRows = (int)(viewport.Height / 24.0f + 2);
|
||||||
|
|
||||||
|
int firstRow = (int)((viewport.Location.Y) / 24.0f - map.YOffset);
|
||||||
|
int lastRow = firstRow + visibleRows;
|
||||||
|
|
||||||
|
if (lastRow < 0 || firstRow > map.Height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (firstRow < 0) firstRow = 0;
|
||||||
|
if (lastRow > map.Height) lastRow = map.Height;
|
||||||
|
|
||||||
|
if (!Game.world.LocalPlayer.Shroud.HasGPS && Game.world.LocalPlayer.Shroud.bounds.HasValue)
|
||||||
|
{
|
||||||
|
var r = Game.world.LocalPlayer.Shroud.bounds.Value;
|
||||||
|
if (firstRow < r.Top - map.YOffset)
|
||||||
|
firstRow = r.Top - map.YOffset;
|
||||||
|
|
||||||
|
if (firstRow > r.Bottom - map.YOffset)
|
||||||
|
firstRow = r.Bottom - map.YOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture );
|
||||||
|
renderer.SpriteShader.Render(() =>
|
||||||
|
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||||
|
new Range<int>(verticesPerRow * firstRow, verticesPerRow * lastRow),
|
||||||
|
new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow),
|
||||||
|
terrainSheet.Texture, PrimitiveType.TriangleList, renderer.SpriteShader));
|
||||||
|
|
||||||
|
overlayRenderer.Draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
131
OpenRA.Game/Graphics/Util.cs
Normal file
131
OpenRA.Game/Graphics/Util.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using OpenRA.FileFormats.Graphics;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
static class Util
|
||||||
|
{
|
||||||
|
public static string[] ReadAllLines(Stream s)
|
||||||
|
{
|
||||||
|
List<string> result = new List<string>();
|
||||||
|
using (StreamReader reader = new StreamReader(s))
|
||||||
|
while(!reader.EndOfStream)
|
||||||
|
{
|
||||||
|
var line = reader.ReadLine();
|
||||||
|
if( !string.IsNullOrEmpty( line ) && line[0] != '#' )
|
||||||
|
result.Add( line );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T[] MakeArray<T>(int count, Converter<int, T> f)
|
||||||
|
{
|
||||||
|
T[] result = new T[count];
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
result[i] = f(i);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
||||||
|
|
||||||
|
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size)
|
||||||
|
{
|
||||||
|
var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]);
|
||||||
|
|
||||||
|
vertices[nv] = new Vertex(o,
|
||||||
|
r.FastMapTextureCoords(0), attrib);
|
||||||
|
vertices[nv + 1] = new Vertex(new float2(o.X + size.X, o.Y),
|
||||||
|
r.FastMapTextureCoords(1), attrib);
|
||||||
|
vertices[nv + 2] = new Vertex(new float2(o.X, o.Y + size.Y),
|
||||||
|
r.FastMapTextureCoords(2), attrib);
|
||||||
|
vertices[nv + 3] = new Vertex(new float2(o.X + size.X, o.Y + size.Y),
|
||||||
|
r.FastMapTextureCoords(3), attrib);
|
||||||
|
|
||||||
|
indices[ni] = (ushort)(nv);
|
||||||
|
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
|
||||||
|
indices[ni + 2] = indices[ni + 5] = (ushort)(nv + 2);
|
||||||
|
indices[ni + 4] = (ushort)(nv + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void FastCopyIntoChannel(Sprite dest, byte[] src)
|
||||||
|
{
|
||||||
|
var bitmap = dest.sheet.Bitmap;
|
||||||
|
BitmapData bits = null;
|
||||||
|
uint[] channelMasks = { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||||
|
int[] shifts = { 16, 8, 0, 24 };
|
||||||
|
|
||||||
|
uint mask = channelMasks[(int)dest.channel];
|
||||||
|
int shift = shifts[(int)dest.channel];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bits = bitmap.LockBits(dest.bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||||
|
|
||||||
|
int width = dest.bounds.Width;
|
||||||
|
int height = dest.bounds.Height;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
fixed (byte* srcbase = &src[0])
|
||||||
|
{
|
||||||
|
byte* s = srcbase;
|
||||||
|
uint* t = (uint*)bits.Scan0.ToPointer();
|
||||||
|
int stride = bits.Stride >> 2;
|
||||||
|
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
|
{
|
||||||
|
uint* p = t;
|
||||||
|
for (int i = 0; i < width; i++, p++)
|
||||||
|
*p = (*p & ~mask) | ((mask & ((uint)*s++) << shift));
|
||||||
|
t += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
bitmap.UnlockBits(bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color Lerp(float t, Color a, Color b)
|
||||||
|
{
|
||||||
|
return Color.FromArgb(
|
||||||
|
LerpChannel(t, a.A, b.A),
|
||||||
|
LerpChannel(t, a.R, b.R),
|
||||||
|
LerpChannel(t, a.G, b.G),
|
||||||
|
LerpChannel(t, a.B, b.B));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int LerpChannel(float t, int a, int b)
|
||||||
|
{
|
||||||
|
return (int)((1 - t) * a + t * b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
151
OpenRA.Game/Graphics/Viewport.cs
Normal file
151
OpenRA.Game/Graphics/Viewport.cs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.Network;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
interface IHandleInput
|
||||||
|
{
|
||||||
|
bool HandleInput(World world, MouseInput mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Viewport
|
||||||
|
{
|
||||||
|
readonly float2 screenSize;
|
||||||
|
float2 scrollPosition;
|
||||||
|
readonly Renderer renderer;
|
||||||
|
|
||||||
|
public float2 Location { get { return scrollPosition; } }
|
||||||
|
|
||||||
|
public int Width { get { return (int)screenSize.X; } }
|
||||||
|
public int Height { get { return (int)screenSize.Y; } }
|
||||||
|
|
||||||
|
SpriteRenderer cursorRenderer;
|
||||||
|
int2 mousePos;
|
||||||
|
float cursorFrame = 0f;
|
||||||
|
|
||||||
|
public void Scroll(float2 delta)
|
||||||
|
{
|
||||||
|
scrollPosition = scrollPosition + delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<IHandleInput> regions { get { return new IHandleInput[] { Game.chrome, Game.controller }; } }
|
||||||
|
|
||||||
|
public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
|
||||||
|
{
|
||||||
|
this.screenSize = screenSize;
|
||||||
|
this.renderer = renderer;
|
||||||
|
cursorRenderer = new SpriteRenderer(renderer, true);
|
||||||
|
|
||||||
|
this.scrollPosition = Game.CellSize* mapStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawRegions( World world )
|
||||||
|
{
|
||||||
|
world.WorldRenderer.palette.Update(world.Queries.WithTraitMultiple<IPaletteModifier>().Select(t=>t.Trait));
|
||||||
|
|
||||||
|
float2 r1 = new float2(2, -2) / screenSize;
|
||||||
|
float2 r2 = new float2(-1, 1);
|
||||||
|
|
||||||
|
renderer.BeginFrame(r1, r2, scrollPosition);
|
||||||
|
|
||||||
|
if( Game.orderManager.GameStarted )
|
||||||
|
{
|
||||||
|
world.WorldRenderer.Draw();
|
||||||
|
Game.chrome.Draw( world );
|
||||||
|
|
||||||
|
|
||||||
|
if( Game.orderManager.Connection.ConnectionState == ConnectionState.NotConnected )
|
||||||
|
Game.chrome.DrawDialog("Connection lost.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// what a hack. as soon as we have some real chrome stuff...
|
||||||
|
|
||||||
|
switch( Game.orderManager.Connection.ConnectionState )
|
||||||
|
{
|
||||||
|
case ConnectionState.Connecting:
|
||||||
|
Game.chrome.DrawDialog("Connecting to {0}:{1}...".F( Game.Settings.NetworkHost, Game.Settings.NetworkPort ));
|
||||||
|
break;
|
||||||
|
case ConnectionState.NotConnected:
|
||||||
|
Game.chrome.DrawDialog("Connection failed.");
|
||||||
|
break;
|
||||||
|
case ConnectionState.Connected:
|
||||||
|
Game.chrome.DrawLobby( world );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cursorName = Game.chrome.HitTest(mousePos) ? "default" : Game.controller.ChooseCursor( world );
|
||||||
|
var c = new Cursor(cursorName);
|
||||||
|
cursorRenderer.DrawSprite(c.GetSprite((int)cursorFrame), mousePos + Location - c.GetHotspot(), "cursor");
|
||||||
|
cursorRenderer.Flush();
|
||||||
|
|
||||||
|
renderer.EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Tick()
|
||||||
|
{
|
||||||
|
cursorFrame += 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
IHandleInput dragRegion = null;
|
||||||
|
public void DispatchMouseInput(World world, MouseInput mi)
|
||||||
|
{
|
||||||
|
if (mi.Event == MouseInputEvent.Move)
|
||||||
|
mousePos = mi.Location;
|
||||||
|
|
||||||
|
if (dragRegion != null) {
|
||||||
|
dragRegion.HandleInput( world, mi );
|
||||||
|
if (mi.Event == MouseInputEvent.Up) dragRegion = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dragRegion = regions.FirstOrDefault(r => r.HandleInput(world, mi));
|
||||||
|
if (mi.Event != MouseInputEvent.Down)
|
||||||
|
dragRegion = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float2 ViewToWorld(MouseInput mi)
|
||||||
|
{
|
||||||
|
return (1 / 24.0f) * (new float2(mi.Location.X, mi.Location.Y) + Location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Center(IEnumerable<Actor> actors)
|
||||||
|
{
|
||||||
|
if (!actors.Any()) return;
|
||||||
|
|
||||||
|
var avgPos = (1f / actors.Count()) * actors
|
||||||
|
.Select(a => a.CenterLocation)
|
||||||
|
.Aggregate((a, b) => a + b);
|
||||||
|
|
||||||
|
scrollPosition = (avgPos - .5f * new float2(Width, Height)).ToInt2();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GoToStartLocation( Player player )
|
||||||
|
{
|
||||||
|
Center( player.World.Queries.OwnedBy[ player ].WithTrait<Selectable>().Select( a => a.Actor ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
315
OpenRA.Game/Graphics/WorldRenderer.cs
Normal file
315
OpenRA.Game/Graphics/WorldRenderer.cs
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||||
|
* This file is part of OpenRA.
|
||||||
|
*
|
||||||
|
* OpenRA is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* OpenRA is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using OpenRA.FileFormats;
|
||||||
|
using OpenRA.Traits;
|
||||||
|
|
||||||
|
namespace OpenRA.Graphics
|
||||||
|
{
|
||||||
|
public class WorldRenderer
|
||||||
|
{
|
||||||
|
readonly World world;
|
||||||
|
internal readonly TerrainRenderer terrainRenderer;
|
||||||
|
internal readonly SpriteRenderer spriteRenderer;
|
||||||
|
internal readonly LineRenderer lineRenderer;
|
||||||
|
internal readonly UiOverlay uiOverlay;
|
||||||
|
internal readonly Renderer renderer;
|
||||||
|
internal readonly HardwarePalette palette;
|
||||||
|
|
||||||
|
public static bool ShowUnitPaths = false;
|
||||||
|
|
||||||
|
internal WorldRenderer(World world, Renderer renderer)
|
||||||
|
{
|
||||||
|
this.world = world;
|
||||||
|
this.renderer = renderer;
|
||||||
|
|
||||||
|
terrainRenderer = new TerrainRenderer(world, renderer, this);
|
||||||
|
spriteRenderer = new SpriteRenderer(renderer, true);
|
||||||
|
lineRenderer = new LineRenderer(renderer);
|
||||||
|
uiOverlay = new UiOverlay(spriteRenderer);
|
||||||
|
palette = new HardwarePalette(renderer, world.Map);
|
||||||
|
Log.Write("Created worldrenderer");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetPaletteIndex(string name)
|
||||||
|
{
|
||||||
|
return palette.GetPaletteIndex(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Palette GetPalette(string name)
|
||||||
|
{
|
||||||
|
return palette.GetPalette(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPalette(string name, Palette pal)
|
||||||
|
{
|
||||||
|
palette.AddPalette(name, pal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawSpriteList(RectangleF rect,
|
||||||
|
IEnumerable<Renderable> images)
|
||||||
|
{
|
||||||
|
foreach (var image in images)
|
||||||
|
{
|
||||||
|
var loc = image.Pos;
|
||||||
|
|
||||||
|
if (loc.X > rect.Right || loc.X < rect.Left - image.Sprite.bounds.Width)
|
||||||
|
continue;
|
||||||
|
if (loc.Y > rect.Bottom || loc.Y < rect.Top - image.Sprite.bounds.Height)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
spriteRenderer.DrawSprite(image.Sprite, loc, image.Palette);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SpriteComparer : IComparer<Renderable>
|
||||||
|
{
|
||||||
|
public int Compare(Renderable x, Renderable y)
|
||||||
|
{
|
||||||
|
var result = x.ZOffset.CompareTo(y.ZOffset);
|
||||||
|
if (result == 0)
|
||||||
|
result = x.Pos.Y.CompareTo(y.Pos.Y);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle GetBoundsRect()
|
||||||
|
{
|
||||||
|
if (!world.LocalPlayer.Shroud.HasGPS && world.LocalPlayer.Shroud.bounds.HasValue)
|
||||||
|
{
|
||||||
|
var r = world.LocalPlayer.Shroud.bounds.Value;
|
||||||
|
|
||||||
|
var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X);
|
||||||
|
var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y);
|
||||||
|
var right = left + (int)(Game.CellSize * r.Width);
|
||||||
|
var bottom = top + (int)(Game.CellSize * r.Height);
|
||||||
|
|
||||||
|
if (left < 0) left = 0;
|
||||||
|
if (top < 0) top = 0;
|
||||||
|
if (right > Game.viewport.Width) right = Game.viewport.Width;
|
||||||
|
if (bottom > Game.viewport.Height) bottom = Game.viewport.Height;
|
||||||
|
|
||||||
|
return new Rectangle(left, top, right - left, bottom - top);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw()
|
||||||
|
{
|
||||||
|
var bounds = GetBoundsRect();
|
||||||
|
renderer.Device.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
|
||||||
|
|
||||||
|
terrainRenderer.Draw(Game.viewport);
|
||||||
|
|
||||||
|
var comparer = new SpriteComparer();
|
||||||
|
|
||||||
|
bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
|
||||||
|
|
||||||
|
var renderables = world.Actors.SelectMany(a => a.Render())
|
||||||
|
.OrderBy(r => r, comparer);
|
||||||
|
|
||||||
|
DrawSpriteList(bounds, renderables);
|
||||||
|
|
||||||
|
foreach (var e in world.Effects)
|
||||||
|
DrawSpriteList(bounds, e.Render());
|
||||||
|
|
||||||
|
uiOverlay.Draw( world );
|
||||||
|
|
||||||
|
spriteRenderer.Flush();
|
||||||
|
|
||||||
|
DrawBandBox();
|
||||||
|
|
||||||
|
if (Game.controller.orderGenerator != null)
|
||||||
|
Game.controller.orderGenerator.Render( world );
|
||||||
|
|
||||||
|
world.LocalPlayer.Shroud.Draw(spriteRenderer);
|
||||||
|
|
||||||
|
lineRenderer.Flush();
|
||||||
|
spriteRenderer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawBandBox()
|
||||||
|
{
|
||||||
|
var selbox = Game.controller.SelectionBox;
|
||||||
|
if (selbox == null) return;
|
||||||
|
|
||||||
|
var a = selbox.Value.First;
|
||||||
|
var b = new float2(selbox.Value.Second.X - a.X, 0);
|
||||||
|
var c = new float2(0, selbox.Value.Second.Y - a.Y);
|
||||||
|
|
||||||
|
lineRenderer.DrawLine(a, a + b, Color.White, Color.White);
|
||||||
|
lineRenderer.DrawLine(a + b, a + b + c, Color.White, Color.White);
|
||||||
|
lineRenderer.DrawLine(a + b + c, a + c, Color.White, Color.White);
|
||||||
|
lineRenderer.DrawLine(a, a + c, Color.White, Color.White);
|
||||||
|
|
||||||
|
foreach (var u in world.SelectActorsInBox(selbox.Value.First, selbox.Value.Second))
|
||||||
|
DrawSelectionBox(u, Color.Yellow, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar)
|
||||||
|
{
|
||||||
|
var bounds = selectedUnit.GetBounds(true);
|
||||||
|
|
||||||
|
var xy = new float2(bounds.Left, bounds.Top);
|
||||||
|
var Xy = new float2(bounds.Right, bounds.Top);
|
||||||
|
var xY = new float2(bounds.Left, bounds.Bottom);
|
||||||
|
var XY = new float2(bounds.Right, bounds.Bottom);
|
||||||
|
|
||||||
|
lineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c);
|
||||||
|
lineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c);
|
||||||
|
lineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c);
|
||||||
|
lineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c);
|
||||||
|
|
||||||
|
lineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c);
|
||||||
|
lineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c);
|
||||||
|
lineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c);
|
||||||
|
lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
|
||||||
|
|
||||||
|
if (drawHealthBar)
|
||||||
|
{
|
||||||
|
DrawHealthBar(selectedUnit, xy, Xy);
|
||||||
|
DrawControlGroup(selectedUnit, xy);
|
||||||
|
|
||||||
|
// Only display pips and tags to the owner
|
||||||
|
if (selectedUnit.Owner == world.LocalPlayer)
|
||||||
|
{
|
||||||
|
DrawPips(selectedUnit, xY);
|
||||||
|
DrawTags(selectedUnit, new float2(.5f * (bounds.Left + bounds.Right ), xy.Y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShowUnitPaths)
|
||||||
|
{
|
||||||
|
var mobile = selectedUnit.traits.GetOrDefault<Mobile>();
|
||||||
|
if (mobile != null)
|
||||||
|
{
|
||||||
|
var path = mobile.GetCurrentPath();
|
||||||
|
var start = selectedUnit.Location;
|
||||||
|
|
||||||
|
foreach (var step in path)
|
||||||
|
{
|
||||||
|
lineRenderer.DrawLine(
|
||||||
|
Game.CellSize * start + new float2(12, 12),
|
||||||
|
Game.CellSize * step + new float2(12, 12),
|
||||||
|
Color.Red, Color.Red);
|
||||||
|
start = step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawHealthBar(Actor selectedUnit, float2 xy, float2 Xy)
|
||||||
|
{
|
||||||
|
var c = Color.Gray;
|
||||||
|
lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
|
||||||
|
lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c);
|
||||||
|
|
||||||
|
var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.Get<OwnedActorInfo>().HP;
|
||||||
|
var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red
|
||||||
|
: (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow
|
||||||
|
: Color.LimeGreen;
|
||||||
|
|
||||||
|
var healthColor2 = Color.FromArgb(
|
||||||
|
255,
|
||||||
|
healthColor.R / 2,
|
||||||
|
healthColor.G / 2,
|
||||||
|
healthColor.B / 2);
|
||||||
|
|
||||||
|
var z = float2.Lerp(xy, Xy, healthAmount);
|
||||||
|
|
||||||
|
lineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0, -4), c, c);
|
||||||
|
lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c);
|
||||||
|
|
||||||
|
lineRenderer.DrawLine(xy + new float2(0, -3), z + new float2(0, -3), healthColor, healthColor);
|
||||||
|
lineRenderer.DrawLine(xy + new float2(0, -2), z + new float2(0, -2), healthColor2, healthColor2);
|
||||||
|
lineRenderer.DrawLine(xy + new float2(0, -4), z + new float2(0, -4), healthColor2, healthColor2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// depends on the order of pips in TraitsInterfaces.cs!
|
||||||
|
static readonly string[] pipStrings = { "pip-empty", "pip-green", "pip-yellow", "pip-red", "pip-gray" };
|
||||||
|
static readonly string[] tagStrings = { "", "tag-fake", "tag-primary" };
|
||||||
|
|
||||||
|
void DrawControlGroup(Actor selectedUnit, float2 basePosition)
|
||||||
|
{
|
||||||
|
var group = Game.controller.selection.GetControlGroupForActor(selectedUnit);
|
||||||
|
if (group == null) return;
|
||||||
|
|
||||||
|
var pipImages = new Animation("pips");
|
||||||
|
pipImages.PlayFetchIndex("groups", () => (int)group);
|
||||||
|
pipImages.Tick();
|
||||||
|
spriteRenderer.DrawSprite(pipImages.Image, basePosition + new float2(-8, 1), "chrome");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPips(Actor selectedUnit, float2 basePosition)
|
||||||
|
{
|
||||||
|
// If a mod wants to implement a unit with multiple pip sources, then they are placed on multiple rows
|
||||||
|
var pipxyBase = basePosition + new float2(-12, -7); // Correct for the offset in the shp file
|
||||||
|
var pipxyOffset = new float2(0, 0); // Correct for offset due to multiple columns/rows
|
||||||
|
|
||||||
|
foreach (var pips in selectedUnit.traits.WithInterface<IPips>())
|
||||||
|
{
|
||||||
|
foreach (var pip in pips.GetPips(selectedUnit))
|
||||||
|
{
|
||||||
|
var pipImages = new Animation("pips");
|
||||||
|
pipImages.PlayRepeating(pipStrings[(int)pip]);
|
||||||
|
spriteRenderer.DrawSprite(pipImages.Image, pipxyBase + pipxyOffset, "chrome");
|
||||||
|
pipxyOffset += new float2(4, 0);
|
||||||
|
|
||||||
|
if (pipxyOffset.X+5 > selectedUnit.GetBounds(false).Width)
|
||||||
|
{
|
||||||
|
pipxyOffset.X = 0;
|
||||||
|
pipxyOffset.Y -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Increment row
|
||||||
|
pipxyOffset.X = 0;
|
||||||
|
pipxyOffset.Y -= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTags(Actor selectedUnit, float2 basePosition)
|
||||||
|
{
|
||||||
|
// If a mod wants to implement a unit with multiple tags, then they are placed on multiple rows
|
||||||
|
var tagxyBase = basePosition + new float2(-16, 2); // Correct for the offset in the shp file
|
||||||
|
var tagxyOffset = new float2(0, 0); // Correct for offset due to multiple rows
|
||||||
|
|
||||||
|
foreach (var tags in selectedUnit.traits.WithInterface<ITags>())
|
||||||
|
{
|
||||||
|
foreach (var tag in tags.GetTags())
|
||||||
|
{
|
||||||
|
if (tag == TagType.None)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var tagImages = new Animation("pips");
|
||||||
|
tagImages.PlayRepeating(tagStrings[(int)tag]);
|
||||||
|
spriteRenderer.DrawSprite(tagImages.Image, tagxyBase + tagxyOffset, "chrome");
|
||||||
|
|
||||||
|
// Increment row
|
||||||
|
tagxyOffset.Y += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user