Everything is now OpenRA, not OpenRa

This commit is contained in:
alzeih
2010-02-27 21:10:22 +13:00
parent 11b926a422
commit 7881deca30
299 changed files with 26919 additions and 21 deletions

View File

@@ -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
fileformats_SRCS = $(shell find OpenRa.FileFormats/ -iname '*.cs')
fileformats_TARGET = OpenRa.FileFormats.dll
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
fileformats_TARGET = OpenRA.FileFormats.dll
fileformats_KIND = library
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll
gl_SRCS = $(shell find OpenRa.Gl/ -iname '*.cs')
gl_TARGET = OpenRa.Gl.dll
gl_SRCS = $(shell find OpenRA.Gl/ -iname '*.cs')
gl_TARGET = OpenRA.Gl.dll
gl_KIND = library
gl_DEPS = $(fileformats_TARGET) $(game_TARGET)
gl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
$(gl_DEPS) $(game_TARGET)
game_SRCS = $(shell find OpenRa.Game/ -iname '*.cs')
game_TARGET = OpenRa.Game.exe
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
game_TARGET = OpenRA.Game.exe
game_KIND = winexe
game_DEPS = $(fileformats_TARGET)
game_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll $(game_DEPS) \
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_TARGET = mods/ra/OpenRa.Mods.RA.dll
ra_SRCS = $(shell find OpenRA.Mods.RA/ -iname '*.cs')
ra_TARGET = mods/ra/OpenRA.Mods.RA.dll
ra_KIND = library
ra_DEPS = $(fileformats_TARGET) $(game_TARGET)
ra_LIBS = $(COMMON_LIBS) $(ra_DEPS)
cnc_SRCS = $(shell find OpenRa.Mods.Cnc/ -iname '*.cs')
cnc_TARGET = mods/cnc/OpenRa.Mods.Cnc.dll
cnc_SRCS = $(shell find OpenRA.Mods.Cnc/ -iname '*.cs')
cnc_TARGET = mods/cnc/OpenRA.Mods.Cnc.dll
cnc_KIND = library
cnc_DEPS = $(fileformats_TARGET) $(game_TARGET)
cnc_LIBS = $(COMMON_LIBS) $(cnc_DEPS)
aftermath_SRCS = $(shell find OpenRa.Mods.Aftermath/ -iname '*.cs')
aftermath_TARGET = mods/aftermath/OpenRa.Mods.Aftermath.dll
aftermath_SRCS = $(shell find OpenRA.Mods.Aftermath/ -iname '*.cs')
aftermath_TARGET = mods/aftermath/OpenRA.Mods.Aftermath.dll
aftermath_KIND = library
aftermath_DEPS = $(fileformats_TARGET) $(game_TARGET)
aftermath_LIBS = $(COMMON_LIBS) $(aftermath_DEPS)

View 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;
}
}
}

View 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
}
};
}
}

View 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();
}
}
}

View 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; } }
}
}

View 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 ) ); };
}
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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 );
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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 );
}
}
}

View 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;
}
}
}

View 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;
}
}
}
}
}
}

View 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++ ];
}
}
}
}
}
}

View 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; }
}
}

View 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;
}
}
}

View 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);
}
}

View 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();
}
}
}

View 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
View 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
View 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 "";
}
}
}
}

View 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>

View 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,
}
}

View 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;
}
}

View 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); }
}
}

View 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));
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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")]

View 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;
}
}

View 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(); }
}
}

View 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();
}
}
}

View 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];
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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);
}
}
}
}

View 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 ); }
}
}

View 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];
}
}
}

View 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); } }
}
}

View 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);
}
}
}

View 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;
}
}
}
}

View 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];
}
}
}

View 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); } }
}
}

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

114
OpenRA.Game/Combat.cs Normal file
View 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
View 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
View 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
View 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
View 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);
}
}
}

View 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; }
}
}

View 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; } }
}
}

View 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
View 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();
}
}

View 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
View 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");
}
}
}

View 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");
}
}
}

View 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
View 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
View 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
View 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
View 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;
}
}
}

View 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();
}
}
}

View 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 );
}
}
}

View 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 */
}
}

View 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(); }
}
}

View 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
View 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
View 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 ];
}
}
}

View 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;
}
}

View 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;
}
}
}

View 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,
}
}

View 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;
}
}

View 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 );
}
}
}

View 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];
}
}
}

View 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];
}
}
}

View 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]; }
}
}

View 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;
}
}
}

View 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);
}
}
}
}

View 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);
}
}
}

View 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();
}
}
}

View 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;
}
}
}

View 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);
}
}
}

View 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 ];
}
}
}

View 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));
}
}
}
}

View 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
}
}

View 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;
}
}
}

View 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,
}
}

View 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;
}
}

View 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();
}
}
}

View 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]; }
}
}

View 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();
}
}
}

View 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);
}
}
}

View 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 ) );
}
}
}

View 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