Everything is now OpenRA, not OpenRa
This commit is contained in:
26
Makefile
26
Makefile
@@ -5,41 +5,41 @@ PROGRAMS =fileformats gl game ra cnc aftermath server seqed
|
||||
|
||||
COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
||||
|
||||
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)
|
||||
|
||||
125
OpenRA.FileFormats/AudLoader.cs
Normal file
125
OpenRA.FileFormats/AudLoader.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
[Flags]
|
||||
enum SoundFlags
|
||||
{
|
||||
Stereo = 0x1,
|
||||
_16Bit = 0x2,
|
||||
}
|
||||
|
||||
enum SoundFormat
|
||||
{
|
||||
WestwoodCompressed = 1,
|
||||
ImaAdpcm = 99,
|
||||
}
|
||||
|
||||
struct Chunk
|
||||
{
|
||||
public int CompressedSize;
|
||||
public int OutputSize;
|
||||
|
||||
public static Chunk Read(BinaryReader r)
|
||||
{
|
||||
Chunk c;
|
||||
c.CompressedSize = r.ReadUInt16();
|
||||
c.OutputSize = r.ReadUInt16();
|
||||
if (0xdeaf != r.ReadUInt32())
|
||||
throw new InvalidDataException("Chunk header is bogus");
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AudLoader
|
||||
{
|
||||
static int[] IndexAdjust = { -1, -1, -1, -1, 2, 4, 6, 8 };
|
||||
static int[] StepTable = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16,
|
||||
17, 19, 21, 23, 25, 28, 31, 34, 37,
|
||||
41, 45, 50, 55, 60, 66, 73, 80, 88,
|
||||
97, 107, 118, 130, 143, 157, 173, 190, 209,
|
||||
230, 253, 279, 307, 337, 371, 408, 449, 494,
|
||||
544, 598, 658, 724, 796, 876, 963, 1060, 1166,
|
||||
1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749,
|
||||
3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
|
||||
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289,
|
||||
16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 };
|
||||
|
||||
static short DecodeSample(byte b, ref int index, ref int current)
|
||||
{
|
||||
var sb = (b & 8) != 0;
|
||||
b &= 7;
|
||||
|
||||
var delta = (StepTable[index] * b) / 4 + StepTable[index] / 8;
|
||||
if (sb) delta = -delta;
|
||||
|
||||
current += delta;
|
||||
if (current > short.MaxValue) current = short.MaxValue;
|
||||
if (current < short.MinValue) current = short.MinValue;
|
||||
|
||||
index += IndexAdjust[b];
|
||||
if (index < 0) index = 0;
|
||||
if (index > 88) index = 88;
|
||||
|
||||
return (short)current;
|
||||
}
|
||||
|
||||
public static byte[] LoadSound(Stream s)
|
||||
{
|
||||
var br = new BinaryReader(s);
|
||||
/*var sampleRate =*/ br.ReadUInt16();
|
||||
var dataSize = br.ReadInt32();
|
||||
var outputSize = br.ReadInt32();
|
||||
/*var flags = (SoundFlags)*/ br.ReadByte();
|
||||
/*var format = (SoundFormat)*/ br.ReadByte();
|
||||
|
||||
var output = new byte[outputSize];
|
||||
var offset = 0;
|
||||
var index = 0;
|
||||
var currentSample = 0;
|
||||
|
||||
while (dataSize > 0)
|
||||
{
|
||||
var chunk = Chunk.Read(br);
|
||||
for (int n = 0; n < chunk.CompressedSize; n++)
|
||||
{
|
||||
var b = br.ReadByte();
|
||||
|
||||
var t = DecodeSample(b, ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
|
||||
t = DecodeSample((byte)(b >> 4), ref index, ref currentSample);
|
||||
output[offset++] = (byte)t;
|
||||
output[offset++] = (byte)(t >> 8);
|
||||
}
|
||||
|
||||
dataSize -= 8 + chunk.CompressedSize;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
416
OpenRA.FileFormats/Blowfish.cs
Normal file
416
OpenRA.FileFormats/Blowfish.cs
Normal file
@@ -0,0 +1,416 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
class Blowfish
|
||||
{
|
||||
public Blowfish(byte[] key)
|
||||
{
|
||||
for (int i = 0, j = 0; i < 18; ++i)
|
||||
{
|
||||
uint a = key[j++ % key.Length];
|
||||
uint b = key[j++ % key.Length];
|
||||
uint c = key[j++ % key.Length];
|
||||
uint d = key[j++ % key.Length];
|
||||
|
||||
m_p[i] ^= a << 24 | b << 16 | c << 8 | d;
|
||||
}
|
||||
|
||||
uint l = 0, r = 0;
|
||||
|
||||
for (int i = 0; i < 18; )
|
||||
{
|
||||
Encrypt(ref l, ref r);
|
||||
m_p[i++] = l;
|
||||
m_p[i++] = r;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 256; )
|
||||
{
|
||||
Encrypt(ref l, ref r);
|
||||
m_s[i, j++] = l;
|
||||
m_s[i, j++] = r;
|
||||
}
|
||||
}
|
||||
|
||||
public uint[] Encrypt(uint[] data) { return RunCipher(data, Encrypt); }
|
||||
public uint[] Decrypt(uint[] data) { return RunCipher(data, Decrypt); }
|
||||
|
||||
delegate void CipherFunc( ref uint a, ref uint b );
|
||||
|
||||
uint[] RunCipher(uint[] data, CipherFunc f)
|
||||
{
|
||||
uint[] result = new uint[data.Length];
|
||||
|
||||
int size = data.Length / 2;
|
||||
int i = 0;
|
||||
while (size-- > 0)
|
||||
{
|
||||
uint a = SwapBytes(data[i]);
|
||||
uint b = SwapBytes(data[i+1]);
|
||||
|
||||
f(ref a, ref b);
|
||||
|
||||
result[i++] = SwapBytes(a);
|
||||
result[i++] = SwapBytes(b);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Encrypt(ref uint a, ref uint b)
|
||||
{
|
||||
uint _a = a, _b = b;
|
||||
_a ^= m_p[0];
|
||||
|
||||
bool x = false;
|
||||
for( int i = 1; i <= 16; i++, x ^= true)
|
||||
{
|
||||
if (x)
|
||||
Round(ref _a, _b, i);
|
||||
else
|
||||
Round(ref _b, _a, i);
|
||||
}
|
||||
_b ^= m_p[17];
|
||||
|
||||
a = _b;
|
||||
b = _a;
|
||||
}
|
||||
|
||||
void Decrypt(ref uint a, ref uint b)
|
||||
{
|
||||
uint _a = a, _b = b;
|
||||
_a ^= m_p[17];
|
||||
|
||||
bool x = false;
|
||||
for (int i = 16; i >= 1; i--, x ^= true)
|
||||
{
|
||||
if (x)
|
||||
Round(ref _a, _b, i);
|
||||
else
|
||||
Round(ref _b, _a, i);
|
||||
}
|
||||
_b ^= m_p[0];
|
||||
|
||||
a = _b;
|
||||
b = _a;
|
||||
}
|
||||
|
||||
uint S(uint x, int i)
|
||||
{
|
||||
return m_s[i, (x >> ((3 - i) << 3)) & 0xff];
|
||||
}
|
||||
|
||||
uint bf_f(uint x)
|
||||
{
|
||||
return ((S(x, 0) + S(x, 1)) ^ S(x, 2)) + S(x, 3);
|
||||
}
|
||||
|
||||
void Round(ref uint a, uint b, int n)
|
||||
{
|
||||
a ^= bf_f(b) ^ m_p[n];
|
||||
}
|
||||
|
||||
uint SwapBytes(uint i)
|
||||
{
|
||||
i = (i << 16) | (i >> 16);
|
||||
i = ((i << 8) & 0xff00ff00) | ((i >> 8) & 0x00ff00ff);
|
||||
return i;
|
||||
}
|
||||
|
||||
uint[] m_p = new uint[] {
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
||||
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
||||
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
||||
0x9216d5d9, 0x8979fb1b
|
||||
};
|
||||
|
||||
uint[,] m_s = new uint[,] {
|
||||
{
|
||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
||||
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
||||
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
||||
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
||||
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
||||
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
||||
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
||||
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
||||
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
||||
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
||||
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
||||
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
||||
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
||||
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
||||
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
||||
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
||||
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
||||
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
||||
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
||||
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
||||
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
||||
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
||||
},
|
||||
{
|
||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
||||
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
||||
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
||||
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
||||
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
||||
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
||||
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
||||
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
||||
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
||||
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
||||
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
||||
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
||||
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
||||
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
||||
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
||||
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
||||
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
||||
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
||||
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
||||
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
||||
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
||||
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
||||
},
|
||||
{
|
||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
||||
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
||||
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
||||
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
||||
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
||||
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
||||
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
||||
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
||||
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
||||
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
||||
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
||||
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
||||
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
||||
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
||||
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
||||
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
||||
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
||||
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
||||
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
||||
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
||||
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
||||
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
||||
},
|
||||
{
|
||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
||||
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
||||
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
||||
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
||||
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
||||
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
||||
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
||||
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
||||
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
||||
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
||||
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
||||
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
||||
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
||||
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
||||
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
||||
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
||||
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
||||
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
||||
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
||||
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
||||
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
||||
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
538
OpenRA.FileFormats/BlowfishKeyProvider.cs
Normal file
538
OpenRA.FileFormats/BlowfishKeyProvider.cs
Normal file
@@ -0,0 +1,538 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
/* possibly the fugliest C# i've ever seen. */
|
||||
|
||||
class BlowfishKeyProvider
|
||||
{
|
||||
const string pubkeyStr = "AihRvNoIbTn85FZRYNZRcT+i6KpU+maCsEqr3Q5q+LDB5tH7Tz2qQ38V";
|
||||
|
||||
static sbyte[] char2num = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
|
||||
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||||
|
||||
class PublicKey
|
||||
{
|
||||
public uint[] key1 = new uint[64];
|
||||
public uint[] key2 = new uint[64];
|
||||
public uint len;
|
||||
}
|
||||
PublicKey pubkey = new PublicKey();
|
||||
|
||||
uint[] glob1 = new uint[64];
|
||||
uint glob1_bitlen, glob1_len_x2;
|
||||
uint[] glob2 = new uint[130];
|
||||
uint[] glob1_hi = new uint[4];
|
||||
uint[] glob1_hi_inv = new uint[4];
|
||||
uint glob1_hi_bitlen;
|
||||
uint glob1_hi_inv_lo, glob1_hi_inv_hi;
|
||||
|
||||
void init_bignum(uint[] n, uint val, uint len)
|
||||
{
|
||||
for (int i = 0; i < len; i++) n[i] = 0;
|
||||
n[0] = val;
|
||||
}
|
||||
|
||||
void move_key_to_big(uint[] n, byte[] key, uint klen, uint blen)
|
||||
{
|
||||
byte sign;
|
||||
|
||||
if ((key[0] & 0x80) != 0) sign = 0xff;
|
||||
else sign = 0;
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (uint* _pn = &n[0])
|
||||
{
|
||||
byte* pn = (byte*)_pn;
|
||||
uint i = blen * 4;
|
||||
for (; i > klen; i--) pn[i - 1] = (byte)sign;
|
||||
for (; i > 0; i--) pn[i - 1] = key[klen - i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void key_to_bignum(uint[] n, byte[] key, uint len)
|
||||
{
|
||||
uint keylen;
|
||||
int i;
|
||||
|
||||
int j = 0;
|
||||
|
||||
if (key[j] != 2) return;
|
||||
j++;
|
||||
|
||||
if ((key[j] & 0x80) != 0)
|
||||
{
|
||||
keylen = 0;
|
||||
for (i = 0; i < (key[j] & 0x7f); i++) keylen = (keylen << 8) | key[j + i + 1];
|
||||
j += (key[j] & 0x7f) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
keylen = key[j];
|
||||
j++;
|
||||
}
|
||||
if (keylen <= len * 4)
|
||||
move_key_to_big(n, key.Skip(j).ToArray(), keylen, len);
|
||||
}
|
||||
|
||||
uint len_bignum(uint[] n, uint len)
|
||||
{
|
||||
uint i;
|
||||
i = len - 1;
|
||||
while ((i >= 0) && (n[i] == 0)) i--;
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
uint bitlen_bignum(uint[] n, uint len)
|
||||
{
|
||||
uint ddlen, bitlen, mask;
|
||||
ddlen = len_bignum(n, len);
|
||||
if (ddlen == 0) return 0;
|
||||
bitlen = ddlen * 32;
|
||||
mask = 0x80000000;
|
||||
while ((mask & n[ddlen - 1]) == 0)
|
||||
{
|
||||
mask >>= 1;
|
||||
bitlen--;
|
||||
}
|
||||
return bitlen;
|
||||
}
|
||||
|
||||
void init_pubkey()
|
||||
{
|
||||
int i = 0;
|
||||
uint i2, tmp;
|
||||
byte[] keytmp = new byte[256];
|
||||
|
||||
init_bignum(pubkey.key2, 0x10001, 64);
|
||||
|
||||
i2 = 0;
|
||||
while (i < pubkeyStr.Length)
|
||||
{
|
||||
tmp = (uint)char2num[pubkeyStr[i++]];
|
||||
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
|
||||
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
|
||||
tmp <<= 6; tmp |= (uint)(byte)char2num[pubkeyStr[i++]];
|
||||
keytmp[i2++] = (byte)((tmp >> 16) & 0xff);
|
||||
keytmp[i2++] = (byte)((tmp >> 8) & 0xff);
|
||||
keytmp[i2++] = (byte)(tmp & 0xff);
|
||||
}
|
||||
|
||||
key_to_bignum(pubkey.key1, keytmp, 64);
|
||||
pubkey.len = bitlen_bignum(pubkey.key1, 64) - 1;
|
||||
}
|
||||
|
||||
uint len_predata()
|
||||
{
|
||||
uint a = (pubkey.len - 1) / 8;
|
||||
return (55 / a + 1) * (a + 1);
|
||||
}
|
||||
|
||||
int cmp_bignum(uint[] n1, uint[] n2, uint len)
|
||||
{
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
--len;
|
||||
if (n1[len] < n2[len]) return -1;
|
||||
if (n1[len] > n2[len]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mov_bignum(uint[] dest, uint[] src, uint len)
|
||||
{
|
||||
Array.Copy(src, dest, len);
|
||||
}
|
||||
|
||||
void shr_bignum(uint[] n, int bits, int len)
|
||||
{
|
||||
int i; int i2 = bits / 32;
|
||||
|
||||
if (i2 > 0)
|
||||
{
|
||||
for (i = 0; i < len - i2; i++) n[i] = n[i + i2];
|
||||
for (; i < len; i++) n[i] = 0;
|
||||
bits = bits % 32;
|
||||
}
|
||||
if (bits == 0) return;
|
||||
for (i = 0; i < len - 1; i++) n[i] = (n[i] >> bits) | (n[i + 1] << (32 -
|
||||
bits));
|
||||
n[i] = n[i] >> bits;
|
||||
}
|
||||
|
||||
void shl_bignum(uint[] n, int bits, int len)
|
||||
{
|
||||
int i, i2;
|
||||
|
||||
i2 = bits / 32;
|
||||
if (i2 > 0)
|
||||
{
|
||||
for (i = len - 1; i > i2; i--) n[i] = n[i - i2];
|
||||
for (; i > 0; i--) n[i] = 0;
|
||||
bits = bits % 32;
|
||||
}
|
||||
if (bits == 0) return;
|
||||
for (i = len - 1; i > 0; i--) n[i] = (n[i] << bits) | (n[i - 1] >> (32 -
|
||||
bits));
|
||||
n[0] <<= bits;
|
||||
}
|
||||
|
||||
uint sub_bignum(uint[] dest, uint[] src1, uint[] src2, uint carry, int len)
|
||||
{
|
||||
uint i1, i2;
|
||||
|
||||
len += len;
|
||||
unsafe
|
||||
{
|
||||
fixed (uint* _ps1 = &src1[0])
|
||||
fixed (uint* _ps2 = &src2[0])
|
||||
fixed (uint* _pd = &dest[0])
|
||||
{
|
||||
ushort* ps1 = (ushort*)_ps1;
|
||||
ushort* ps2 = (ushort*)_ps2;
|
||||
ushort* pd = (ushort*)_pd;
|
||||
|
||||
while (--len != -1)
|
||||
{
|
||||
i1 = *ps1++;
|
||||
i2 = *ps2++;
|
||||
*pd++ = (ushort)(i1 - i2 - carry);
|
||||
if (((i1 - i2 - carry) & 0x10000) != 0) carry = 1; else carry = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
unsafe uint sub_bignum(uint* dest, uint* src1, uint* src2, uint carry, int len)
|
||||
{
|
||||
uint i1, i2;
|
||||
|
||||
len += len;
|
||||
|
||||
ushort* ps1 = (ushort*)src1;
|
||||
ushort* ps2 = (ushort*)src2;
|
||||
ushort* pd = (ushort*)dest;
|
||||
|
||||
while (--len != -1)
|
||||
{
|
||||
i1 = *ps1++;
|
||||
i2 = *ps2++;
|
||||
*pd++ = (ushort)(i1 - i2 - carry);
|
||||
if (((i1 - i2 - carry) & 0x10000) != 0) carry = 1; else carry = 0;
|
||||
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
void inv_bignum(uint[] n1, uint[] n2, uint len)
|
||||
{
|
||||
uint[] n_tmp = new uint[64];
|
||||
uint n2_bytelen, bit;
|
||||
int n2_bitlen;
|
||||
|
||||
int j = 0;
|
||||
|
||||
init_bignum(n_tmp, 0, len);
|
||||
init_bignum(n1, 0, len);
|
||||
n2_bitlen = (int)bitlen_bignum(n2, len);
|
||||
bit = ((uint)1) << (n2_bitlen % 32);
|
||||
j = ((n2_bitlen + 32) / 32) - 1;
|
||||
n2_bytelen = (uint)((n2_bitlen - 1) / 32) * 4;
|
||||
n_tmp[n2_bytelen / 4] |= ((uint)1) << ((n2_bitlen - 1) & 0x1f);
|
||||
|
||||
while (n2_bitlen > 0)
|
||||
{
|
||||
n2_bitlen--;
|
||||
shl_bignum(n_tmp, 1, (int)len);
|
||||
if (cmp_bignum(n_tmp, n2, len) != -1)
|
||||
{
|
||||
sub_bignum(n_tmp, n_tmp, n2, 0, (int)len);
|
||||
n1[j] |= bit;
|
||||
}
|
||||
bit >>= 1;
|
||||
if (bit == 0)
|
||||
{
|
||||
j--;
|
||||
bit = 0x80000000;
|
||||
}
|
||||
}
|
||||
init_bignum(n_tmp, 0, len);
|
||||
}
|
||||
|
||||
void inc_bignum(uint[] n, uint len)
|
||||
{
|
||||
int i = 0;
|
||||
while ((++n[i] == 0) && (--len > 0)) i++;
|
||||
}
|
||||
|
||||
void init_two_dw(uint[] n, uint len)
|
||||
{
|
||||
mov_bignum(glob1, n, len);
|
||||
glob1_bitlen = bitlen_bignum(glob1, len);
|
||||
glob1_len_x2 = (glob1_bitlen + 15) / 16;
|
||||
mov_bignum(glob1_hi, glob1.Skip((int)len_bignum(glob1, len) - 2).ToArray(), 2);
|
||||
glob1_hi_bitlen = bitlen_bignum(glob1_hi, 2) - 32;
|
||||
shr_bignum(glob1_hi, (int)glob1_hi_bitlen, 2);
|
||||
inv_bignum(glob1_hi_inv, glob1_hi, 2);
|
||||
shr_bignum(glob1_hi_inv, 1, 2);
|
||||
glob1_hi_bitlen = (glob1_hi_bitlen + 15) % 16 + 1;
|
||||
inc_bignum(glob1_hi_inv, 2);
|
||||
if (bitlen_bignum(glob1_hi_inv, 2) > 32)
|
||||
{
|
||||
shr_bignum(glob1_hi_inv, 1, 2);
|
||||
glob1_hi_bitlen--;
|
||||
}
|
||||
glob1_hi_inv_lo = (ushort)glob1_hi_inv[0];
|
||||
glob1_hi_inv_hi = (ushort)(glob1_hi_inv[0] >> 16);
|
||||
}
|
||||
|
||||
unsafe void mul_bignum_word(ushort *pn1, uint[] n2, uint mul, uint len)
|
||||
{
|
||||
uint i, tmp;
|
||||
unsafe
|
||||
{
|
||||
fixed (uint* _pn2 = &n2[0])
|
||||
{
|
||||
ushort* pn2 = (ushort*)_pn2;
|
||||
|
||||
tmp = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tmp = mul * (*pn2) + (*pn1) + tmp;
|
||||
*pn1 = (ushort)tmp;
|
||||
pn1++;
|
||||
pn2++;
|
||||
tmp >>= 16;
|
||||
}
|
||||
*pn1 += (ushort)tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mul_bignum(uint[] dest, uint[] src1, uint[] src2, uint len)
|
||||
{
|
||||
uint i;
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed( uint * _psrc2 = &src2[0] )
|
||||
fixed(uint* _pdest = &dest[0])
|
||||
{
|
||||
ushort* psrc2 = (ushort*)_psrc2;
|
||||
ushort* pdest = (ushort*)_pdest;
|
||||
|
||||
init_bignum(dest, 0, len * 2);
|
||||
for (i = 0; i < len * 2; i++)
|
||||
mul_bignum_word(pdest++, src1, *psrc2++, len * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void not_bignum(uint[] n, uint len)
|
||||
{
|
||||
uint i;
|
||||
for (i = 0; i < len; i++) n[i] = ~n[i];
|
||||
}
|
||||
|
||||
void neg_bignum(uint[] n, uint len)
|
||||
{
|
||||
not_bignum(n, len);
|
||||
inc_bignum(n, len);
|
||||
}
|
||||
|
||||
unsafe uint get_mulword(uint* n)
|
||||
{
|
||||
ushort* wn = (ushort*)n;
|
||||
uint i = (uint)((((((((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_lo + 0x10000) >> 1)
|
||||
+ (((*(wn - 2) ^ 0xffff) * glob1_hi_inv_hi + glob1_hi_inv_hi) >> 1) + 1)
|
||||
>> 16) + ((((*(wn - 1) ^ 0xffff) & 0xffff) * glob1_hi_inv_hi) >> 1) +
|
||||
(((*wn ^ 0xffff) * glob1_hi_inv_lo) >> 1) + 1) >> 14) + glob1_hi_inv_hi
|
||||
* (*wn ^ 0xffff) * 2) >> (int)glob1_hi_bitlen);
|
||||
if (i > 0xffff) i = 0xffff;
|
||||
return i & 0xffff;
|
||||
}
|
||||
|
||||
void dec_bignum(uint[] n, uint len)
|
||||
{
|
||||
int i = 0;
|
||||
while ((--n[i] == 0xffffffff) && (--len > 0))
|
||||
i++;
|
||||
}
|
||||
|
||||
void calc_a_bignum(uint[] n1, uint[] n2, uint[] n3, uint len)
|
||||
{
|
||||
uint g2_len_x2, len_diff;
|
||||
unsafe
|
||||
{
|
||||
fixed( uint* g1 = &glob1[0])
|
||||
fixed (uint* g2 = &glob2[0])
|
||||
{
|
||||
mul_bignum(glob2, n2, n3, len);
|
||||
glob2[len * 2] = 0;
|
||||
g2_len_x2 = len_bignum(glob2, len * 2 + 1) * 2;
|
||||
if (g2_len_x2 >= glob1_len_x2)
|
||||
{
|
||||
inc_bignum(glob2, len * 2 + 1);
|
||||
neg_bignum(glob2, len * 2 + 1);
|
||||
len_diff = g2_len_x2 + 1 - glob1_len_x2;
|
||||
ushort* esi = ((ushort*)g2) + (1 + g2_len_x2 - glob1_len_x2);
|
||||
ushort* edi = ((ushort*)g2) + (g2_len_x2 + 1);
|
||||
for (; len_diff != 0; len_diff--)
|
||||
{
|
||||
edi--;
|
||||
uint tmp = get_mulword((uint*)edi);
|
||||
esi--;
|
||||
if (tmp > 0)
|
||||
{
|
||||
mul_bignum_word(esi, glob1, tmp, 2 * len);
|
||||
if ((*edi & 0x8000) == 0)
|
||||
{
|
||||
if (0 != sub_bignum((uint*)esi, (uint*)esi, g1, 0, (int)len)) (*edi)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
neg_bignum(glob2, len);
|
||||
dec_bignum(glob2, len);
|
||||
}
|
||||
mov_bignum(n1, glob2, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear_tmp_vars(uint len)
|
||||
{
|
||||
init_bignum(glob1, 0, len);
|
||||
init_bignum(glob2, 0, len);
|
||||
init_bignum(glob1_hi_inv, 0, 4);
|
||||
init_bignum(glob1_hi, 0, 4);
|
||||
glob1_bitlen = 0;
|
||||
glob1_hi_bitlen = 0;
|
||||
glob1_len_x2 = 0;
|
||||
glob1_hi_inv_lo = 0;
|
||||
glob1_hi_inv_hi = 0;
|
||||
}
|
||||
|
||||
void calc_a_key(uint[] n1, uint[] n2, uint[] n3, uint[] n4, uint len)
|
||||
{
|
||||
uint[] n_tmp = new uint[64];
|
||||
uint n3_len, n4_len;
|
||||
int n3_bitlen;
|
||||
uint bit_mask;
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (uint* _pn3 = &n3[0])
|
||||
{
|
||||
uint* pn3 = _pn3;
|
||||
|
||||
init_bignum(n1, 1, len);
|
||||
n4_len = len_bignum(n4, len);
|
||||
init_two_dw(n4, n4_len);
|
||||
n3_bitlen = (int)bitlen_bignum(n3, n4_len);
|
||||
n3_len = (uint)((n3_bitlen + 31) / 32);
|
||||
bit_mask = (((uint)1) << ((n3_bitlen - 1) % 32)) >> 1;
|
||||
pn3 += n3_len - 1;
|
||||
n3_bitlen--;
|
||||
mov_bignum(n1, n2, n4_len);
|
||||
while (--n3_bitlen != -1)
|
||||
{
|
||||
if (bit_mask == 0)
|
||||
{
|
||||
bit_mask = 0x80000000;
|
||||
pn3--;
|
||||
}
|
||||
calc_a_bignum(n_tmp, n1, n1, n4_len);
|
||||
if ((*pn3 & bit_mask) != 0)
|
||||
calc_a_bignum(n1, n_tmp, n2, n4_len);
|
||||
else
|
||||
mov_bignum(n1, n_tmp, n4_len);
|
||||
bit_mask >>= 1;
|
||||
}
|
||||
init_bignum(n_tmp, 0, n4_len);
|
||||
clear_tmp_vars(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe void memcpy(byte* dest, byte* src, int len)
|
||||
{
|
||||
while (len-- != 0) *dest++ = *src++;
|
||||
}
|
||||
|
||||
unsafe void process_predata(byte* pre, uint pre_len, byte *buf)
|
||||
{
|
||||
uint[] n2 = new uint[64];
|
||||
uint[] n3 = new uint[64];
|
||||
|
||||
uint a = (pubkey.len - 1) / 8;
|
||||
while (a + 1 <= pre_len)
|
||||
{
|
||||
init_bignum(n2, 0, 64);
|
||||
fixed( uint * pn2 = &n2[0] )
|
||||
memcpy((byte *)pn2, pre, (int)a + 1);
|
||||
calc_a_key(n3, n2, pubkey.key2, pubkey.key1, 64);
|
||||
|
||||
fixed( uint * pn3 = &n3[0] )
|
||||
memcpy(buf, (byte *)pn3, (int)a);
|
||||
|
||||
pre_len -= a + 1;
|
||||
pre += a + 1;
|
||||
buf += a;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] DecryptKey(byte[] src)
|
||||
{
|
||||
init_pubkey();
|
||||
byte[] dest = new byte[256];
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* pdest = &dest[0])
|
||||
fixed (byte* psrc = &src[0])
|
||||
process_predata(psrc, len_predata(), pdest);
|
||||
}
|
||||
return dest.Take(56).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
59
OpenRA.FileFormats/Cache.cs
Normal file
59
OpenRA.FileFormats/Cache.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Cache<T, U> : IEnumerable<KeyValuePair<T, U>>
|
||||
{
|
||||
Dictionary<T, U> hax = new Dictionary<T, U>();
|
||||
Func<T,U> loader;
|
||||
|
||||
public Cache(Func<T,U> loader)
|
||||
{
|
||||
if (loader == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public U this[T key]
|
||||
{
|
||||
get
|
||||
{
|
||||
U result;
|
||||
if (!hax.TryGetValue(key, out result))
|
||||
hax.Add(key, result = loader(key));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<T, U>> GetEnumerator() { return hax.GetEnumerator(); }
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
|
||||
|
||||
public IEnumerable<T> Keys { get { return hax.Keys; } }
|
||||
public IEnumerable<U> Values { get { return hax.Values; } }
|
||||
}
|
||||
}
|
||||
76
OpenRA.FileFormats/Collections/Set.cs
Executable file
76
OpenRA.FileFormats/Collections/Set.cs
Executable file
@@ -0,0 +1,76 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.Collections
|
||||
{
|
||||
public class Set<T> : IEnumerable<T>
|
||||
{
|
||||
Dictionary<T, bool> data = new Dictionary<T, bool>();
|
||||
|
||||
public void Add( T obj )
|
||||
{
|
||||
data.Add( obj, false );
|
||||
if( OnAdd != null )
|
||||
OnAdd( obj );
|
||||
}
|
||||
|
||||
public void Remove( T obj )
|
||||
{
|
||||
data.Remove( obj );
|
||||
if( OnRemove != null )
|
||||
OnRemove( obj );
|
||||
}
|
||||
|
||||
public event Action<T> OnAdd;
|
||||
public event Action<T> OnRemove;
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return data.Keys.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
public class CachedView<T,U> : Set<U>
|
||||
{
|
||||
public CachedView( Set<T> set, Func<T, bool> include, Func<T, U> store )
|
||||
: this( set, include, x => new[] { store( x ) } )
|
||||
{
|
||||
}
|
||||
|
||||
public CachedView( Set<T> set, Func<T,bool> include, Func<T,IEnumerable<U>> store )
|
||||
{
|
||||
foreach( var t in set )
|
||||
if( include( t ) )
|
||||
store( t ).Do( x => Add( x ) );
|
||||
|
||||
set.OnAdd += obj => { if( include( obj ) ) store( obj ).Do( x => Add( x ) ); };
|
||||
set.OnRemove += obj => { if( include( obj ) ) store( obj ).Do( x => Remove( x ) ); };
|
||||
}
|
||||
}
|
||||
}
|
||||
45
OpenRA.FileFormats/DisposableAction.cs
Normal file
45
OpenRA.FileFormats/DisposableAction.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class DisposableAction : IDisposable
|
||||
{
|
||||
public DisposableAction(Action a) { this.a = a; }
|
||||
|
||||
Action a;
|
||||
bool disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
a();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~DisposableAction()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
156
OpenRA.FileFormats/Dune2ShpReader.cs
Normal file
156
OpenRA.FileFormats/Dune2ShpReader.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public enum Dune2ImageFlags : int
|
||||
{
|
||||
F80_F2 = 0,
|
||||
F2 = 2,
|
||||
L16_F80_F2_1 = 1,
|
||||
L16_F80_F2_2 = 3,
|
||||
Ln_F80_F2 = 5
|
||||
}
|
||||
|
||||
public class Dune2ImageHeader
|
||||
{
|
||||
public readonly Dune2ImageFlags Flags;
|
||||
public readonly int Width;
|
||||
public readonly int Height;
|
||||
public readonly int Slices;
|
||||
public readonly int FileSize;
|
||||
public readonly int DataSize;
|
||||
|
||||
public readonly byte[] LookupTable;
|
||||
public byte[] Image;
|
||||
|
||||
public Dune2ImageHeader(BinaryReader reader)
|
||||
{
|
||||
Flags = (Dune2ImageFlags)reader.ReadUInt16();
|
||||
Slices = reader.ReadByte();
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadByte();
|
||||
FileSize = reader.ReadUInt16();
|
||||
DataSize = reader.ReadUInt16();
|
||||
|
||||
if (Flags == Dune2ImageFlags.L16_F80_F2_1 ||
|
||||
Flags == Dune2ImageFlags.L16_F80_F2_2 ||
|
||||
Flags == Dune2ImageFlags.Ln_F80_F2)
|
||||
{
|
||||
int n = Flags == Dune2ImageFlags.Ln_F80_F2 ? reader.ReadByte() : (byte)16;
|
||||
LookupTable = new byte[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
LookupTable[i] = reader.ReadByte();
|
||||
}
|
||||
else
|
||||
{
|
||||
LookupTable = new byte[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
LookupTable[i] = (byte)i;
|
||||
LookupTable[1] = 0x7f;
|
||||
LookupTable[2] = 0x7e;
|
||||
LookupTable[3] = 0x7d;
|
||||
LookupTable[4] = 0x7c;
|
||||
}
|
||||
}
|
||||
|
||||
public Size Size
|
||||
{
|
||||
get { return new Size(Width, Height); }
|
||||
}
|
||||
}
|
||||
|
||||
public class Dune2ShpReader : IEnumerable<Dune2ImageHeader>
|
||||
{
|
||||
public readonly int ImageCount;
|
||||
|
||||
List<Dune2ImageHeader> headers = new List<Dune2ImageHeader>();
|
||||
|
||||
public Dune2ShpReader(Stream stream)
|
||||
{
|
||||
BinaryReader reader = new BinaryReader(stream);
|
||||
|
||||
ImageCount = reader.ReadUInt16();
|
||||
|
||||
//Last offset is pointer to end of file.
|
||||
uint[] offsets = new uint[ImageCount + 1];
|
||||
|
||||
uint temp = reader.ReadUInt32();
|
||||
|
||||
//If fourth byte in file is non-zero, the offsets are two bytes each.
|
||||
bool twoByteOffsets = (temp & 0xFF0000) > 0;
|
||||
if (twoByteOffsets)
|
||||
{
|
||||
offsets[0] = ((temp & 0xFFFF0000) >> 16) + 2; //Offset does not account for image count bytes
|
||||
offsets[1] = (temp & 0xFFFF) + 2;
|
||||
}
|
||||
else
|
||||
offsets[0] = temp + 2;
|
||||
|
||||
for (int i = twoByteOffsets ? 2 : 1; i < ImageCount + 1; i++)
|
||||
offsets[i] = (twoByteOffsets ? reader.ReadUInt16() : reader.ReadUInt32()) + 2;
|
||||
|
||||
for (int i = 0; i < ImageCount; i++)
|
||||
{
|
||||
reader.BaseStream.Seek(offsets[i], SeekOrigin.Begin);
|
||||
Dune2ImageHeader header = new Dune2ImageHeader(reader);
|
||||
byte[] imgData = reader.ReadBytes(header.FileSize);
|
||||
header.Image = new byte[header.Height * header.Width];
|
||||
|
||||
//Decode image data
|
||||
if (header.Flags != Dune2ImageFlags.F2)
|
||||
{
|
||||
byte[] tempData = new byte[header.DataSize];
|
||||
Format80.DecodeInto(imgData, tempData);
|
||||
Format2.DecodeInto(tempData, header.Image);
|
||||
}
|
||||
else
|
||||
Format2.DecodeInto(imgData, header.Image);
|
||||
|
||||
//Lookup values in lookup table
|
||||
if (header.LookupTable != null)
|
||||
for (int j = 0; j < header.Image.Length; j++)
|
||||
header.Image[j] = header.LookupTable[header.Image[j]];
|
||||
|
||||
headers.Add(header);
|
||||
}
|
||||
}
|
||||
|
||||
public Dune2ImageHeader this[int index]
|
||||
{
|
||||
get { return headers[index]; }
|
||||
}
|
||||
|
||||
public IEnumerator<Dune2ImageHeader> GetEnumerator()
|
||||
{
|
||||
return headers.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
OpenRA.FileFormats/Exts.cs
Normal file
39
OpenRA.FileFormats/Exts.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Exts
|
||||
{
|
||||
public static string F(this string fmt, params object[] args)
|
||||
{
|
||||
return string.Format(fmt, args);
|
||||
}
|
||||
|
||||
public static void Do<T>( this IEnumerable<T> e, Action<T> fn )
|
||||
{
|
||||
foreach( var ee in e )
|
||||
fn( ee );
|
||||
}
|
||||
}
|
||||
}
|
||||
119
OpenRA.FileFormats/FieldLoader.cs
Normal file
119
OpenRA.FileFormats/FieldLoader.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class FieldLoader
|
||||
{
|
||||
public static void Load(object self, IniSection ini)
|
||||
{
|
||||
foreach (var x in ini)
|
||||
{
|
||||
var field = self.GetType().GetField(x.Key.Trim());
|
||||
if (field == null)
|
||||
throw new NotImplementedException("Missing field `{0}` on `{1}`".F(x.Key.Trim(), self.GetType().Name));
|
||||
field.SetValue(self, GetValue(field.FieldType, x.Value.Trim()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Load(object self, MiniYaml my)
|
||||
{
|
||||
foreach (var x in my.Nodes)
|
||||
{
|
||||
var field = self.GetType().GetField(x.Key.Trim());
|
||||
if (field == null)
|
||||
throw new NotImplementedException("Missing field `{0}` on `{1}`".F(x.Key.Trim(), self.GetType().Name));
|
||||
field.SetValue(self, GetValue(field.FieldType, x.Value.Value));
|
||||
}
|
||||
}
|
||||
|
||||
public static object GetValue( Type fieldType, string x )
|
||||
{
|
||||
if (x != null) x = x.Trim();
|
||||
if( fieldType == typeof( int ) )
|
||||
return int.Parse( x );
|
||||
|
||||
else if (fieldType == typeof(float))
|
||||
return float.Parse(x.Replace("%","")) * (x.Contains( '%' ) ? 0.01f : 1f);
|
||||
|
||||
else if (fieldType == typeof(string))
|
||||
return x;
|
||||
|
||||
else if (fieldType.IsEnum)
|
||||
return Enum.Parse(fieldType, x, true);
|
||||
|
||||
else if (fieldType == typeof(bool))
|
||||
return ParseYesNo(x);
|
||||
|
||||
else if (fieldType.IsArray)
|
||||
{
|
||||
if (x == null)
|
||||
return Array.CreateInstance(fieldType.GetElementType(), 0);
|
||||
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var ret = Array.CreateInstance(fieldType.GetElementType(), parts.Length);
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
ret.SetValue(GetValue(fieldType.GetElementType(), parts[i].Trim()), i);
|
||||
return ret;
|
||||
}
|
||||
else if (fieldType == typeof(int2))
|
||||
{
|
||||
var parts = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return new int2(int.Parse(parts[0]), int.Parse(parts[1]));
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException("FieldLoader: don't know how to load field of type " + fieldType.ToString());
|
||||
}
|
||||
|
||||
static bool ParseYesNo( string p )
|
||||
{
|
||||
p = p.ToLowerInvariant();
|
||||
if( p == "yes" ) return true;
|
||||
if( p == "true" ) return true;
|
||||
if( p == "no" ) return false;
|
||||
if( p == "false" ) return false;
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static class FieldSaver
|
||||
{
|
||||
public static MiniYaml Save(object o)
|
||||
{
|
||||
return new MiniYaml(null, o.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance)
|
||||
.ToDictionary(
|
||||
f => f.Name,
|
||||
f => new MiniYaml(FormatValue(o, f))));
|
||||
}
|
||||
|
||||
static string FormatValue(object o, FieldInfo f)
|
||||
{
|
||||
var v = f.GetValue(o);
|
||||
return f.FieldType.IsArray
|
||||
? string.Join(",", ((Array)v).OfType<object>().Select(a => a.ToString()).ToArray())
|
||||
: v.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
138
OpenRA.FileFormats/FileSystem.cs
Normal file
138
OpenRA.FileFormats/FileSystem.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class FileSystem
|
||||
{
|
||||
static List<IFolder> mountedFolders = new List<IFolder>();
|
||||
|
||||
static Cache<uint, List<IFolder>> allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
|
||||
static void MountInner(IFolder folder)
|
||||
{
|
||||
mountedFolders.Add(folder);
|
||||
|
||||
foreach( var hash in folder.AllFileHashes() )
|
||||
{
|
||||
var l = allFiles[hash];
|
||||
if( !l.Contains( folder ) )
|
||||
l.Add( folder );
|
||||
}
|
||||
}
|
||||
|
||||
public static void Mount(string name)
|
||||
{
|
||||
name = name.ToLowerInvariant();
|
||||
var optional = name.StartsWith("~");
|
||||
if (optional) name = name.Substring(1);
|
||||
|
||||
var a = name.EndsWith(".mix")
|
||||
? (Action)(() => FileSystem.MountInner(new Package(name)))
|
||||
: () => FileSystem.MountInner(new Folder(name));
|
||||
|
||||
if (optional)
|
||||
try { a(); }
|
||||
catch { }
|
||||
else
|
||||
a();
|
||||
}
|
||||
|
||||
public static void UnmountAll()
|
||||
{
|
||||
mountedFolders.Clear();
|
||||
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
}
|
||||
|
||||
static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename )
|
||||
{
|
||||
foreach( var folder in index[ PackageEntry.HashFilename( filename ) ] )
|
||||
{
|
||||
Stream s = folder.GetContent(filename);
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Stream Open(string filename)
|
||||
{
|
||||
if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 )
|
||||
{
|
||||
var ret = GetFromCache( allFiles, filename );
|
||||
if( ret != null )
|
||||
return ret;
|
||||
}
|
||||
|
||||
foreach( IFolder folder in mountedFolders )
|
||||
{
|
||||
Stream s = folder.GetContent(filename);
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||
}
|
||||
|
||||
public static Stream OpenWithExts( string filename, params string[] exts )
|
||||
{
|
||||
if( filename.IndexOfAny( new char[] { '/', '\\' } ) == -1 )
|
||||
{
|
||||
foreach( var ext in exts )
|
||||
{
|
||||
var s = GetFromCache( allFiles, filename + ext );
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
foreach( var ext in exts )
|
||||
{
|
||||
foreach( IFolder folder in mountedFolders )
|
||||
{
|
||||
Stream s = folder.GetContent( filename + ext );
|
||||
if( s != null )
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
|
||||
}
|
||||
|
||||
public static bool Exists(string filename)
|
||||
{
|
||||
foreach (var folder in mountedFolders)
|
||||
{
|
||||
var s = folder.GetContent(filename);
|
||||
if (s != null)
|
||||
{
|
||||
s.Dispose();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
45
OpenRA.FileFormats/Folder.cs
Normal file
45
OpenRA.FileFormats/Folder.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Folder : IFolder
|
||||
{
|
||||
readonly string path;
|
||||
|
||||
public Folder(string path) { this.path = path; }
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
Log.Write( "GetContent from folder: {0}", filename );
|
||||
try { return File.OpenRead( Path.Combine( path, filename ) ); }
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) )
|
||||
yield return PackageEntry.HashFilename( filename );
|
||||
}
|
||||
}
|
||||
}
|
||||
46
OpenRA.FileFormats/Format2.cs
Normal file
46
OpenRA.FileFormats/Format2.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class Format2
|
||||
{
|
||||
public static int DecodeInto(byte[] src, byte[] dest)
|
||||
{
|
||||
FastByteReader r = new FastByteReader(src);
|
||||
|
||||
int i = 0;
|
||||
while (!r.Done())
|
||||
{
|
||||
byte cmd = r.ReadByte();
|
||||
if (cmd == 0)
|
||||
{
|
||||
byte count = r.ReadByte();
|
||||
while (count-- > 0)
|
||||
dest[i++] = 0;
|
||||
}
|
||||
else
|
||||
dest[i++] = cmd;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
OpenRA.FileFormats/Format40.cs
Normal file
88
OpenRA.FileFormats/Format40.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class Format40
|
||||
{
|
||||
public static int DecodeInto( byte[] src, byte[] dest )
|
||||
{
|
||||
var ctx = new FastByteReader(src);
|
||||
int destIndex = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
byte i = ctx.ReadByte();
|
||||
if( ( i & 0x80 ) == 0 )
|
||||
{
|
||||
int count = i & 0x7F;
|
||||
if( count == 0 )
|
||||
{
|
||||
// case 6
|
||||
count = ctx.ReadByte();
|
||||
byte value = ctx.ReadByte();
|
||||
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||
dest[ destIndex ] ^= value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 5
|
||||
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||
dest[destIndex] ^= ctx.ReadByte();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = i & 0x7F;
|
||||
if( count == 0 )
|
||||
{
|
||||
count = ctx.ReadWord();
|
||||
if( count == 0 )
|
||||
return destIndex;
|
||||
|
||||
if( ( count & 0x8000 ) == 0 )
|
||||
{
|
||||
// case 2
|
||||
destIndex += ( count & 0x7FFF );
|
||||
}
|
||||
else if( ( count & 0x4000 ) == 0 )
|
||||
{
|
||||
// case 3
|
||||
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
|
||||
dest[destIndex] ^= ctx.ReadByte();
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 4
|
||||
byte value = ctx.ReadByte();
|
||||
for( int end = destIndex + ( count & 0x3FFF ) ; destIndex < end ; destIndex++ )
|
||||
dest[ destIndex ] ^= value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 1
|
||||
destIndex += count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
135
OpenRA.FileFormats/Format80.cs
Normal file
135
OpenRA.FileFormats/Format80.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
class FastByteReader
|
||||
{
|
||||
readonly byte[] src;
|
||||
int offset = 0;
|
||||
|
||||
public FastByteReader(byte[] src)
|
||||
{
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
public bool Done() { return offset >= src.Length; }
|
||||
public byte ReadByte() { return src[offset++]; }
|
||||
public int ReadWord()
|
||||
{
|
||||
int x = ReadByte();
|
||||
return x | (ReadByte() << 8);
|
||||
}
|
||||
|
||||
public void CopyTo(byte[] dest, int offset, int count)
|
||||
{
|
||||
Array.Copy(src, this.offset, dest, offset, count);
|
||||
this.offset += count;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Format80
|
||||
{
|
||||
static void ReplicatePrevious( byte[] dest, int destIndex, int srcIndex, int count )
|
||||
{
|
||||
if( srcIndex > destIndex )
|
||||
throw new NotImplementedException( string.Format( "srcIndex > destIndex {0} {1}", srcIndex, destIndex ) );
|
||||
|
||||
if( destIndex - srcIndex == 1 )
|
||||
{
|
||||
for( int i = 0 ; i < count ; i++ )
|
||||
dest[ destIndex + i ] = dest[ destIndex - 1 ];
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0 ; i < count ; i++ )
|
||||
dest[ destIndex + i ] = dest[ srcIndex + i ];
|
||||
}
|
||||
}
|
||||
|
||||
public static int DecodeInto( byte[] src, byte[] dest )
|
||||
{
|
||||
var ctx = new FastByteReader(src);
|
||||
int destIndex = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
byte i = ctx.ReadByte();
|
||||
if( ( i & 0x80 ) == 0 )
|
||||
{
|
||||
// case 2
|
||||
byte secondByte = ctx.ReadByte();
|
||||
int count = ( ( i & 0x70 ) >> 4 ) + 3;
|
||||
int rpos = ( ( i & 0xf ) << 8 ) + secondByte;
|
||||
|
||||
ReplicatePrevious( dest, destIndex, destIndex - rpos, count );
|
||||
destIndex += count;
|
||||
}
|
||||
else if( ( i & 0x40 ) == 0 )
|
||||
{
|
||||
// case 1
|
||||
int count = i & 0x3F;
|
||||
if( count == 0 )
|
||||
return destIndex;
|
||||
|
||||
ctx.CopyTo( dest, destIndex, count );
|
||||
destIndex += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count3 = i & 0x3F;
|
||||
if( count3 == 0x3E )
|
||||
{
|
||||
// case 4
|
||||
int count = ctx.ReadWord();
|
||||
byte color = ctx.ReadByte();
|
||||
|
||||
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||
dest[ destIndex ] = color;
|
||||
}
|
||||
else if( count3 == 0x3F )
|
||||
{
|
||||
// case 5
|
||||
int count = ctx.ReadWord();
|
||||
int srcIndex = ctx.ReadWord();
|
||||
if( srcIndex >= destIndex )
|
||||
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
|
||||
|
||||
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||
dest[ destIndex ] = dest[ srcIndex++ ];
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 3
|
||||
int count = count3 + 3;
|
||||
int srcIndex = ctx.ReadWord();
|
||||
if( srcIndex >= destIndex )
|
||||
throw new NotImplementedException( string.Format( "srcIndex >= destIndex {0} {1}", srcIndex, destIndex ) );
|
||||
|
||||
for( int end = destIndex + count ; destIndex < end ; destIndex++ )
|
||||
dest[ destIndex ] = dest[ srcIndex++ ];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
105
OpenRA.FileFormats/Graphics/IGraphicsDevice.cs
Executable file
105
OpenRA.FileFormats/Graphics/IGraphicsDevice.cs
Executable file
@@ -0,0 +1,105 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats.Graphics
|
||||
{
|
||||
[AttributeUsage( AttributeTargets.Assembly )]
|
||||
public class RendererAttribute : Attribute
|
||||
{
|
||||
public readonly Type Type;
|
||||
|
||||
public RendererAttribute( Type graphicsDeviceType )
|
||||
{
|
||||
if( !typeof( IGraphicsDevice ).IsAssignableFrom( graphicsDeviceType ) )
|
||||
throw new InvalidOperationException( "Incorrect type in RendererAttribute" );
|
||||
Type = graphicsDeviceType;
|
||||
}
|
||||
}
|
||||
|
||||
public interface IGraphicsDevice
|
||||
{
|
||||
IVertexBuffer<Vertex> CreateVertexBuffer( int length );
|
||||
IIndexBuffer CreateIndexBuffer( int length );
|
||||
ITexture CreateTexture( Bitmap bitmap );
|
||||
IShader CreateShader( Stream stream );
|
||||
|
||||
Size WindowSize { get; }
|
||||
|
||||
void Begin();
|
||||
void End();
|
||||
void Clear( Color color );
|
||||
void Present();
|
||||
|
||||
void DrawIndexedPrimitives( PrimitiveType type, Range<int> vertexRange, Range<int> indexRange );
|
||||
void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives );
|
||||
|
||||
void EnableScissor( int left, int top, int width, int height );
|
||||
void DisableScissor();
|
||||
}
|
||||
|
||||
public interface IVertexBuffer<T>
|
||||
{
|
||||
void Bind();
|
||||
void SetData( T[] vertices );
|
||||
}
|
||||
|
||||
public interface IIndexBuffer
|
||||
{
|
||||
void Bind();
|
||||
void SetData( ushort[] indices );
|
||||
}
|
||||
|
||||
public interface IShader
|
||||
{
|
||||
void SetValue( string name, float x, float y );
|
||||
void SetValue( string param, ITexture texture );
|
||||
void Commit();
|
||||
void Render( Action a );
|
||||
}
|
||||
|
||||
public interface ITexture
|
||||
{
|
||||
void SetData( Bitmap bitmap );
|
||||
}
|
||||
|
||||
public interface IFont
|
||||
{
|
||||
void DrawText( string text, int2 pos, Color c );
|
||||
|
||||
int2 Measure( string text );
|
||||
}
|
||||
|
||||
public enum PrimitiveType
|
||||
{
|
||||
PointList,
|
||||
LineList,
|
||||
TriangleList,
|
||||
}
|
||||
|
||||
public struct Range<T>
|
||||
{
|
||||
public readonly T Start, End;
|
||||
public Range( T start, T end ) { Start = start; End = end; }
|
||||
}
|
||||
}
|
||||
38
OpenRA.FileFormats/Graphics/Vertex.cs
Normal file
38
OpenRA.FileFormats/Graphics/Vertex.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenRA.FileFormats.Graphics
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vertex
|
||||
{
|
||||
public float x, y, z, u, v;
|
||||
public float p, c;
|
||||
|
||||
public Vertex(float2 xy, float2 uv, float2 pc)
|
||||
{
|
||||
this.x = xy.X; this.y = xy.Y; this.z = 0;
|
||||
this.u = uv.X; this.v = uv.Y;
|
||||
this.p = pc.X; this.c = pc.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
OpenRA.FileFormats/IPaletteRemap.cs
Normal file
29
OpenRA.FileFormats/IPaletteRemap.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public interface IPaletteRemap
|
||||
{
|
||||
Color GetRemappedColor(Color original, int index);
|
||||
}
|
||||
}
|
||||
161
OpenRA.FileFormats/IniFile.cs
Normal file
161
OpenRA.FileFormats/IniFile.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class IniFile
|
||||
{
|
||||
Dictionary<string, IniSection> sections = new Dictionary<string, IniSection>();
|
||||
|
||||
public IniFile( Stream s )
|
||||
{
|
||||
Load( s );
|
||||
}
|
||||
|
||||
public IniFile( params Stream[] streams )
|
||||
{
|
||||
foreach( var s in streams )
|
||||
Load( s );
|
||||
}
|
||||
|
||||
public void Load( Stream s )
|
||||
{
|
||||
StreamReader reader = new StreamReader( s );
|
||||
IniSection currentSection = null;
|
||||
|
||||
while( !reader.EndOfStream )
|
||||
{
|
||||
string line = reader.ReadLine();
|
||||
|
||||
if( line.Length == 0 ) continue;
|
||||
|
||||
switch( line[ 0 ] )
|
||||
{
|
||||
case ';': break;
|
||||
case '[': currentSection = ProcessSection( line ); break;
|
||||
default: ProcessEntry( line, currentSection ); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Regex sectionPattern = new Regex( @"^\[([^]]*)\]" );
|
||||
|
||||
IniSection ProcessSection( string line )
|
||||
{
|
||||
Match m = sectionPattern.Match( line );
|
||||
if( m == null || !m.Success )
|
||||
return null;
|
||||
string sectionName = m.Groups[ 1 ].Value.ToLowerInvariant();
|
||||
|
||||
IniSection ret;
|
||||
if( !sections.TryGetValue( sectionName, out ret ) )
|
||||
sections.Add( sectionName, ret = new IniSection( sectionName ) );
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ProcessEntry( string line, IniSection currentSection )
|
||||
{
|
||||
int comment = line.IndexOf( ';' );
|
||||
if( comment >= 0 )
|
||||
line = line.Substring( 0, comment );
|
||||
|
||||
line = line.Trim();
|
||||
if( line.Length == 0 )
|
||||
return false;
|
||||
|
||||
var key = line;
|
||||
var value = "";
|
||||
int eq = line.IndexOf( '=' );
|
||||
if( eq >= 0 )
|
||||
{
|
||||
key = line.Substring( 0, eq );
|
||||
value = line.Substring( eq + 1, line.Length - eq - 1 );
|
||||
}
|
||||
|
||||
if( currentSection == null )
|
||||
throw new InvalidOperationException( "No current INI section" );
|
||||
|
||||
if( !currentSection.Contains( key ) )
|
||||
currentSection.Add( key, value );
|
||||
return true;
|
||||
}
|
||||
|
||||
public IniSection GetSection( string s )
|
||||
{
|
||||
return GetSection( s, false );
|
||||
}
|
||||
|
||||
public IniSection GetSection( string s, bool allowFail )
|
||||
{
|
||||
IniSection section;
|
||||
if( sections.TryGetValue( s.ToLowerInvariant(), out section ) )
|
||||
return section;
|
||||
|
||||
if( allowFail )
|
||||
return new IniSection( s );
|
||||
throw new InvalidOperationException( "Section does not exist in map or rules: " + s );
|
||||
}
|
||||
|
||||
public IEnumerable<IniSection> Sections { get { return sections.Values; } }
|
||||
}
|
||||
|
||||
public class IniSection : IEnumerable<KeyValuePair<string, string>>
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
Dictionary<string, string> values = new Dictionary<string, string>();
|
||||
|
||||
public IniSection( string name )
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public void Add( string key, string value )
|
||||
{
|
||||
values[key] = value;
|
||||
}
|
||||
|
||||
public bool Contains( string key )
|
||||
{
|
||||
return values.ContainsKey( key );
|
||||
}
|
||||
|
||||
public string GetValue( string key, string defaultValue )
|
||||
{
|
||||
string s;
|
||||
return values.TryGetValue( key, out s ) ? s : defaultValue;
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
|
||||
{
|
||||
return values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
56
OpenRA.FileFormats/Lazy.cs
Normal file
56
OpenRA.FileFormats/Lazy.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Lazy<T>
|
||||
{
|
||||
Func<T> p;
|
||||
T value;
|
||||
|
||||
public Lazy(Func<T> p)
|
||||
{
|
||||
if (p == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (p == null)
|
||||
return value;
|
||||
|
||||
value = p();
|
||||
p = null;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Lazy
|
||||
{
|
||||
public static Lazy<T> New<T>(Func<T> p) { return new Lazy<T>(p); }
|
||||
}
|
||||
}
|
||||
176
OpenRA.FileFormats/Map.cs
Normal file
176
OpenRA.FileFormats/Map.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Map
|
||||
{
|
||||
public readonly string Title;
|
||||
public readonly string Theater;
|
||||
|
||||
public readonly int XOffset;
|
||||
public readonly int YOffset;
|
||||
public int2 Offset { get { return new int2( XOffset, YOffset ); } }
|
||||
|
||||
public readonly int Width;
|
||||
public readonly int Height;
|
||||
public int2 Size { get { return new int2(Width, Height); } }
|
||||
|
||||
public readonly TileReference[ , ] MapTiles = new TileReference[ 128, 128 ];
|
||||
public readonly List<TreeReference> Trees = new List<TreeReference>();
|
||||
|
||||
public readonly IEnumerable<int2> SpawnPoints;
|
||||
|
||||
static string Truncate( string s, int maxLength )
|
||||
{
|
||||
return s.Length <= maxLength ? s : s.Substring(0,maxLength );
|
||||
}
|
||||
|
||||
public string TileSuffix { get { return "." + Truncate(Theater, 3); } }
|
||||
|
||||
public Map(IniFile file)
|
||||
{
|
||||
for (int j = 0; j < 128; j++)
|
||||
for (int i = 0; i < 128; i++)
|
||||
MapTiles[i, j] = new TileReference();
|
||||
|
||||
IniSection basic = file.GetSection("Basic");
|
||||
Title = basic.GetValue("Name", "(null)");
|
||||
|
||||
IniSection map = file.GetSection("Map");
|
||||
Theater = Truncate(map.GetValue("Theater", "TEMPERATE"), 8);
|
||||
|
||||
XOffset = int.Parse(map.GetValue("X", "0"));
|
||||
YOffset = int.Parse(map.GetValue("Y", "0"));
|
||||
|
||||
Width = int.Parse(map.GetValue("Width", "0"));
|
||||
Height = int.Parse(map.GetValue("Height", "0"));
|
||||
|
||||
UnpackTileData(ReadPackedSection(file.GetSection("MapPack")));
|
||||
UnpackOverlayData(ReadPackedSection(file.GetSection("OverlayPack")));
|
||||
ReadTrees(file);
|
||||
|
||||
SpawnPoints = file.GetSection("Waypoints")
|
||||
.Select(kv => Pair.New(int.Parse(kv.Key), new int2(int.Parse(kv.Value) % 128, int.Parse(kv.Value) / 128)))
|
||||
.Where(a => a.First < 8)
|
||||
.Select(a => a.Second)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
static MemoryStream ReadPackedSection(IniSection mapPackSection)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 1; ; i++)
|
||||
{
|
||||
string line = mapPackSection.GetValue(i.ToString(), null);
|
||||
if (line == null)
|
||||
break;
|
||||
|
||||
sb.Append(line.Trim());
|
||||
}
|
||||
|
||||
byte[] data = Convert.FromBase64String(sb.ToString());
|
||||
List<byte[]> chunks = new List<byte[]>();
|
||||
BinaryReader reader = new BinaryReader(new MemoryStream(data));
|
||||
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
uint length = reader.ReadUInt32() & 0xdfffffff;
|
||||
byte[] dest = new byte[8192];
|
||||
byte[] src = reader.ReadBytes((int)length);
|
||||
|
||||
/*int actualLength =*/ Format80.DecodeInto(src, dest);
|
||||
|
||||
chunks.Add(dest);
|
||||
}
|
||||
}
|
||||
catch (EndOfStreamException) { }
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
foreach (byte[] chunk in chunks)
|
||||
ms.Write(chunk, 0, chunk.Length);
|
||||
|
||||
ms.Position = 0;
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
static byte ReadByte( Stream s )
|
||||
{
|
||||
int ret = s.ReadByte();
|
||||
if( ret == -1 )
|
||||
throw new NotImplementedException();
|
||||
return (byte)ret;
|
||||
}
|
||||
|
||||
static ushort ReadWord(Stream s)
|
||||
{
|
||||
ushort ret = ReadByte(s);
|
||||
ret |= (ushort)(ReadByte(s) << 8);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void UnpackTileData( MemoryStream ms )
|
||||
{
|
||||
for( int i = 0 ; i < 128 ; i++ )
|
||||
for( int j = 0 ; j < 128 ; j++ )
|
||||
MapTiles[j, i].tile = ReadWord(ms);
|
||||
|
||||
for( int i = 0 ; i < 128 ; i++ )
|
||||
for( int j = 0 ; j < 128 ; j++ )
|
||||
{
|
||||
MapTiles[j, i].image = (byte)ms.ReadByte();
|
||||
if( MapTiles[ j, i ].tile == 0xff || MapTiles[ j, i ].tile == 0xffff )
|
||||
MapTiles[ j, i ].image = (byte)( i % 4 + ( j % 4 ) * 4 );
|
||||
}
|
||||
}
|
||||
|
||||
void UnpackOverlayData( MemoryStream ms )
|
||||
{
|
||||
for( int i = 0 ; i < 128 ; i++ )
|
||||
for( int j = 0 ; j < 128 ; j++ )
|
||||
MapTiles[ j, i ].overlay = ReadByte( ms );
|
||||
}
|
||||
|
||||
void ReadTrees( IniFile file )
|
||||
{
|
||||
IniSection terrain = file.GetSection( "TERRAIN", true );
|
||||
if( terrain == null )
|
||||
return;
|
||||
|
||||
foreach( KeyValuePair<string, string> kv in terrain )
|
||||
Trees.Add( new TreeReference( int.Parse( kv.Key ), kv.Value ) );
|
||||
}
|
||||
|
||||
public bool IsInMap(int x, int y)
|
||||
{
|
||||
return (x >= XOffset && y >= YOffset && x < XOffset + Width && y < YOffset + Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
168
OpenRA.FileFormats/MiniYaml.cs
Executable file
168
OpenRA.FileFormats/MiniYaml.cs
Executable file
@@ -0,0 +1,168 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
using MiniYamlNodes = Dictionary<string, MiniYaml>;
|
||||
|
||||
public class MiniYaml
|
||||
{
|
||||
public string Value;
|
||||
public Dictionary<string, MiniYaml> Nodes = new Dictionary<string,MiniYaml>();
|
||||
|
||||
public MiniYaml( string value ) : this( value, new Dictionary<string, MiniYaml>() ) { }
|
||||
|
||||
public MiniYaml( string value, Dictionary<string, MiniYaml> nodes )
|
||||
{
|
||||
Value = value;
|
||||
Nodes = nodes;
|
||||
}
|
||||
|
||||
static Dictionary<string, MiniYaml> FromLines(string[] lines)
|
||||
{
|
||||
var levels = new List<Dictionary<string, MiniYaml>>();
|
||||
levels.Add(new Dictionary<string, MiniYaml>());
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var t = line.TrimStart(' ', '\t');
|
||||
if (t.Length == 0 || t[0] == '#')
|
||||
continue;
|
||||
var level = line.Length - t.Length;
|
||||
|
||||
if (levels.Count <= level)
|
||||
throw new InvalidOperationException("Bad indent in miniyaml");
|
||||
while (levels.Count > level + 1)
|
||||
levels.RemoveAt(levels.Count - 1);
|
||||
|
||||
var colon = t.IndexOf(':');
|
||||
var d = new Dictionary<string, MiniYaml>();
|
||||
|
||||
if (colon == -1)
|
||||
levels[level].Add(t.Trim(), new MiniYaml(null, d));
|
||||
else
|
||||
{
|
||||
var value = t.Substring(colon + 1).Trim();
|
||||
if (value.Length == 0)
|
||||
value = null;
|
||||
levels[level].Add(t.Substring(0, colon).Trim(), new MiniYaml(value, d));
|
||||
}
|
||||
levels.Add(d);
|
||||
}
|
||||
return levels[0];
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromFile( string path )
|
||||
{
|
||||
return FromLines(File.ReadAllLines( path ));
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromStream(Stream s)
|
||||
{
|
||||
using (var reader = new StreamReader(s))
|
||||
return FromString(reader.ReadToEnd());
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> FromString(string text)
|
||||
{
|
||||
return FromLines(text.Split('\n'));
|
||||
}
|
||||
|
||||
public static Dictionary<string, MiniYaml> Merge( Dictionary<string, MiniYaml> a, Dictionary<string, MiniYaml> b )
|
||||
{
|
||||
if( a.Count == 0 )
|
||||
return b;
|
||||
if( b.Count == 0 )
|
||||
return a;
|
||||
|
||||
var ret = new Dictionary<string, MiniYaml>();
|
||||
|
||||
var keys = a.Keys.Union( b.Keys ).ToList();
|
||||
|
||||
var noInherit = keys.Where( x => x.Length > 0 && x[ 0 ] == '-' ).Select( x => x.Substring( 1 ) ).ToList();
|
||||
|
||||
foreach( var key in keys )
|
||||
{
|
||||
MiniYaml aa, bb;
|
||||
a.TryGetValue( key, out aa );
|
||||
b.TryGetValue( key, out bb );
|
||||
|
||||
if( key.Length > 0 && key[ 0 ] == '-' )
|
||||
continue;
|
||||
else if( noInherit.Contains( key ) )
|
||||
{
|
||||
if( aa != null )
|
||||
ret.Add( key, aa );
|
||||
}
|
||||
else
|
||||
ret.Add( key, Merge( aa, bb ) );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static MiniYaml Merge( MiniYaml a, MiniYaml b )
|
||||
{
|
||||
if( a == null )
|
||||
return b;
|
||||
if( b == null )
|
||||
return a;
|
||||
|
||||
return new MiniYaml( a.Value ?? b.Value, Merge( a.Nodes, b.Nodes ) );
|
||||
}
|
||||
|
||||
public IEnumerable<string> ToLines(string name)
|
||||
{
|
||||
yield return name + ": " + Value;
|
||||
if (Nodes != null)
|
||||
foreach (var line in Nodes.ToLines(false))
|
||||
yield return "\t" + line;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MiniYamlExts
|
||||
{
|
||||
public static void WriteToFile(this MiniYamlNodes y, string filename)
|
||||
{
|
||||
File.WriteAllLines(filename, y.ToLines(true).Select(x => x.TrimEnd()).ToArray());
|
||||
}
|
||||
|
||||
public static string WriteToString(this MiniYamlNodes y)
|
||||
{
|
||||
return string.Join("\n", y.ToLines(true).Select(x => x.TrimEnd()).ToArray());
|
||||
}
|
||||
|
||||
public static IEnumerable<string> ToLines(this MiniYamlNodes y, bool lowest)
|
||||
{
|
||||
foreach (var kv in y)
|
||||
{
|
||||
foreach (var line in kv.Value.ToLines(kv.Key))
|
||||
yield return line;
|
||||
if (lowest)
|
||||
yield return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
OpenRA.FileFormats/OpenRA.FileFormats.csproj
Normal file
106
OpenRA.FileFormats/OpenRA.FileFormats.csproj
Normal file
@@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenRA.FileFormats</RootNamespace>
|
||||
<AssemblyName>OpenRA.FileFormats</AssemblyName>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>2.0</OldToolsVersion>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Tao.Sdl, Version=1.2.13.0, Culture=neutral, PublicKeyToken=9c7a200e36c0094e, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AudLoader.cs" />
|
||||
<Compile Include="Blowfish.cs" />
|
||||
<Compile Include="BlowfishKeyProvider.cs" />
|
||||
<Compile Include="Cache.cs" />
|
||||
<Compile Include="Collections\Set.cs" />
|
||||
<Compile Include="DisposableAction.cs" />
|
||||
<Compile Include="Dune2ShpReader.cs" />
|
||||
<Compile Include="Exts.cs" />
|
||||
<Compile Include="FieldLoader.cs" />
|
||||
<Compile Include="FileSystem.cs" />
|
||||
<Compile Include="float2.cs" />
|
||||
<Compile Include="Folder.cs" />
|
||||
<Compile Include="Format2.cs" />
|
||||
<Compile Include="Format40.cs" />
|
||||
<Compile Include="Format80.cs" />
|
||||
<Compile Include="Graphics\IGraphicsDevice.cs" />
|
||||
<Compile Include="Graphics\Vertex.cs" />
|
||||
<Compile Include="IniFile.cs" />
|
||||
<Compile Include="int2.cs" />
|
||||
<Compile Include="IPaletteRemap.cs" />
|
||||
<Compile Include="Lazy.cs" />
|
||||
<Compile Include="Map.cs" />
|
||||
<Compile Include="MiniYaml.cs" />
|
||||
<Compile Include="PackageEntry.cs" />
|
||||
<Compile Include="Package.cs" />
|
||||
<Compile Include="Pair.cs" />
|
||||
<Compile Include="Palette.cs" />
|
||||
<Compile Include="PlayerColorRemap.cs" />
|
||||
<Compile Include="PriorityQueue.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ProtocolVersion.cs" />
|
||||
<Compile Include="Session.cs" />
|
||||
<Compile Include="ShpReader.cs" />
|
||||
<Compile Include="ShroudPaletteRemap.cs" />
|
||||
<Compile Include="SingleColorRemap.cs" />
|
||||
<Compile Include="Support\Log.cs" />
|
||||
<Compile Include="Support\Stopwatch.cs" />
|
||||
<Compile Include="Support\Timer.cs" />
|
||||
<Compile Include="Terrain.cs" />
|
||||
<Compile Include="TileReference.cs" />
|
||||
<Compile Include="TileSet.cs" />
|
||||
<Compile Include="TreeReference.cs" />
|
||||
<Compile Include="Tuple.cs" />
|
||||
<Compile Include="TypeDictionary.cs" />
|
||||
<Compile Include="Walkability.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
166
OpenRA.FileFormats/Package.cs
Normal file
166
OpenRA.FileFormats/Package.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public interface IFolder
|
||||
{
|
||||
Stream GetContent(string filename);
|
||||
IEnumerable<uint> AllFileHashes();
|
||||
}
|
||||
|
||||
public class Package : IFolder
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index;
|
||||
readonly bool isRmix, isEncrypted;
|
||||
readonly long dataStart;
|
||||
readonly Stream s;
|
||||
|
||||
public Package(string filename)
|
||||
{
|
||||
s = FileSystem.Open(filename);
|
||||
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
uint signature = reader.ReadUInt32();
|
||||
|
||||
isRmix = 0 == (signature & ~(uint)(MixFileFlags.Checksum | MixFileFlags.Encrypted));
|
||||
|
||||
if (isRmix)
|
||||
{
|
||||
isEncrypted = 0 != (signature & (uint)MixFileFlags.Encrypted);
|
||||
if( isEncrypted )
|
||||
{
|
||||
index = ParseRaHeader( s, out dataStart ).ToDictionary(x => x.Hash);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
s.Seek( 0, SeekOrigin.Begin );
|
||||
|
||||
isEncrypted = false;
|
||||
index = ParseTdHeader(s, out dataStart).ToDictionary(x => x.Hash);
|
||||
}
|
||||
|
||||
const long headerStart = 84;
|
||||
|
||||
List<PackageEntry> ParseRaHeader(Stream s, out long dataStart)
|
||||
{
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
byte[] keyblock = reader.ReadBytes(80);
|
||||
byte[] blowfishKey = new BlowfishKeyProvider().DecryptKey(keyblock);
|
||||
|
||||
uint[] h = ReadUints(reader, 2);
|
||||
|
||||
Blowfish fish = new Blowfish(blowfishKey);
|
||||
MemoryStream ms = Decrypt( h, fish );
|
||||
BinaryReader reader2 = new BinaryReader(ms);
|
||||
|
||||
ushort numFiles = reader2.ReadUInt16();
|
||||
uint datasize = reader2.ReadUInt32();
|
||||
|
||||
Console.WriteLine("{0} files, {1} kb", numFiles, datasize >> 10);
|
||||
|
||||
s.Position = headerStart;
|
||||
reader = new BinaryReader(s);
|
||||
|
||||
int byteCount = 6 + numFiles * PackageEntry.Size;
|
||||
h = ReadUints( reader, ( byteCount + 3 ) / 4 );
|
||||
|
||||
ms = Decrypt( h, fish );
|
||||
|
||||
dataStart = headerStart + byteCount + ( ( ~byteCount + 1 ) & 7 );
|
||||
|
||||
long ds;
|
||||
return ParseTdHeader( ms, out ds );
|
||||
}
|
||||
|
||||
static MemoryStream Decrypt( uint[] h, Blowfish fish )
|
||||
{
|
||||
uint[] decrypted = fish.Decrypt( h );
|
||||
|
||||
MemoryStream ms = new MemoryStream();
|
||||
BinaryWriter writer = new BinaryWriter( ms );
|
||||
foreach( uint t in decrypted )
|
||||
writer.Write( t );
|
||||
writer.Flush();
|
||||
|
||||
ms.Position = 0;
|
||||
return ms;
|
||||
}
|
||||
|
||||
uint[] ReadUints(BinaryReader r, int count)
|
||||
{
|
||||
uint[] ret = new uint[count];
|
||||
for (int i = 0; i < ret.Length; i++)
|
||||
ret[i] = r.ReadUInt32();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
List<PackageEntry> ParseTdHeader(Stream s, out long dataStart)
|
||||
{
|
||||
List<PackageEntry> items = new List<PackageEntry>();
|
||||
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
ushort numFiles = reader.ReadUInt16();
|
||||
/*uint dataSize = */reader.ReadUInt32();
|
||||
|
||||
for (int i = 0; i < numFiles; i++)
|
||||
items.Add(new PackageEntry(reader));
|
||||
|
||||
dataStart = s.Position;
|
||||
return items;
|
||||
}
|
||||
|
||||
public Stream GetContent(uint hash)
|
||||
{
|
||||
PackageEntry e;
|
||||
if (!index.TryGetValue(hash, out e))
|
||||
return null;
|
||||
|
||||
s.Seek( dataStart + e.Offset, SeekOrigin.Begin );
|
||||
byte[] data = new byte[ e.Length ];
|
||||
s.Read( data, 0, (int)e.Length );
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return GetContent(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
enum MixFileFlags : uint
|
||||
{
|
||||
Checksum = 0x10000,
|
||||
Encrypted = 0x20000,
|
||||
}
|
||||
}
|
||||
80
OpenRA.FileFormats/PackageEntry.cs
Normal file
80
OpenRA.FileFormats/PackageEntry.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class PackageEntry
|
||||
{
|
||||
public readonly uint Hash;
|
||||
public readonly uint Offset;
|
||||
public readonly uint Length;
|
||||
|
||||
public PackageEntry(BinaryReader r)
|
||||
{
|
||||
Hash = r.ReadUInt32();
|
||||
Offset = r.ReadUInt32();
|
||||
Length = r.ReadUInt32();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string filename;
|
||||
if (Names.TryGetValue(Hash, out filename))
|
||||
return string.Format("{0} - offset 0x{1:x8} - length 0x{2:x8}", filename, Offset, Length);
|
||||
else
|
||||
return string.Format("0x{0:x8} - offset 0x{1:x8} - length 0x{2:x8}", Hash, Offset, Length);
|
||||
}
|
||||
|
||||
public static uint HashFilename(string name)
|
||||
{
|
||||
if (name.Length > 12)
|
||||
name = name.Substring(0, 12);
|
||||
|
||||
name = name.ToUpperInvariant();
|
||||
if (name.Length % 4 != 0)
|
||||
name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');
|
||||
|
||||
MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
|
||||
BinaryReader reader = new BinaryReader(ms);
|
||||
|
||||
int len = name.Length >> 2;
|
||||
uint result = 0;
|
||||
|
||||
while (len-- != 0)
|
||||
result = ((result << 1) | (result >> 31)) + reader.ReadUInt32();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Dictionary<uint, string> Names = new Dictionary<uint,string>();
|
||||
|
||||
public static void AddStandardName(string s)
|
||||
{
|
||||
uint hash = HashFilename(s);
|
||||
Names.Add(hash, s);
|
||||
}
|
||||
|
||||
public const int Size = 12;
|
||||
}
|
||||
}
|
||||
75
OpenRA.FileFormats/Pair.cs
Normal file
75
OpenRA.FileFormats/Pair.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public struct Pair<T, U>
|
||||
{
|
||||
public T First;
|
||||
public U Second;
|
||||
|
||||
public Pair(T first, U second)
|
||||
{
|
||||
First = first;
|
||||
Second = second;
|
||||
}
|
||||
|
||||
static IEqualityComparer<T> tc = EqualityComparer<T>.Default;
|
||||
static IEqualityComparer<U> uc = EqualityComparer<U>.Default;
|
||||
|
||||
public static bool operator ==(Pair<T, U> a, Pair<T, U> b)
|
||||
{
|
||||
return tc.Equals(a.First, b.First) && uc.Equals(a.Second, b.Second);
|
||||
}
|
||||
|
||||
public static bool operator !=(Pair<T, U> a, Pair<T, U> b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is Pair<T, U>))
|
||||
return false;
|
||||
|
||||
return (Pair<T, U>)obj == this;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return First.GetHashCode() ^ Second.GetHashCode();
|
||||
}
|
||||
|
||||
public Pair<T, U> WithFirst(T t) { return new Pair<T, U>(t, Second); }
|
||||
public Pair<T, U> WithSecond(U u) { return new Pair<T, U>(First, u); }
|
||||
|
||||
public static T AsFirst(Pair<T, U> p) { return p.First; }
|
||||
public static U AsSecond(Pair<T, U> p) { return p.Second; }
|
||||
|
||||
public Pair<U, T> Swap() { return Pair.New(Second, First); }
|
||||
}
|
||||
|
||||
public static class Pair
|
||||
{
|
||||
public static Pair<T, U> New<T, U>(T t, U u) { return new Pair<T, U>(t, u); }
|
||||
}
|
||||
}
|
||||
60
OpenRA.FileFormats/Palette.cs
Normal file
60
OpenRA.FileFormats/Palette.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Palette
|
||||
{
|
||||
List<Color> colors = new List<Color>();
|
||||
|
||||
public Color GetColor(int index)
|
||||
{
|
||||
return colors[index];
|
||||
}
|
||||
|
||||
public Palette(Stream s)
|
||||
{
|
||||
using (BinaryReader reader = new BinaryReader(s))
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
byte r = (byte)(reader.ReadByte() << 2);
|
||||
byte g = (byte)(reader.ReadByte() << 2);
|
||||
byte b = (byte)(reader.ReadByte() << 2);
|
||||
|
||||
colors.Add(Color.FromArgb(r, g, b));
|
||||
}
|
||||
}
|
||||
colors[0] = Color.FromArgb(0, 0, 0, 0);
|
||||
colors[3] = Color.FromArgb(178, 0, 0, 0);
|
||||
colors[4] = Color.FromArgb(140, 0, 0, 0);
|
||||
}
|
||||
|
||||
public Palette(Palette p, IPaletteRemap r)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
colors.Add(r.GetRemappedColor(p.GetColor(i), i));
|
||||
}
|
||||
}
|
||||
}
|
||||
50
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file
50
OpenRA.FileFormats/PlayerColorRemap.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class PlayerColorRemap : IPaletteRemap
|
||||
{
|
||||
Dictionary<int, Color> remapColors;
|
||||
|
||||
public PlayerColorRemap(Stream s)
|
||||
{
|
||||
var yaml = MiniYaml.FromStream(s);
|
||||
remapColors = yaml.ToDictionary(
|
||||
y => int.Parse(y.Key),
|
||||
y => ArrayToColor((int[])FieldLoader.GetValue(
|
||||
typeof(int[]), y.Value.Value.Trim())));
|
||||
}
|
||||
|
||||
static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2], x[3]); }
|
||||
|
||||
public Color GetRemappedColor(Color original, int index)
|
||||
{
|
||||
Color c;
|
||||
return remapColors.TryGetValue(index, out c)
|
||||
? c : original;
|
||||
}
|
||||
}
|
||||
}
|
||||
113
OpenRA.FileFormats/PriorityQueue.cs
Normal file
113
OpenRA.FileFormats/PriorityQueue.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class PriorityQueue<T>
|
||||
where T : IComparable<T>
|
||||
{
|
||||
List<T[]> items = new List<T[]>();
|
||||
int level, index;
|
||||
|
||||
public PriorityQueue()
|
||||
{
|
||||
items.Add(new T[1]);
|
||||
}
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
int addLevel = level;
|
||||
int addIndex = index;
|
||||
|
||||
while (addLevel >= 1 && Above(addLevel, addIndex).CompareTo(item) > 0)
|
||||
{
|
||||
items[addLevel][addIndex] = Above(addLevel, addIndex);
|
||||
--addLevel;
|
||||
addIndex >>= 1;
|
||||
}
|
||||
|
||||
items[addLevel][addIndex] = item;
|
||||
|
||||
if (++index >= (1 << level))
|
||||
{
|
||||
index = 0;
|
||||
if (items.Count <= ++level)
|
||||
items.Add(new T[1 << level]);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Empty { get { return (level == 0); } }
|
||||
|
||||
T At(int level, int index) { return items[level][index]; }
|
||||
T Above(int level, int index) { return items[level - 1][index >> 1]; }
|
||||
|
||||
T Last()
|
||||
{
|
||||
int lastLevel = level;
|
||||
int lastIndex = index;
|
||||
|
||||
if (--lastIndex < 0)
|
||||
lastIndex = (1 << --lastLevel) - 1;
|
||||
|
||||
return At(lastLevel, lastIndex);
|
||||
}
|
||||
|
||||
public T Pop()
|
||||
{
|
||||
if (level == 0 && index == 0)
|
||||
throw new InvalidOperationException("Attempting to pop empty PriorityQueue");
|
||||
|
||||
T ret = At(0, 0);
|
||||
BubbleInto(0, 0, Last());
|
||||
if (--index < 0)
|
||||
index = (1 << --level) - 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BubbleInto(int intoLevel, int intoIndex, T val)
|
||||
{
|
||||
int downLevel = intoLevel + 1;
|
||||
int downIndex = intoIndex << 1;
|
||||
|
||||
if (downLevel > level || (downLevel == level && downIndex >= index))
|
||||
{
|
||||
items[intoLevel][intoIndex] = val;
|
||||
return;
|
||||
}
|
||||
|
||||
if (downLevel <= level && downIndex < index - 1 &&
|
||||
At(downLevel, downIndex).CompareTo(At(downLevel, downIndex + 1)) >= 0)
|
||||
++downIndex;
|
||||
|
||||
if (val.CompareTo(At(downLevel, downIndex)) <= 0)
|
||||
{
|
||||
items[intoLevel][intoIndex] = val;
|
||||
return;
|
||||
}
|
||||
|
||||
items[intoLevel][intoIndex] = At(downLevel, downIndex);
|
||||
BubbleInto(downLevel, downIndex, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
OpenRA.FileFormats/Properties/AssemblyInfo.cs
Normal file
36
OpenRA.FileFormats/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("OpenRA.FileFormats")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("OpenRA.FileFormats")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2007,2009,2010")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
28
OpenRA.FileFormats/ProtocolVersion.cs
Normal file
28
OpenRA.FileFormats/ProtocolVersion.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class ProtocolVersion
|
||||
{
|
||||
// you *must* increment this whenever you make an incompatible protocol change
|
||||
public static readonly int Version = 2;
|
||||
}
|
||||
}
|
||||
84
OpenRA.FileFormats/Session.cs
Normal file
84
OpenRA.FileFormats/Session.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Session
|
||||
{
|
||||
public List<Client> Clients = new List<Client>();
|
||||
public Global GlobalSettings = new Global();
|
||||
|
||||
public enum ClientState
|
||||
{
|
||||
NotReady,
|
||||
Downloading,
|
||||
Ready
|
||||
}
|
||||
|
||||
public class Client
|
||||
{
|
||||
public int Index;
|
||||
public int PaletteIndex;
|
||||
public string Country;
|
||||
public int SpawnPoint;
|
||||
public string Name;
|
||||
public ClientState State;
|
||||
}
|
||||
|
||||
public class Global
|
||||
{
|
||||
public string Map = "scm12ea.ini";
|
||||
public string[] Packages = {}; // filename:sha1 pairs.
|
||||
public string[] Mods = { "ra" }; // mod names
|
||||
public int OrderLatency = 3;
|
||||
}
|
||||
}
|
||||
|
||||
public class Manifest
|
||||
{
|
||||
public readonly string[] Folders = { };
|
||||
public readonly string[] Packages = { };
|
||||
public readonly string[] LegacyRules = { };
|
||||
public readonly string[] Rules = { };
|
||||
public readonly string[] Sequences = { };
|
||||
public readonly string[] Chrome = { };
|
||||
public readonly string[] Assemblies = { };
|
||||
|
||||
public Manifest(string[] mods)
|
||||
{
|
||||
var yaml = mods
|
||||
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
|
||||
.Aggregate(MiniYaml.Merge);
|
||||
|
||||
Folders = YamlList(yaml, "Folders");
|
||||
Packages = YamlList(yaml, "Packages");
|
||||
LegacyRules = YamlList(yaml, "LegacyRules");
|
||||
Rules = YamlList(yaml, "Rules");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
Assemblies = YamlList(yaml, "Assemblies");
|
||||
}
|
||||
|
||||
static string[] YamlList(Dictionary<string, MiniYaml> ys, string key) { return ys[key].Nodes.Keys.ToArray(); }
|
||||
}
|
||||
}
|
||||
177
OpenRA.FileFormats/ShpReader.cs
Normal file
177
OpenRA.FileFormats/ShpReader.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class ImageHeader
|
||||
{
|
||||
public uint Offset;
|
||||
public Format Format;
|
||||
|
||||
public uint RefOffset;
|
||||
public Format RefFormat;
|
||||
public ImageHeader RefImage;
|
||||
|
||||
public byte[] Image;
|
||||
|
||||
public ImageHeader( BinaryReader reader )
|
||||
{
|
||||
Offset = reader.ReadUInt32();
|
||||
Format = (Format)( Offset >> 24 );
|
||||
Offset &= 0xFFFFFF;
|
||||
|
||||
RefOffset = reader.ReadUInt16();
|
||||
RefFormat = (Format)reader.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
public enum Format
|
||||
{
|
||||
Format20 = 0x20,
|
||||
Format40 = 0x40,
|
||||
Format80 = 0x80,
|
||||
}
|
||||
|
||||
public class ShpReader : IEnumerable<ImageHeader>
|
||||
{
|
||||
public readonly int ImageCount;
|
||||
public readonly ushort Width;
|
||||
public readonly ushort Height;
|
||||
|
||||
public Size Size { get { return new Size(Width, Height); } }
|
||||
|
||||
private readonly List<ImageHeader> headers = new List<ImageHeader>();
|
||||
|
||||
int recurseDepth = 0;
|
||||
|
||||
public ShpReader( Stream stream )
|
||||
{
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
|
||||
ImageCount = reader.ReadUInt16();
|
||||
reader.ReadUInt16();
|
||||
reader.ReadUInt16();
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
reader.ReadUInt32();
|
||||
|
||||
for( int i = 0 ; i < ImageCount ; i++ )
|
||||
headers.Add( new ImageHeader( reader ) );
|
||||
|
||||
new ImageHeader( reader ); // end-of-file header
|
||||
new ImageHeader( reader ); // all-zeroes header
|
||||
|
||||
Dictionary<uint, ImageHeader> offsets = new Dictionary<uint, ImageHeader>();
|
||||
foreach( ImageHeader h in headers )
|
||||
offsets.Add( h.Offset, h );
|
||||
|
||||
for( int i = 0 ; i < ImageCount ; i++ )
|
||||
{
|
||||
ImageHeader h = headers[ i ];
|
||||
if( h.Format == Format.Format20 )
|
||||
h.RefImage = headers[ i - 1 ];
|
||||
|
||||
else if( h.Format == Format.Format40 )
|
||||
{
|
||||
if( !offsets.TryGetValue( h.RefOffset, out h.RefImage ) )
|
||||
throw new InvalidDataException( string.Format( "Reference doesnt point to image data {0}->{1}", h.Offset, h.RefOffset ) );
|
||||
}
|
||||
}
|
||||
|
||||
foreach( ImageHeader h in headers )
|
||||
Decompress( stream, h );
|
||||
}
|
||||
|
||||
public ImageHeader this[ int index ]
|
||||
{
|
||||
get { return headers[ index ]; }
|
||||
}
|
||||
|
||||
void Decompress( Stream stream, ImageHeader h )
|
||||
{
|
||||
if( recurseDepth > ImageCount )
|
||||
throw new InvalidDataException( "Format20/40 headers contain infinite loop" );
|
||||
|
||||
switch( h.Format )
|
||||
{
|
||||
case Format.Format20:
|
||||
case Format.Format40:
|
||||
{
|
||||
if( h.RefImage.Image == null )
|
||||
{
|
||||
++recurseDepth;
|
||||
Decompress( stream, h.RefImage );
|
||||
--recurseDepth;
|
||||
}
|
||||
|
||||
h.Image = CopyImageData( h.RefImage.Image );
|
||||
Format40.DecodeInto(ReadCompressedData(stream, h), h.Image);
|
||||
break;
|
||||
}
|
||||
case Format.Format80:
|
||||
{
|
||||
byte[] imageBytes = new byte[ Width * Height ];
|
||||
Format80.DecodeInto( ReadCompressedData( stream, h ), imageBytes );
|
||||
h.Image = imageBytes;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] ReadCompressedData( Stream stream, ImageHeader h )
|
||||
{
|
||||
stream.Position = h.Offset;
|
||||
// Actually, far too big. There's no length field with the correct length though :(
|
||||
int compressedLength = (int)( stream.Length - stream.Position );
|
||||
|
||||
byte[] compressedBytes = new byte[ compressedLength ];
|
||||
stream.Read( compressedBytes, 0, compressedLength );
|
||||
|
||||
//MemoryStream ms = new MemoryStream( compressedBytes );
|
||||
return compressedBytes;
|
||||
}
|
||||
|
||||
private byte[] CopyImageData( byte[] baseImage )
|
||||
{
|
||||
byte[] imageData = new byte[ Width * Height ];
|
||||
for( int i = 0 ; i < Width * Height ; i++ )
|
||||
imageData[ i ] = baseImage[ i ];
|
||||
|
||||
return imageData;
|
||||
}
|
||||
|
||||
public IEnumerator<ImageHeader> GetEnumerator()
|
||||
{
|
||||
return headers.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
48
OpenRA.FileFormats/ShroudPaletteRemap.cs
Normal file
48
OpenRA.FileFormats/ShroudPaletteRemap.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class ShroudPaletteRemap : IPaletteRemap
|
||||
{
|
||||
public Color GetRemappedColor(Color original, int index)
|
||||
{
|
||||
// false-color version for debug
|
||||
|
||||
//return new[] {
|
||||
// Color.FromArgb(64,0,0,0), Color.Green,
|
||||
// Color.Blue, Color.Yellow,
|
||||
// Color.Green,
|
||||
// Color.Red,
|
||||
// Color.Purple,
|
||||
// Color.Cyan}[index % 8];
|
||||
|
||||
return new[] {
|
||||
Color.Transparent, Color.Green,
|
||||
Color.Blue, Color.Yellow,
|
||||
Color.Black,
|
||||
Color.FromArgb(192,0,0,0),
|
||||
Color.FromArgb(128,0,0,0),
|
||||
Color.FromArgb(64,0,0,0)}[index % 8];
|
||||
}
|
||||
}
|
||||
}
|
||||
38
OpenRA.FileFormats/SingleColorRemap.cs
Normal file
38
OpenRA.FileFormats/SingleColorRemap.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class SingleColorRemap : IPaletteRemap
|
||||
{
|
||||
Color c;
|
||||
public SingleColorRemap(Color c)
|
||||
{
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
public Color GetRemappedColor(Color original, int index)
|
||||
{
|
||||
return original.A > 0 ? c : original;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
OpenRA.FileFormats/Support/Log.cs
Executable file
39
OpenRA.FileFormats/Support/Log.cs
Executable file
@@ -0,0 +1,39 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Log
|
||||
{
|
||||
static StreamWriter writer = File.CreateText("log.txt");
|
||||
|
||||
static Log()
|
||||
{
|
||||
writer.AutoFlush = true;
|
||||
}
|
||||
|
||||
public static void Write(string format, params object[] args)
|
||||
{
|
||||
writer.WriteLine(format, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
OpenRA.FileFormats/Support/Stopwatch.cs
Executable file
42
OpenRA.FileFormats/Support/Stopwatch.cs
Executable file
@@ -0,0 +1,42 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using Tao.Sdl;
|
||||
namespace OpenRA.Support
|
||||
{
|
||||
public class Stopwatch
|
||||
{
|
||||
int start;
|
||||
public Stopwatch()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public double ElapsedTime()
|
||||
{
|
||||
return (1.0/1000.0) * (double)(Sdl.SDL_GetTicks() - start);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
start = Sdl.SDL_GetTicks();
|
||||
}
|
||||
}
|
||||
}
|
||||
35
OpenRA.FileFormats/Support/Timer.cs
Executable file
35
OpenRA.FileFormats/Support/Timer.cs
Executable file
@@ -0,0 +1,35 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.Support
|
||||
{
|
||||
public static class Timer
|
||||
{
|
||||
static Stopwatch sw = new Stopwatch();
|
||||
static double lastTime = 0;
|
||||
|
||||
public static void Time( string message )
|
||||
{
|
||||
var time = sw.ElapsedTime();
|
||||
Log.Write( message, time - lastTime );
|
||||
lastTime = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
OpenRA.FileFormats/Terrain.cs
Normal file
67
OpenRA.FileFormats/Terrain.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Terrain
|
||||
{
|
||||
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
|
||||
|
||||
public Terrain( Stream stream )
|
||||
{
|
||||
int Width, Height;
|
||||
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
Width = reader.ReadUInt16();
|
||||
Height = reader.ReadUInt16();
|
||||
|
||||
if( Width != 24 || Height != 24 )
|
||||
throw new InvalidDataException( string.Format( "{0}x{1}", Width, Height ) );
|
||||
|
||||
/*NumTiles = */reader.ReadUInt16();
|
||||
reader.ReadUInt16();
|
||||
/*XDim = */reader.ReadUInt16();
|
||||
/*YDim = */reader.ReadUInt16();
|
||||
/*uint FileSize = */reader.ReadUInt32();
|
||||
uint ImgStart = reader.ReadUInt32();
|
||||
reader.ReadUInt32();
|
||||
reader.ReadUInt32();
|
||||
int IndexEnd = reader.ReadInt32();
|
||||
reader.ReadUInt32();
|
||||
int IndexStart = reader.ReadInt32();
|
||||
|
||||
stream.Position = IndexStart;
|
||||
|
||||
foreach( byte b in new BinaryReader(stream).ReadBytes(IndexEnd - IndexStart) )
|
||||
{
|
||||
if (b != 255)
|
||||
{
|
||||
stream.Position = ImgStart + b * 24 * 24;
|
||||
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(24 * 24));
|
||||
}
|
||||
else
|
||||
TileBitmapBytes.Add(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
OpenRA.FileFormats/TileReference.cs
Normal file
45
OpenRA.FileFormats/TileReference.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public struct TileReference
|
||||
{
|
||||
public ushort tile;
|
||||
public byte image;
|
||||
public byte overlay;
|
||||
public byte smudge;
|
||||
public byte density; /* used for ore/gems */
|
||||
|
||||
public override int GetHashCode() { return tile.GetHashCode() ^ image.GetHashCode(); }
|
||||
|
||||
public override bool Equals( object obj )
|
||||
{
|
||||
if( obj == null )
|
||||
return false;
|
||||
|
||||
TileReference r = (TileReference)obj;
|
||||
return ( r.image == image && r.tile == tile );
|
||||
}
|
||||
|
||||
public static bool operator ==( TileReference a, TileReference b ) { return a.Equals( b ); }
|
||||
public static bool operator !=( TileReference a, TileReference b ) { return !a.Equals( b ); }
|
||||
}
|
||||
}
|
||||
109
OpenRA.FileFormats/TileSet.cs
Normal file
109
OpenRA.FileFormats/TileSet.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class TileSet
|
||||
{
|
||||
public readonly Dictionary<ushort, Terrain> tiles = new Dictionary<ushort, Terrain>();
|
||||
|
||||
public readonly Walkability Walkability = new Walkability();
|
||||
public readonly Dictionary<ushort, TileTemplate> walk
|
||||
= new Dictionary<ushort, TileTemplate>();
|
||||
|
||||
string NextLine( StreamReader reader )
|
||||
{
|
||||
string ret;
|
||||
do
|
||||
{
|
||||
ret = reader.ReadLine();
|
||||
if( ret == null )
|
||||
return null;
|
||||
ret = ret.Trim();
|
||||
}
|
||||
while( ret.Length == 0 || ret[ 0 ] == ';' );
|
||||
return ret;
|
||||
}
|
||||
|
||||
public TileSet( string suffix )
|
||||
{
|
||||
Walkability = new Walkability();
|
||||
|
||||
char tileSetChar = char.ToUpperInvariant( suffix[ 1 ] );
|
||||
StreamReader tileIdFile = new StreamReader( FileSystem.Open( "tileSet.til" ) );
|
||||
|
||||
while( true )
|
||||
{
|
||||
string tileSetStr = NextLine( tileIdFile );
|
||||
string countStr = NextLine( tileIdFile );
|
||||
string startStr = NextLine( tileIdFile );
|
||||
string pattern = NextLine( tileIdFile );
|
||||
if( tileSetStr == null || countStr == null || startStr == null || pattern == null )
|
||||
break;
|
||||
|
||||
if( tileSetStr.IndexOf( tileSetChar.ToString() ) == -1 )
|
||||
continue;
|
||||
|
||||
int count = int.Parse( countStr );
|
||||
int start = int.Parse( startStr, NumberStyles.HexNumber );
|
||||
for( int i = 0 ; i < count ; i++ )
|
||||
{
|
||||
string tilename = string.Format(pattern, i + 1);
|
||||
|
||||
if (!walk.ContainsKey((ushort)(start + i)))
|
||||
walk.Add((ushort)(start + i), Walkability.GetWalkability(tilename));
|
||||
|
||||
using( Stream s = FileSystem.Open( tilename + suffix ) )
|
||||
{
|
||||
if( !tiles.ContainsKey( (ushort)( start + i ) ) )
|
||||
tiles.Add( (ushort)( start + i ), new Terrain( s ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tileIdFile.Close();
|
||||
}
|
||||
|
||||
public byte[] GetBytes(TileReference r)
|
||||
{
|
||||
Terrain tile;
|
||||
if( tiles.TryGetValue( r.tile, out tile ) )
|
||||
return tile.TileBitmapBytes[ r.image ];
|
||||
|
||||
byte[] missingTile = new byte[ 24 * 24 ];
|
||||
for( int i = 0 ; i < missingTile.Length ; i++ )
|
||||
missingTile[ i ] = 0x36;
|
||||
|
||||
return missingTile;
|
||||
}
|
||||
|
||||
public int GetWalkability(TileReference r)
|
||||
{
|
||||
if (r.tile == 0xff || r.tile == 0xffff)
|
||||
r.image = 0;
|
||||
|
||||
return walk[r.tile].TerrainType[r.image];
|
||||
}
|
||||
}
|
||||
}
|
||||
40
OpenRA.FileFormats/TreeReference.cs
Normal file
40
OpenRA.FileFormats/TreeReference.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public struct TreeReference
|
||||
{
|
||||
public readonly int X;
|
||||
public readonly int Y;
|
||||
public readonly string Image;
|
||||
|
||||
public TreeReference(int xy, string image)
|
||||
{
|
||||
X = xy % 128;
|
||||
Y = xy / 128;
|
||||
Image = image;
|
||||
}
|
||||
|
||||
public Point Location { get { return new Point(X, Y); } }
|
||||
}
|
||||
}
|
||||
39
OpenRA.FileFormats/Tuple.cs
Normal file
39
OpenRA.FileFormats/Tuple.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class Tuple<A, B, C>
|
||||
{
|
||||
public A a;
|
||||
public B b;
|
||||
public C c;
|
||||
|
||||
public Tuple(A a, B b, C c) { this.a = a; this.b = b; this.c = c; }
|
||||
}
|
||||
|
||||
public static class Tuple
|
||||
{
|
||||
public static Tuple<A, B, C> New<A, B, C>(A a, B b, C c)
|
||||
{
|
||||
return new Tuple<A, B, C>(a, b, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
OpenRA.FileFormats/TypeDictionary.cs
Normal file
115
OpenRA.FileFormats/TypeDictionary.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class TypeDictionary
|
||||
{
|
||||
Dictionary<Type, object> dataSingular = new Dictionary<Type, object>();
|
||||
Dictionary<Type, List<object>> dataMultiple = new Dictionary<Type, List<object>>();
|
||||
|
||||
public void Add( object val )
|
||||
{
|
||||
var t = val.GetType();
|
||||
|
||||
foreach( var i in t.GetInterfaces() )
|
||||
InnerAdd( i, val );
|
||||
foreach( var tt in t.BaseTypes() )
|
||||
InnerAdd( tt, val );
|
||||
}
|
||||
|
||||
void InnerAdd( Type t, object val )
|
||||
{
|
||||
List<object> objs;
|
||||
object obj;
|
||||
|
||||
if( dataMultiple.TryGetValue( t, out objs ) )
|
||||
objs.Add( val );
|
||||
else if( dataSingular.TryGetValue( t, out obj ) )
|
||||
{
|
||||
dataSingular.Remove( t );
|
||||
dataMultiple.Add( t, new List<object> { obj, val } );
|
||||
}
|
||||
else
|
||||
dataSingular.Add( t, val );
|
||||
}
|
||||
|
||||
public bool Contains<T>()
|
||||
{
|
||||
return dataSingular.ContainsKey( typeof( T ) ) || dataMultiple.ContainsKey( typeof( T ) );
|
||||
}
|
||||
|
||||
public T Get<T>()
|
||||
{
|
||||
if( dataMultiple.ContainsKey( typeof( T ) ) )
|
||||
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||
|
||||
object ret;
|
||||
if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
|
||||
throw new InvalidOperationException(string.Format("TypeDictionary does not contain instance of type `{0}`", typeof(T)));
|
||||
return (T)ret;
|
||||
}
|
||||
|
||||
public T GetOrDefault<T>()
|
||||
{
|
||||
if( dataMultiple.ContainsKey( typeof( T ) ) )
|
||||
throw new InvalidOperationException( string.Format( "TypeDictionary contains multiple instance of type `{0}`", typeof( T ) ) );
|
||||
|
||||
object ret;
|
||||
if( !dataSingular.TryGetValue( typeof( T ), out ret ) )
|
||||
return default( T );
|
||||
return (T)ret;
|
||||
}
|
||||
|
||||
public IEnumerable<T> WithInterface<T>()
|
||||
{
|
||||
List<object> objs;
|
||||
object obj;
|
||||
|
||||
if( dataMultiple.TryGetValue( typeof( T ), out objs ) )
|
||||
return objs.Cast<T>();
|
||||
else if( dataSingular.TryGetValue( typeof( T ), out obj ) )
|
||||
return new T[] { (T)obj };
|
||||
else
|
||||
return new T[ 0 ];
|
||||
}
|
||||
|
||||
public IEnumerator<object> GetEnumerator()
|
||||
{
|
||||
return WithInterface<object>().GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
static class TypeExts
|
||||
{
|
||||
public static IEnumerable<Type> BaseTypes( this Type t )
|
||||
{
|
||||
while( t != null )
|
||||
{
|
||||
yield return t;
|
||||
t = t.BaseType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
OpenRA.FileFormats/Walkability.cs
Normal file
73
OpenRA.FileFormats/Walkability.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class TileTemplate
|
||||
{
|
||||
public int Index; // not valid for `interior` stuff. only used for bridges.
|
||||
public string Name;
|
||||
public int2 Size;
|
||||
public string Bridge;
|
||||
public float HP;
|
||||
public Dictionary<int, int> TerrainType = new Dictionary<int, int>();
|
||||
}
|
||||
|
||||
public class Walkability
|
||||
{
|
||||
Dictionary<string, TileTemplate> walkability
|
||||
= new Dictionary<string,TileTemplate>();
|
||||
|
||||
public Walkability()
|
||||
{
|
||||
var file = new IniFile( FileSystem.Open( "templates.ini" ) );
|
||||
|
||||
foreach (var section in file.Sections)
|
||||
{
|
||||
var tile = new TileTemplate
|
||||
{
|
||||
Size = new int2(
|
||||
int.Parse(section.GetValue("width", "0")),
|
||||
int.Parse(section.GetValue("height", "0"))),
|
||||
TerrainType = section
|
||||
.Where(p => p.Key.StartsWith("tiletype"))
|
||||
.ToDictionary(
|
||||
p => int.Parse(p.Key.Substring(8)),
|
||||
p => int.Parse(p.Value)),
|
||||
Name = section.GetValue("Name", null).ToLowerInvariant(),
|
||||
Bridge = section.GetValue("bridge", null),
|
||||
HP = float.Parse(section.GetValue("hp", "0"))
|
||||
};
|
||||
tile.Index = -1;
|
||||
int.TryParse(section.Name.Substring(3), out tile.Index);
|
||||
|
||||
walkability[tile.Name] = tile;
|
||||
}
|
||||
}
|
||||
|
||||
public TileTemplate GetWalkability(string terrainName)
|
||||
{
|
||||
return walkability[terrainName];
|
||||
}
|
||||
}
|
||||
}
|
||||
113
OpenRA.FileFormats/float2.cs
Normal file
113
OpenRA.FileFormats/float2.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct float2
|
||||
{
|
||||
public float X, Y;
|
||||
|
||||
public float2(float x, float y) { X = x; Y = y; }
|
||||
public float2(PointF p) { X = p.X; Y = p.Y; }
|
||||
public float2(Point p) { X = p.X; Y = p.Y; }
|
||||
public float2(Size p) { X = p.Width; Y = p.Height; }
|
||||
public float2(SizeF p) { X = p.Width; Y = p.Height; }
|
||||
|
||||
public PointF ToPointF() { return new PointF(X, Y); }
|
||||
public SizeF ToSizeF() { return new SizeF(X, Y); }
|
||||
|
||||
public static implicit operator float2(int2 src) { return new float2(src.X, src.Y); }
|
||||
|
||||
public static float2 operator +(float2 a, float2 b) { return new float2(a.X + b.X, a.Y + b.Y); }
|
||||
public static float2 operator -(float2 a, float2 b) { return new float2(a.X - b.X, a.Y - b.Y); }
|
||||
|
||||
public static float2 operator -(float2 a) { return new float2(-a.X, -a.Y); }
|
||||
|
||||
public static float Lerp(float a, float b, float t) { return a + t * (b - a); }
|
||||
|
||||
public static float2 Lerp(float2 a, float2 b, float t)
|
||||
{
|
||||
return new float2(
|
||||
Lerp(a.X, b.X, t),
|
||||
Lerp(a.Y, b.Y, t));
|
||||
}
|
||||
|
||||
public static float2 Lerp(float2 a, float2 b, float2 t)
|
||||
{
|
||||
return new float2(
|
||||
Lerp(a.X, b.X, t.X),
|
||||
Lerp(a.Y, b.Y, t.Y));
|
||||
}
|
||||
|
||||
public static float2 FromAngle(float a) { return new float2((float)Math.Sin(a), (float)Math.Cos(a)); }
|
||||
|
||||
static float Constrain(float x, float a, float b) { return x < a ? a : x > b ? b : x; }
|
||||
|
||||
public float2 Constrain(float2 min, float2 max)
|
||||
{
|
||||
return new float2(
|
||||
Constrain(X, min.X, max.X),
|
||||
Constrain(Y, min.Y, max.Y));
|
||||
}
|
||||
|
||||
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
|
||||
public static float2 operator *( float2 a, float2 b ) { return new float2( a.X * b.X, a.Y * b.Y ); }
|
||||
public static float2 operator /( float2 a, float2 b ) { return new float2( a.X / b.X, a.Y / b.Y ); }
|
||||
|
||||
public static bool operator ==(float2 me, float2 other) { return (me.X == other.X && me.Y == other.Y); }
|
||||
public static bool operator !=(float2 me, float2 other) { return !(me == other); }
|
||||
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
float2 o = (float2)obj;
|
||||
return o == this;
|
||||
}
|
||||
|
||||
public static readonly float2 Zero = new float2(0, 0);
|
||||
|
||||
public static bool WithinEpsilon(float2 a, float2 b, float e)
|
||||
{
|
||||
float2 d = a - b;
|
||||
return Math.Abs(d.X) < e && Math.Abs(d.Y) < e;
|
||||
}
|
||||
|
||||
public float2 Sign() { return new float2(Math.Sign(X), Math.Sign(Y)); }
|
||||
public static float Dot(float2 a, float2 b) { return a.X * b.X + a.Y * b.Y; }
|
||||
public float2 Round() { return new float2((float)Math.Round(X), (float)Math.Round(Y)); }
|
||||
|
||||
public override string ToString() { return string.Format("({0},{1})", X, Y); }
|
||||
public int2 ToInt2() { return new int2((int)X, (int)Y); }
|
||||
|
||||
public static float2 Max(float2 a, float2 b) { return new float2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
|
||||
public static float2 Min(float2 a, float2 b) { return new float2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
|
||||
|
||||
public float LengthSquared { get { return X * X + Y * Y; } }
|
||||
public float Length { get { return (float)Math.Sqrt(LengthSquared); } }
|
||||
}
|
||||
}
|
||||
67
OpenRA.FileFormats/int2.cs
Normal file
67
OpenRA.FileFormats/int2.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public struct int2
|
||||
{
|
||||
public int X,Y;
|
||||
|
||||
public int2( int x, int y ) { this.X = x; this.Y = y; }
|
||||
public int2( Point p ) { X = p.X; Y = p.Y; }
|
||||
public int2( Size p ) { X = p.Width; Y = p.Height; }
|
||||
|
||||
public static int2 operator +(int2 a, int2 b) { return new int2(a.X + b.X, a.Y + b.Y); }
|
||||
public static int2 operator -(int2 a, int2 b) { return new int2(a.X - b.X, a.Y - b.Y); }
|
||||
public static int2 operator *(int a, int2 b) { return new int2(a * b.X, a * b.Y); }
|
||||
public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); }
|
||||
|
||||
public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); }
|
||||
public static bool operator !=(int2 me, int2 other) { return !(me == other); }
|
||||
|
||||
public int2 Sign() { return new int2(Math.Sign(X), Math.Sign(Y)); }
|
||||
public int2 Abs() { return new int2( Math.Abs( X ), Math.Abs( Y ) ); }
|
||||
public int LengthSquared { get { return X * X + Y * Y; } }
|
||||
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
|
||||
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode(); }
|
||||
|
||||
public static int2 Max(int2 a, int2 b) { return new int2(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)); }
|
||||
public static int2 Min(int2 a, int2 b) { return new int2(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y)); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
int2 o = (int2)obj;
|
||||
return o == this;
|
||||
}
|
||||
|
||||
public static readonly int2 Zero = new int2(0, 0);
|
||||
public Point ToPoint() { return new Point(X, Y); }
|
||||
public PointF ToPointF() { return new PointF(X, Y); }
|
||||
public float2 ToFloat2() { return new float2(X, Y); }
|
||||
|
||||
public override string ToString() { return string.Format("({0},{1})", X, Y); }
|
||||
}
|
||||
}
|
||||
238
OpenRA.Game/Actor.cs
Executable file
238
OpenRA.Game/Actor.cs
Executable file
@@ -0,0 +1,238 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Traits;
|
||||
using OpenRA.Traits.Activities;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Actor
|
||||
{
|
||||
[Sync]
|
||||
public readonly TypeDictionary traits = new TypeDictionary();
|
||||
public readonly ActorInfo Info;
|
||||
|
||||
public readonly World World;
|
||||
public readonly uint ActorID;
|
||||
|
||||
[Sync]
|
||||
public int2 Location;
|
||||
[Sync]
|
||||
public Player Owner;
|
||||
[Sync]
|
||||
public int Health;
|
||||
IActivity currentActivity;
|
||||
|
||||
public Actor( World world, string name, int2 location, Player owner )
|
||||
{
|
||||
World = world;
|
||||
ActorID = world.NextAID();
|
||||
Location = location;
|
||||
CenterLocation = Traits.Util.CenterOfCell(Location);
|
||||
Owner = owner;
|
||||
|
||||
if (name != null)
|
||||
{
|
||||
//Log.Write("Loading {0}",name.ToLowerInvariant());
|
||||
Info = Rules.Info[name.ToLowerInvariant()];
|
||||
Health = this.GetMaxHP();
|
||||
|
||||
foreach (var trait in Info.TraitsInConstructOrder())
|
||||
traits.Add(trait.Create(this));
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
while (currentActivity != null)
|
||||
{
|
||||
var a = currentActivity;
|
||||
currentActivity = a.Tick(this) ?? new Idle();
|
||||
if (a == currentActivity || currentActivity is Idle) break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsIdle
|
||||
{
|
||||
get { return currentActivity == null || currentActivity is Idle; }
|
||||
}
|
||||
|
||||
public float2 CenterLocation;
|
||||
float2 SelectedSize
|
||||
{
|
||||
get // todo: inline into GetBounds
|
||||
{
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
if (si != null && si.Bounds != null)
|
||||
return new float2(si.Bounds[0], si.Bounds[1]);
|
||||
|
||||
var firstSprite = Render().FirstOrDefault();
|
||||
if (firstSprite.Sprite == null) return float2.Zero;
|
||||
return firstSprite.Sprite.size;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
var mods = traits.WithInterface<IRenderModifier>();
|
||||
var sprites = traits.WithInterface<IRender>().SelectMany(x => x.Render(this));
|
||||
return mods.Aggregate(sprites, (m, p) => p.ModifyRender(this, m));
|
||||
}
|
||||
|
||||
public Order Order( int2 xy, MouseInput mi )
|
||||
{
|
||||
if (Owner != World.LocalPlayer)
|
||||
return null;
|
||||
|
||||
if (!World.Map.IsInMap(xy.X, xy.Y))
|
||||
return null;
|
||||
|
||||
var underCursor = World.FindUnitsAtMouse(mi.Location).FirstOrDefault();
|
||||
|
||||
if (underCursor != null && !underCursor.traits.Contains<Selectable>())
|
||||
underCursor = null;
|
||||
|
||||
return traits.WithInterface<IIssueOrder>()
|
||||
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
|
||||
.FirstOrDefault( x => x != null );
|
||||
}
|
||||
|
||||
public RectangleF GetBounds(bool useAltitude)
|
||||
{
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
|
||||
var size = SelectedSize;
|
||||
var loc = CenterLocation - 0.5f * size;
|
||||
|
||||
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
|
||||
loc += new float2(si.Bounds[2], si.Bounds[3]);
|
||||
|
||||
if (useAltitude)
|
||||
{
|
||||
var unit = traits.GetOrDefault<Unit>();
|
||||
if (unit != null) loc -= new float2(0, unit.Altitude);
|
||||
}
|
||||
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public bool IsDead { get { return Health <= 0; } }
|
||||
public bool IsInWorld { get; set; }
|
||||
public bool RemoveOnDeath = true;
|
||||
|
||||
public DamageState GetDamageState()
|
||||
{
|
||||
if (Health <= 0)
|
||||
return DamageState.Dead;
|
||||
|
||||
if (Health < this.GetMaxHP() * Rules.General.ConditionRed)
|
||||
return DamageState.Quarter;
|
||||
|
||||
if (Health < this.GetMaxHP() * Rules.General.ConditionYellow)
|
||||
return DamageState.Half;
|
||||
|
||||
if (Health < this.GetMaxHP() * 0.75)
|
||||
return DamageState.ThreeQuarter;
|
||||
|
||||
return DamageState.Normal;
|
||||
}
|
||||
|
||||
public void InflictDamage(Actor attacker, int damage, WarheadInfo warhead)
|
||||
{
|
||||
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
|
||||
|
||||
var oldState = GetDamageState();
|
||||
|
||||
/* apply the damage modifiers, if we have any. */
|
||||
damage = (int)traits.WithInterface<IDamageModifier>().Aggregate(
|
||||
(float)damage, (a, t) => t.GetDamageModifier() * a);
|
||||
|
||||
Health -= damage;
|
||||
if (Health <= 0)
|
||||
{
|
||||
Health = 0;
|
||||
if (attacker.Owner != null)
|
||||
attacker.Owner.Kills++;
|
||||
|
||||
if (RemoveOnDeath)
|
||||
World.AddFrameEndTask(w => w.Remove(this));
|
||||
}
|
||||
|
||||
var maxHP = this.GetMaxHP();
|
||||
|
||||
if (Health > maxHP) Health = maxHP;
|
||||
|
||||
var newState = GetDamageState();
|
||||
|
||||
foreach (var nd in traits.WithInterface<INotifyDamage>())
|
||||
nd.Damaged(this, new AttackInfo
|
||||
{
|
||||
Attacker = attacker,
|
||||
Damage = damage,
|
||||
DamageState = newState,
|
||||
DamageStateChanged = newState != oldState,
|
||||
Warhead = warhead
|
||||
});
|
||||
}
|
||||
|
||||
public void QueueActivity( IActivity nextActivity )
|
||||
{
|
||||
if( currentActivity == null )
|
||||
{
|
||||
currentActivity = nextActivity;
|
||||
return;
|
||||
}
|
||||
var act = currentActivity;
|
||||
while( act.NextActivity != null )
|
||||
{
|
||||
act = act.NextActivity;
|
||||
}
|
||||
act.NextActivity = nextActivity;
|
||||
}
|
||||
|
||||
public void CancelActivity()
|
||||
{
|
||||
if( currentActivity != null )
|
||||
currentActivity.Cancel( this );
|
||||
}
|
||||
|
||||
// For pathdebug, et al
|
||||
public IActivity GetCurrentActivity()
|
||||
{
|
||||
return currentActivity;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int)ActorID;
|
||||
}
|
||||
|
||||
public override bool Equals( object obj )
|
||||
{
|
||||
var o = obj as Actor;
|
||||
return ( o != null && o.ActorID == ActorID );
|
||||
}
|
||||
}
|
||||
}
|
||||
77
OpenRA.Game/Chat.cs
Normal file
77
OpenRA.Game/Chat.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
class Chat
|
||||
{
|
||||
const int logLength = 10;
|
||||
|
||||
public List<Tuple<Color, string, string>> recentLines = new List<Tuple<Color, string, string>>();
|
||||
public string typing = "";
|
||||
public bool isChatting = true;
|
||||
|
||||
public void Toggle()
|
||||
{
|
||||
if( isChatting && typing.Length > 0 )
|
||||
Game.IssueOrder( Order.Chat( typing ) );
|
||||
|
||||
typing = "";
|
||||
if( Game.orderManager.GameStarted )
|
||||
isChatting ^= true;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
typing = "";
|
||||
isChatting = false;
|
||||
}
|
||||
|
||||
public void TypeChar(char c)
|
||||
{
|
||||
if (c == '\b')
|
||||
{
|
||||
if (typing.Length > 0)
|
||||
typing = typing.Remove(typing.Length - 1);
|
||||
}
|
||||
else
|
||||
typing += c;
|
||||
}
|
||||
|
||||
public void AddLine(Player p, string text)
|
||||
{
|
||||
AddLine(p.Color, p.PlayerName, text);
|
||||
}
|
||||
|
||||
public void AddLine(Color c, string from, string text)
|
||||
{
|
||||
Log.Write( "Chat: {0}: {1}", from, text );
|
||||
recentLines.Add(Tuple.New(c, from, text));
|
||||
var eva = Game.world.LocalPlayer.PlayerActor.Info.Traits.Get<EvaAlertsInfo>();
|
||||
Sound.Play(eva.ChatBeep);
|
||||
while (recentLines.Count > logLength) recentLines.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
1214
OpenRA.Game/Chrome.cs
Normal file
1214
OpenRA.Game/Chrome.cs
Normal file
File diff suppressed because it is too large
Load Diff
114
OpenRA.Game/Combat.cs
Normal file
114
OpenRA.Game/Combat.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
static class Combat /* some utility bits that are shared between various things */
|
||||
{
|
||||
public static void DoImpact(int2 loc, int2 visualLoc,
|
||||
WeaponInfo weapon, ProjectileInfo projectile, WarheadInfo warhead, Actor firedBy)
|
||||
{
|
||||
var world = firedBy.World;
|
||||
|
||||
var targetTile = ((1f / Game.CellSize) * loc.ToFloat2()).ToInt2();
|
||||
|
||||
var isWater = world.IsWater(targetTile);
|
||||
var hitWater = world.IsCellBuildable(targetTile, UnitMovementType.Float);
|
||||
|
||||
if (warhead.Explosion != 0)
|
||||
world.AddFrameEndTask(
|
||||
w => w.Add(new Explosion(w, visualLoc, warhead.Explosion, hitWater)));
|
||||
|
||||
var impactSound = warhead.ImpactSound;
|
||||
if (hitWater && warhead.WaterImpactSound != null)
|
||||
impactSound = warhead.WaterImpactSound;
|
||||
if (impactSound != null) Sound.Play(impactSound + ".aud");
|
||||
|
||||
if (!isWater) world.Map.AddSmudge(targetTile, warhead);
|
||||
if (warhead.Ore) world.Map.DestroyOre(targetTile.X, targetTile.Y);
|
||||
|
||||
var firepowerModifier = firedBy.traits
|
||||
.WithInterface<IFirepowerModifier>()
|
||||
.Select(a => a.GetFirepowerModifier())
|
||||
.Product();
|
||||
|
||||
var maxSpread = GetMaximumSpread(weapon, warhead, firepowerModifier);
|
||||
var hitActors = world.FindUnitsInCircle(loc, maxSpread);
|
||||
|
||||
foreach (var victim in hitActors)
|
||||
victim.InflictDamage(firedBy,
|
||||
(int)GetDamageToInflict(victim, loc, weapon, warhead, firepowerModifier), warhead);
|
||||
}
|
||||
|
||||
static float GetMaximumSpread(WeaponInfo weapon, WarheadInfo warhead, float modifier)
|
||||
{
|
||||
return (int)(warhead.Spread * Math.Log(Math.Abs(weapon.Damage * modifier), 2));
|
||||
}
|
||||
|
||||
static float GetDamageToInflict(Actor target, int2 loc, WeaponInfo weapon, WarheadInfo warhead, float modifier)
|
||||
{
|
||||
if (!WeaponValidForTarget(weapon, target))
|
||||
return 0f;
|
||||
|
||||
var distance = (target.CenterLocation - loc).Length*1/24f;
|
||||
var rawDamage = weapon.Damage * modifier * (float)Math.Exp(-distance / warhead.Spread);
|
||||
var multiplier = warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor);
|
||||
return rawDamage * multiplier;
|
||||
}
|
||||
|
||||
public static bool WeaponValidForTarget(WeaponInfo weapon, Actor target)
|
||||
{
|
||||
var projectile = Rules.ProjectileInfo[weapon.Projectile];
|
||||
var warhead = Rules.WarheadInfo[weapon.Warhead];
|
||||
var unit = target.traits.GetOrDefault<Unit>();
|
||||
|
||||
if (warhead.EffectivenessAgainst(target.Info.Traits.Get<OwnedActorInfo>().Armor) <= 0)
|
||||
return false;
|
||||
|
||||
if (target.traits.Contains<Submarine>())
|
||||
return projectile.ASW;
|
||||
|
||||
if (unit != null && unit.Altitude > 0)
|
||||
return projectile.AA;
|
||||
|
||||
if (projectile.UnderWater && !target.Info.Traits.Get<OwnedActorInfo>().WaterBound)
|
||||
return false;
|
||||
|
||||
return projectile.AG;
|
||||
}
|
||||
|
||||
public static bool HasAnyValidWeapons(Actor self, Actor target)
|
||||
{
|
||||
var info = self.Info.Traits.Get<AttackBaseInfo>();
|
||||
if (info.PrimaryWeapon != null &&
|
||||
WeaponValidForTarget(self.GetPrimaryWeapon(), target)) return true;
|
||||
if (info.SecondaryWeapon != null &&
|
||||
WeaponValidForTarget(self.GetSecondaryWeapon(), target)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
146
OpenRA.Game/Controller.cs
Normal file
146
OpenRA.Game/Controller.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Orders;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Controller : IHandleInput
|
||||
{
|
||||
public IOrderGenerator orderGenerator = new UnitOrderGenerator();
|
||||
public Selection selection = new Selection();
|
||||
|
||||
public void CancelInputMode() { orderGenerator = new UnitOrderGenerator(); }
|
||||
|
||||
public bool ToggleInputMode<T>() where T : IOrderGenerator, new()
|
||||
{
|
||||
if (orderGenerator is T)
|
||||
{
|
||||
CancelInputMode();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
orderGenerator = new T();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyOrders(World world, float2 xy, MouseInput mi)
|
||||
{
|
||||
if (orderGenerator == null) return;
|
||||
|
||||
var orders = orderGenerator.Order(world, xy.ToInt2(), mi).ToArray();
|
||||
Game.orderManager.IssueOrders( orders );
|
||||
|
||||
var voicedActor = orders.Select(o => o.Subject)
|
||||
.FirstOrDefault(a => a.Owner == world.LocalPlayer && a.traits.Contains<Unit>());
|
||||
|
||||
var isMove = orders.Any(o => o.OrderString == "Move");
|
||||
var isAttack = orders.Any( o => o.OrderString == "Attack" );
|
||||
|
||||
if (voicedActor != null)
|
||||
{
|
||||
|
||||
if(voicedActor.traits.GetOrDefault<IMovement>().CanEnterCell(xy.ToInt2()))
|
||||
Sound.PlayVoice(isAttack ? "Attack" : "Move", voicedActor);
|
||||
|
||||
if (isMove)
|
||||
world.Add(new Effects.MoveFlash(world, Game.CellSize * xy));
|
||||
}
|
||||
}
|
||||
|
||||
float2 dragStart, dragEnd;
|
||||
public bool HandleInput(World world, MouseInput mi)
|
||||
{
|
||||
var xy = Game.viewport.ViewToWorld(mi);
|
||||
|
||||
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Down)
|
||||
{
|
||||
if (!(orderGenerator is PlaceBuildingOrderGenerator))
|
||||
dragStart = dragEnd = xy;
|
||||
ApplyOrders(world, xy, mi);
|
||||
}
|
||||
|
||||
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Move)
|
||||
dragEnd = xy;
|
||||
|
||||
if (mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up)
|
||||
{
|
||||
if (orderGenerator is UnitOrderGenerator)
|
||||
{
|
||||
var newSelection = world.SelectActorsInBox(Game.CellSize * dragStart, Game.CellSize * xy);
|
||||
selection.Combine(world, newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
|
||||
}
|
||||
|
||||
dragStart = dragEnd = xy;
|
||||
}
|
||||
|
||||
if (mi.Button == MouseButton.None && mi.Event == MouseInputEvent.Move)
|
||||
dragStart = dragEnd = xy;
|
||||
|
||||
if (mi.Button == MouseButton.Right && mi.Event == MouseInputEvent.Down)
|
||||
ApplyOrders(world, xy, mi);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Pair<float2, float2>? SelectionBox
|
||||
{
|
||||
get
|
||||
{
|
||||
if (dragStart == dragEnd) return null;
|
||||
return Pair.New(Game.CellSize * dragStart, Game.CellSize * dragEnd);
|
||||
}
|
||||
}
|
||||
|
||||
public float2 MousePosition { get { return dragEnd; } }
|
||||
Modifiers modifiers;
|
||||
|
||||
public string ChooseCursor( World world )
|
||||
{
|
||||
int sync = world.SyncHash();
|
||||
|
||||
try
|
||||
{
|
||||
var mi = new MouseInput
|
||||
{
|
||||
Location = ( Game.CellSize * MousePosition - Game.viewport.Location ).ToInt2(),
|
||||
Button = MouseButton.Right,
|
||||
Modifiers = modifiers
|
||||
};
|
||||
|
||||
return orderGenerator.GetCursor( world, MousePosition.ToInt2(), mi );
|
||||
}
|
||||
finally
|
||||
{
|
||||
if( sync != world.SyncHash() )
|
||||
throw new InvalidOperationException( "Desync in Controller.ChooseCursor" );
|
||||
}
|
||||
}
|
||||
|
||||
public void SetModifiers(Modifiers mods) { modifiers = mods; }
|
||||
}
|
||||
}
|
||||
36
OpenRA.Game/Cursor.cs
Normal file
36
OpenRA.Game/Cursor.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Graphics;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public class Cursor
|
||||
{
|
||||
CursorSequence sequence;
|
||||
public Cursor(string cursor)
|
||||
{
|
||||
sequence = SequenceProvider.GetCursorSequence(cursor);
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame) { return sequence.GetSprite(frame); }
|
||||
public int2 GetHotspot() { return sequence.Hotspot; }
|
||||
}
|
||||
}
|
||||
133
OpenRA.Game/Effects/Bullet.cs
Executable file
133
OpenRA.Game/Effects/Bullet.cs
Executable file
@@ -0,0 +1,133 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
public class Bullet : IEffect
|
||||
{
|
||||
readonly Player Owner;
|
||||
readonly Actor FiredBy;
|
||||
readonly WeaponInfo Weapon;
|
||||
readonly ProjectileInfo Projectile;
|
||||
readonly WarheadInfo Warhead;
|
||||
readonly int2 Src;
|
||||
readonly int2 Dest;
|
||||
readonly int2 VisualDest;
|
||||
readonly int SrcAltitude;
|
||||
readonly int DestAltitude;
|
||||
|
||||
int t = 0;
|
||||
Animation anim;
|
||||
|
||||
const int BaseBulletSpeed = 100; /* pixels / 40ms frame */
|
||||
|
||||
public Bullet(string weapon, Player owner, Actor firedBy,
|
||||
int2 src, int2 dest, int srcAltitude, int destAltitude)
|
||||
: this(Rules.WeaponInfo[weapon], owner, firedBy, src, dest, srcAltitude, destAltitude) { }
|
||||
|
||||
/* src, dest are *pixel* coords */
|
||||
public Bullet(WeaponInfo weapon, Player owner, Actor firedBy,
|
||||
int2 src, int2 dest, int srcAltitude, int destAltitude)
|
||||
{
|
||||
Owner = owner;
|
||||
FiredBy = firedBy;
|
||||
Src = src;
|
||||
Dest = dest;
|
||||
SrcAltitude = srcAltitude;
|
||||
DestAltitude = destAltitude;
|
||||
VisualDest = Dest + new int2(
|
||||
firedBy.World.CosmeticRandom.Next(-10, 10),
|
||||
firedBy.World.CosmeticRandom.Next(-10, 10));
|
||||
Weapon = weapon;
|
||||
Projectile = Rules.ProjectileInfo[Weapon.Projectile];
|
||||
Warhead = Rules.WarheadInfo[Weapon.Warhead];
|
||||
|
||||
if (Projectile.Image != null && Projectile.Image != "none")
|
||||
{
|
||||
if (Projectile.Rotates)
|
||||
anim = new Animation(Projectile.Image, () => Traits.Util.GetFacing((dest - src).ToFloat2(), 0));
|
||||
else
|
||||
anim = new Animation(Projectile.Image);
|
||||
|
||||
anim.PlayRepeating("idle");
|
||||
}
|
||||
}
|
||||
|
||||
int TotalTime() { return (Dest - Src).Length * BaseBulletSpeed / Weapon.Speed; }
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
t += 40;
|
||||
|
||||
if (t > TotalTime()) /* remove finished bullets */
|
||||
{
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
Combat.DoImpact(Dest, VisualDest - new int2( 0, DestAltitude ),
|
||||
Weapon, Projectile, Warhead, FiredBy);
|
||||
}
|
||||
|
||||
if (Projectile.Trail != null)
|
||||
{
|
||||
var at = (float)t / TotalTime();
|
||||
var altitude = float2.Lerp(SrcAltitude, DestAltitude, at);
|
||||
var pos = float2.Lerp(Src.ToFloat2(), VisualDest.ToFloat2(), at)
|
||||
- 0.5f * anim.Image.size - new float2(0, altitude);
|
||||
|
||||
var highPos = (Projectile.High || Projectile.Arcing)
|
||||
? (pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at)))
|
||||
: pos;
|
||||
|
||||
world.AddFrameEndTask(w => w.Add(
|
||||
new Smoke(w, highPos.ToInt2(), Projectile.Trail)));
|
||||
}
|
||||
}
|
||||
|
||||
const float height = .1f;
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
if (anim != null)
|
||||
{
|
||||
var at = (float)t / TotalTime();
|
||||
|
||||
var altitude = float2.Lerp(SrcAltitude, DestAltitude, at);
|
||||
var pos = float2.Lerp( Src.ToFloat2(), VisualDest.ToFloat2(), at)
|
||||
- 0.5f * anim.Image.size - new float2( 0, altitude );
|
||||
|
||||
if (Projectile.High || Projectile.Arcing)
|
||||
{
|
||||
if (Projectile.Shadow)
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow");
|
||||
|
||||
var highPos = pos - new float2(0, (VisualDest - Src).Length * height * 4 * at * (1 - at));
|
||||
|
||||
yield return new Renderable(anim.Image, highPos - .5f * anim.Image.size, Owner.Palette);
|
||||
}
|
||||
else
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, Projectile.UnderWater ? "shadow" : Owner.Palette);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
OpenRA.Game/Effects/Corpse.cs
Executable file
50
OpenRA.Game/Effects/Corpse.cs
Executable file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class Corpse : IEffect
|
||||
{
|
||||
readonly Animation anim;
|
||||
readonly float2 pos;
|
||||
readonly Player owner;
|
||||
|
||||
public Corpse(Actor fromActor, int death)
|
||||
{
|
||||
anim = new Animation(fromActor.traits.GetOrDefault<RenderSimple>().GetImage(fromActor));
|
||||
anim.PlayThen("die{0}".F(death + 1),
|
||||
() => fromActor.World.AddFrameEndTask(w => w.Remove(this)));
|
||||
|
||||
pos = fromActor.CenterLocation;
|
||||
owner = fromActor.Owner;
|
||||
}
|
||||
|
||||
public void Tick( World world ) { anim.Tick(); }
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, owner.Palette);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
OpenRA.Game/Effects/DelayedAction.cs
Executable file
46
OpenRA.Game/Effects/DelayedAction.cs
Executable file
@@ -0,0 +1,46 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
public class DelayedAction : IEffect
|
||||
{
|
||||
Action a;
|
||||
int delay;
|
||||
|
||||
public DelayedAction(int delay, Action a)
|
||||
{
|
||||
this.a = a;
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if (--delay <= 0)
|
||||
world.AddFrameEndTask(w => { w.Remove(this); a(); });
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render() { yield break; }
|
||||
}
|
||||
}
|
||||
50
OpenRA.Game/Effects/Explosion.cs
Executable file
50
OpenRA.Game/Effects/Explosion.cs
Executable file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
public class Explosion : IEffect
|
||||
{
|
||||
Animation anim;
|
||||
int2 pos;
|
||||
|
||||
public Explosion( World world, int2 pixelPos, int style, bool isWater)
|
||||
{
|
||||
this.pos = pixelPos;
|
||||
var variantSuffix = isWater ? "w" : "";
|
||||
anim = new Animation("explosion");
|
||||
anim.PlayThen(style.ToString() + variantSuffix,
|
||||
() => world.AddFrameEndTask(w => w.Remove(this)));
|
||||
}
|
||||
|
||||
public void Tick( World world ) { anim.Tick(); }
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "effect");
|
||||
}
|
||||
|
||||
public Player Owner { get { return null; } }
|
||||
}
|
||||
}
|
||||
52
OpenRA.Game/Effects/FlashTarget.cs
Executable file
52
OpenRA.Game/Effects/FlashTarget.cs
Executable file
@@ -0,0 +1,52 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class FlashTarget : IEffect
|
||||
{
|
||||
Actor target;
|
||||
int remainingTicks = 4;
|
||||
|
||||
public FlashTarget(Actor target)
|
||||
{
|
||||
this.target = target;
|
||||
foreach (var e in target.World.Effects.OfType<FlashTarget>().Where(a => a.target == target).ToArray())
|
||||
target.World.Remove(e);
|
||||
}
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if (--remainingTicks == 0)
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
if (remainingTicks % 2 == 0)
|
||||
foreach (var r in target.Render())
|
||||
yield return r.WithPalette("highlight");
|
||||
}
|
||||
}
|
||||
}
|
||||
31
OpenRA.Game/Effects/IEffect.cs
Executable file
31
OpenRA.Game/Effects/IEffect.cs
Executable file
@@ -0,0 +1,31 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
public interface IEffect
|
||||
{
|
||||
void Tick( World world );
|
||||
IEnumerable<Renderable> Render();
|
||||
}
|
||||
}
|
||||
64
OpenRA.Game/Effects/LaserZap.cs
Normal file
64
OpenRA.Game/Effects/LaserZap.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class LaserZap : IEffect
|
||||
{
|
||||
readonly int2 from, to;
|
||||
readonly int radius;
|
||||
int timeUntilRemove = 10; // # of frames
|
||||
int totalTime = 10;
|
||||
Color color;
|
||||
|
||||
public LaserZap(int2 from, int2 to, int radius, Color color)
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.color = color;
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
public void Tick(World world)
|
||||
{
|
||||
if (timeUntilRemove <= 0)
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
--timeUntilRemove;
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
int alpha = (int)((1-(float)(totalTime-timeUntilRemove)/totalTime)*255);
|
||||
Color rc = Color.FromArgb(alpha,color);
|
||||
|
||||
float2 unit = 1.0f/(from - to).Length*(from - to).ToFloat2();
|
||||
float2 norm = new float2(-unit.Y, unit.X);
|
||||
|
||||
for (int i = -radius; i < radius; i++)
|
||||
Game.world.WorldRenderer.lineRenderer.DrawLine(from + i * norm, to + i * norm, rc, rc);
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
114
OpenRA.Game/Effects/Missile.cs
Executable file
114
OpenRA.Game/Effects/Missile.cs
Executable file
@@ -0,0 +1,114 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class Missile : IEffect
|
||||
{
|
||||
readonly Actor FiredBy;
|
||||
readonly WeaponInfo Weapon;
|
||||
readonly ProjectileInfo Projectile;
|
||||
readonly WarheadInfo Warhead;
|
||||
float2 Pos;
|
||||
readonly Actor Target;
|
||||
readonly Animation anim;
|
||||
int Facing;
|
||||
int t;
|
||||
int Altitude;
|
||||
|
||||
public Missile(WeaponInfo weapon, Player owner, Actor firedBy,
|
||||
int2 src, Actor target, int altitude, int facing)
|
||||
{
|
||||
Weapon = weapon;
|
||||
Projectile = Rules.ProjectileInfo[Weapon.Projectile];
|
||||
Warhead = Rules.WarheadInfo[Weapon.Warhead];
|
||||
FiredBy = firedBy;
|
||||
Target = target;
|
||||
Pos = src.ToFloat2();
|
||||
Altitude = altitude;
|
||||
Facing = facing;
|
||||
|
||||
if (Projectile.Image != null && Projectile.Image != "none")
|
||||
{
|
||||
if (Projectile.Rotates)
|
||||
anim = new Animation(Projectile.Image, () => Facing);
|
||||
else
|
||||
anim = new Animation(Projectile.Image);
|
||||
|
||||
anim.PlayRepeating("idle");
|
||||
}
|
||||
}
|
||||
|
||||
const int MissileCloseEnough = 7;
|
||||
const float Scale = .2f;
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
t += 40;
|
||||
|
||||
var targetUnit = Target.traits.GetOrDefault<Unit>();
|
||||
var targetAltitude = targetUnit != null ? targetUnit.Altitude : 0;
|
||||
Altitude += Math.Sign(targetAltitude - Altitude);
|
||||
|
||||
Traits.Util.TickFacing(ref Facing,
|
||||
Traits.Util.GetFacing(Target.CenterLocation - Pos, Facing),
|
||||
Projectile.ROT);
|
||||
|
||||
anim.Tick();
|
||||
|
||||
var dist = Target.CenterLocation - Pos;
|
||||
if (dist.LengthSquared < MissileCloseEnough * MissileCloseEnough || Target.IsDead)
|
||||
Explode(world);
|
||||
|
||||
var speed = Scale * Weapon.Speed * ((targetAltitude > 0 && Weapon.TurboBoost) ? 1.5f : 1f);
|
||||
|
||||
var angle = Facing / 128f * Math.PI;
|
||||
var move = speed * -float2.FromAngle((float)angle);
|
||||
Pos += move;
|
||||
|
||||
if (Projectile.Trail != null)
|
||||
world.AddFrameEndTask(w => w.Add(
|
||||
new Smoke(w, (Pos - 1.5f * move - new int2( 0, Altitude )).ToInt2(), Projectile.Trail)));
|
||||
|
||||
if (Projectile.RangeLimit != 0 && t > Projectile.RangeLimit * 40)
|
||||
Explode(world);
|
||||
}
|
||||
|
||||
void Explode(World world)
|
||||
{
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
|
||||
if (t > Projectile.Arm * 40) /* don't blow up in our launcher's face! */
|
||||
Combat.DoImpact(Pos.ToInt2(), Pos.ToInt2(), Weapon, Projectile, Warhead, FiredBy);
|
||||
return;
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, Pos - 0.5f * anim.Image.size - new float2(0, Altitude), "effect");
|
||||
}
|
||||
}
|
||||
}
|
||||
47
OpenRA.Game/Effects/MoveFlash.cs
Executable file
47
OpenRA.Game/Effects/MoveFlash.cs
Executable file
@@ -0,0 +1,47 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class MoveFlash : IEffect
|
||||
{
|
||||
Animation anim = new Animation("moveflsh");
|
||||
float2 pos;
|
||||
|
||||
public MoveFlash( World world, float2 pos )
|
||||
{
|
||||
this.pos = pos;
|
||||
anim.PlayThen( "idle",
|
||||
() => world.AddFrameEndTask(
|
||||
w => w.Remove( this ) ) );
|
||||
}
|
||||
|
||||
public void Tick( World world ) { anim.Tick(); }
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "shadow");
|
||||
}
|
||||
}
|
||||
}
|
||||
47
OpenRA.Game/Effects/RepairIndicator.cs
Executable file
47
OpenRA.Game/Effects/RepairIndicator.cs
Executable file
@@ -0,0 +1,47 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class RepairIndicator : IEffect
|
||||
{
|
||||
int framesLeft = (int)(Rules.General.RepairRate * 25 * 60 / 2);
|
||||
Actor a;
|
||||
Animation anim = new Animation("select");
|
||||
|
||||
public RepairIndicator(Actor a) { this.a = a; anim.PlayRepeating("repair"); }
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if (--framesLeft == 0 || a.IsDead)
|
||||
world.AddFrameEndTask(w => w.Remove(this));
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image,
|
||||
a.CenterLocation - .5f * anim.Image.size, "chrome");
|
||||
}
|
||||
}
|
||||
}
|
||||
50
OpenRA.Game/Effects/Smoke.cs
Executable file
50
OpenRA.Game/Effects/Smoke.cs
Executable file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class Smoke : IEffect
|
||||
{
|
||||
readonly int2 pos;
|
||||
readonly Animation anim;
|
||||
|
||||
public Smoke(World world, int2 pos, string trail)
|
||||
{
|
||||
this.pos = pos;
|
||||
anim = new Animation(trail);
|
||||
anim.PlayThen("idle",
|
||||
() => world.AddFrameEndTask(w => w.Remove(this)));
|
||||
}
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
anim.Tick();
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
yield return new Renderable(anim.Image, pos - .5f * anim.Image.size, "effect");
|
||||
}
|
||||
}
|
||||
}
|
||||
104
OpenRA.Game/Effects/TeslaZap.cs
Executable file
104
OpenRA.Game/Effects/TeslaZap.cs
Executable file
@@ -0,0 +1,104 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Effects
|
||||
{
|
||||
class TeslaZap : IEffect
|
||||
{
|
||||
readonly int2 from, to;
|
||||
readonly Sequence tesla;
|
||||
int timeUntilRemove = 2; // # of frames
|
||||
|
||||
public TeslaZap( int2 from, int2 to )
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.tesla = SequenceProvider.GetSequence( "litning", "bright" );
|
||||
}
|
||||
|
||||
public void Tick( World world )
|
||||
{
|
||||
if( timeUntilRemove <= 0 )
|
||||
world.AddFrameEndTask( w => w.Remove( this ) );
|
||||
--timeUntilRemove;
|
||||
}
|
||||
|
||||
public IEnumerable<Renderable> Render()
|
||||
{
|
||||
if( from.X < to.X )
|
||||
return DrawZap( from, to, tesla );
|
||||
else if( from.X > to.X || from.Y > to.Y )
|
||||
return DrawZap( to, from, tesla );
|
||||
else
|
||||
return DrawZap( from, to, tesla );
|
||||
}
|
||||
|
||||
static IEnumerable<Renderable> DrawZap( int2 from, int2 to, Sequence tesla )
|
||||
{
|
||||
int2 d = to - from;
|
||||
if( d.X < 8 )
|
||||
{
|
||||
var prev = new int2( 0, 0 );
|
||||
var y = d.Y;
|
||||
while( y >= prev.Y + 8 )
|
||||
{
|
||||
yield return new Renderable( tesla.GetSprite( 2 ), (float2)( from + prev - new int2( 0, 8 ) ), "effect");
|
||||
prev.Y += 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var prev = new int2( 0, 0 );
|
||||
for( int i = 1 ; i < d.X ; i += 8 )
|
||||
{
|
||||
var y = i * d.Y / d.X;
|
||||
if( y <= prev.Y - 8 )
|
||||
{
|
||||
yield return new Renderable(tesla.GetSprite(3), (float2)(from + prev - new int2(8, 16)), "effect");
|
||||
prev.Y -= 8;
|
||||
while( y <= prev.Y - 8 )
|
||||
{
|
||||
yield return new Renderable(tesla.GetSprite(2), (float2)(from + prev - new int2(0, 16)), "effect");
|
||||
prev.Y -= 8;
|
||||
}
|
||||
}
|
||||
else if( y >= prev.Y + 8 )
|
||||
{
|
||||
yield return new Renderable(tesla.GetSprite(0), (float2)(from + prev - new int2(8, 8)), "effect");
|
||||
prev.Y += 8;
|
||||
while( y >= prev.Y + 8 )
|
||||
{
|
||||
yield return new Renderable(tesla.GetSprite(2), (float2)(from + prev - new int2(0, 8)), "effect");
|
||||
prev.Y += 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
yield return new Renderable(tesla.GetSprite(1), (float2)(from + prev - new int2(8, 8)), "effect");
|
||||
|
||||
prev.X += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
90
OpenRA.Game/Exts.cs
Normal file
90
OpenRA.Game/Exts.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Exts
|
||||
{
|
||||
public static bool HasModifier(this Modifiers k, Modifiers mod)
|
||||
{
|
||||
return (k & mod) == mod;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> SymmetricDifference<T>(this IEnumerable<T> xs, IEnumerable<T> ys)
|
||||
{
|
||||
// this is probably a shockingly-slow way to do this, but it's concise.
|
||||
return xs.Except(ys).Concat(ys.Except(xs));
|
||||
}
|
||||
|
||||
public static float Product(this IEnumerable<float> xs)
|
||||
{
|
||||
return xs.Aggregate(1f, (a, x) => a * x);
|
||||
}
|
||||
|
||||
public static WeaponInfo GetPrimaryWeapon(this Actor self)
|
||||
{
|
||||
var info = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
|
||||
if (info == null) return null;
|
||||
|
||||
var weapon = info.PrimaryWeapon;
|
||||
if (weapon == null) return null;
|
||||
|
||||
return Rules.WeaponInfo[weapon];
|
||||
}
|
||||
|
||||
public static WeaponInfo GetSecondaryWeapon(this Actor self)
|
||||
{
|
||||
var info = self.Info.Traits.GetOrDefault<AttackBaseInfo>();
|
||||
if (info == null) return null;
|
||||
|
||||
var weapon = info.SecondaryWeapon;
|
||||
if (weapon == null) return null;
|
||||
|
||||
return Rules.WeaponInfo[weapon];
|
||||
}
|
||||
|
||||
public static int GetMaxHP(this Actor self)
|
||||
{
|
||||
var oai = self.Info.Traits.GetOrDefault<OwnedActorInfo>();
|
||||
if (oai == null) return 0;
|
||||
return oai.HP;
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k )
|
||||
where V : new()
|
||||
{
|
||||
return d.GetOrAdd( k, _ => new V() );
|
||||
}
|
||||
|
||||
public static V GetOrAdd<K, V>( this Dictionary<K, V> d, K k, Func<K, V> createFn )
|
||||
{
|
||||
V ret;
|
||||
if( !d.TryGetValue( k, out ret ) )
|
||||
d.Add( k, ret = createFn( k ) );
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
427
OpenRA.Game/Game.cs
Normal file
427
OpenRA.Game/Game.cs
Normal file
@@ -0,0 +1,427 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
using Timer = OpenRA.Support.Timer;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Game
|
||||
{
|
||||
public static readonly int CellSize = 24;
|
||||
|
||||
public static World world;
|
||||
internal static Viewport viewport;
|
||||
public static Controller controller;
|
||||
internal static Chrome chrome;
|
||||
public static UserSettings Settings;
|
||||
|
||||
internal static OrderManager orderManager;
|
||||
|
||||
public static bool skipMakeAnims = true;
|
||||
|
||||
internal static Renderer renderer;
|
||||
static int2 clientSize;
|
||||
static string mapName;
|
||||
internal static Session LobbyInfo = new Session();
|
||||
static bool changePending;
|
||||
|
||||
public static void LoadModPackages(Manifest manifest)
|
||||
{
|
||||
FileSystem.UnmountAll();
|
||||
Timer.Time("reset: {0}");
|
||||
|
||||
foreach (var dir in manifest.Folders) FileSystem.Mount(dir);
|
||||
foreach (var pkg in manifest.Packages) FileSystem.Mount(pkg);
|
||||
|
||||
Timer.Time("mount temporary packages: {0}");
|
||||
}
|
||||
|
||||
public static void ChangeMap(string mapName)
|
||||
{
|
||||
Timer.Time( "----ChangeMap" );
|
||||
|
||||
var manifest = new Manifest(LobbyInfo.GlobalSettings.Mods);
|
||||
Timer.Time( "manifest: {0}" );
|
||||
|
||||
Game.changePending = false;
|
||||
Game.mapName = mapName;
|
||||
SheetBuilder.Initialize(renderer);
|
||||
|
||||
LoadModPackages(manifest);
|
||||
|
||||
Rules.LoadRules(mapName, manifest);
|
||||
Timer.Time( "load rules: {0}" );
|
||||
|
||||
world = null; // trying to access the old world will NRE, rather than silently doing it wrong.
|
||||
|
||||
Player.ResetPlayerColorList();
|
||||
ChromeProvider.Initialize(manifest.Chrome);
|
||||
|
||||
world = new World();
|
||||
|
||||
Game.world.ActorAdded += a =>
|
||||
{
|
||||
if (a.Owner != null && a.Info.Traits.Contains<OwnedActorInfo>())
|
||||
a.Owner.Shroud.Explore(a);
|
||||
};
|
||||
Timer.Time( "world: {0}" );
|
||||
|
||||
SequenceProvider.Initialize(manifest.Sequences);
|
||||
viewport = new Viewport(clientSize, Game.world.Map.Offset, Game.world.Map.Offset + Game.world.Map.Size, renderer);
|
||||
Timer.Time( "ChromeProv, SeqProv, viewport: {0}" );
|
||||
|
||||
skipMakeAnims = true;
|
||||
foreach (var treeReference in Game.world.Map.Trees)
|
||||
world.CreateActor(treeReference.Image, new int2(treeReference.Location), null);
|
||||
Timer.Time( "trees: {0}" );
|
||||
|
||||
world.LoadMapActors(Rules.AllRules);
|
||||
skipMakeAnims = false;
|
||||
Timer.Time( "map actors: {0}" );
|
||||
|
||||
chrome = new Chrome(renderer);
|
||||
Timer.Time( "chrome: {0}" );
|
||||
|
||||
Timer.Time( "----end ChangeMap" );
|
||||
chat.AddLine(Color.White, "Debug", "Map change {0} -> {1}".F(Game.mapName, mapName));
|
||||
}
|
||||
|
||||
internal static void Initialize(string mapName, Renderer renderer, int2 clientSize, int localPlayer, Controller controller)
|
||||
{
|
||||
|
||||
Game.renderer = renderer;
|
||||
Game.clientSize = clientSize;
|
||||
|
||||
// todo
|
||||
Sound.Initialize();
|
||||
PerfHistory.items["render"].hasNormalTick = false;
|
||||
PerfHistory.items["batches"].hasNormalTick = false;
|
||||
PerfHistory.items["text"].hasNormalTick = false;
|
||||
Game.controller = controller;
|
||||
|
||||
ChangeMap(mapName);
|
||||
|
||||
if (Settings.Replay != "")
|
||||
throw new NotImplementedException();
|
||||
else
|
||||
{
|
||||
var connection = (string.IsNullOrEmpty(Settings.NetworkHost))
|
||||
? new EchoConnection()
|
||||
: new NetworkConnection( Settings.NetworkHost, Settings.NetworkPort );
|
||||
orderManager = new OrderManager(connection, "replay.rep");
|
||||
}
|
||||
}
|
||||
|
||||
static int lastTime = Environment.TickCount;
|
||||
|
||||
public static void ResetTimer()
|
||||
{
|
||||
lastTime = Environment.TickCount;
|
||||
}
|
||||
|
||||
public static int RenderFrame = 0;
|
||||
|
||||
internal static Chat chat = new Chat();
|
||||
|
||||
public static void Tick()
|
||||
{
|
||||
if (changePending && PackageDownloader.IsIdle())
|
||||
{
|
||||
ChangeMap(LobbyInfo.GlobalSettings.Map);
|
||||
return;
|
||||
}
|
||||
|
||||
int t = Environment.TickCount;
|
||||
int dt = t - lastTime;
|
||||
if (dt >= Settings.Timestep)
|
||||
{
|
||||
using (new PerfSample("tick_time"))
|
||||
{
|
||||
lastTime += Settings.Timestep;
|
||||
chrome.Tick( world );
|
||||
|
||||
orderManager.TickImmediate( world );
|
||||
|
||||
if (orderManager.IsReadyForNextFrame)
|
||||
{
|
||||
orderManager.Tick(world);
|
||||
controller.orderGenerator.Tick(world);
|
||||
controller.selection.Tick(world);
|
||||
|
||||
world.Tick();
|
||||
|
||||
PerfHistory.Tick();
|
||||
}
|
||||
else
|
||||
if (orderManager.FrameNumber == 0)
|
||||
lastTime = Environment.TickCount;
|
||||
}
|
||||
}
|
||||
|
||||
using (new PerfSample("render"))
|
||||
{
|
||||
++RenderFrame;
|
||||
viewport.DrawRegions( world );
|
||||
}
|
||||
|
||||
PerfHistory.items["render"].Tick();
|
||||
PerfHistory.items["batches"].Tick();
|
||||
PerfHistory.items["text"].Tick();
|
||||
}
|
||||
|
||||
public static void SyncLobbyInfo(string data)
|
||||
{
|
||||
var session = new Session();
|
||||
session.GlobalSettings.Mods = Settings.InitialMods;
|
||||
|
||||
var ys = MiniYaml.FromString(data);
|
||||
foreach (var y in ys)
|
||||
{
|
||||
if (y.Key == "GlobalSettings")
|
||||
{
|
||||
FieldLoader.Load(session.GlobalSettings, y.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
int index;
|
||||
if (!int.TryParse(y.Key, out index))
|
||||
continue; // not a player.
|
||||
|
||||
var client = new Session.Client();
|
||||
FieldLoader.Load(client, y.Value);
|
||||
session.Clients.Add(client);
|
||||
|
||||
world.players[index].SyncFromLobby(client);
|
||||
}
|
||||
|
||||
LobbyInfo = session;
|
||||
|
||||
if (Game.orderManager.Connection.ConnectionState == ConnectionState.Connected)
|
||||
world.SetLocalPlayer(Game.orderManager.Connection.LocalClientId);
|
||||
|
||||
if (Game.orderManager.FramesAhead != LobbyInfo.GlobalSettings.OrderLatency
|
||||
&& !Game.orderManager.GameStarted)
|
||||
{
|
||||
Game.orderManager.FramesAhead = LobbyInfo.GlobalSettings.OrderLatency;
|
||||
Game.chat.AddLine(Color.White, "Server",
|
||||
"Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency));
|
||||
}
|
||||
|
||||
if (PackageDownloader.SetPackageList(LobbyInfo.GlobalSettings.Packages)
|
||||
|| mapName != LobbyInfo.GlobalSettings.Map)
|
||||
changePending = true;
|
||||
}
|
||||
|
||||
public static void IssueOrder(Order o) { orderManager.IssueOrder(o); } /* avoid exposing the OM to mod code */
|
||||
|
||||
public static void StartGame()
|
||||
{
|
||||
Game.chat.Reset();
|
||||
|
||||
var taken = LobbyInfo.Clients.Where(c => c.SpawnPoint != 0)
|
||||
.Select(c => world.Map.SpawnPoints.ElementAt(c.SpawnPoint - 1)).ToList();
|
||||
|
||||
var available = world.Map.SpawnPoints.Except(taken).ToList();
|
||||
|
||||
foreach (var client in LobbyInfo.Clients)
|
||||
{
|
||||
var sp = (client.SpawnPoint == 0)
|
||||
? ChooseSpawnPoint(available, taken)
|
||||
: world.Map.SpawnPoints.ElementAt(client.SpawnPoint - 1);
|
||||
|
||||
foreach (var ssu in world.players[client.Index].PlayerActor
|
||||
.traits.WithInterface<IOnGameStart>())
|
||||
ssu.SpawnStartingUnits(world.players[client.Index], sp);
|
||||
}
|
||||
|
||||
Game.viewport.GoToStartLocation( Game.world.LocalPlayer );
|
||||
orderManager.StartGame();
|
||||
}
|
||||
|
||||
static int2 ChooseSpawnPoint(List<int2> available, List<int2> taken)
|
||||
{
|
||||
if (available.Count == 0)
|
||||
throw new InvalidOperationException("No free spawnpoint.");
|
||||
|
||||
var n = taken.Count == 0
|
||||
? world.SharedRandom.Next(available.Count)
|
||||
: available // pick the most distant spawnpoint from everyone else
|
||||
.Select((k,i) => Pair.New(k,i))
|
||||
.OrderByDescending(a => taken.Sum(t => (t - a.First).LengthSquared))
|
||||
.Select(a => a.Second)
|
||||
.First();
|
||||
|
||||
var sp = available[n];
|
||||
available.RemoveAt(n);
|
||||
taken.Add(sp);
|
||||
return sp;
|
||||
}
|
||||
|
||||
static int2 lastPos;
|
||||
public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Modifiers modifierKeys)
|
||||
{
|
||||
int sync = Game.world.SyncHash();
|
||||
|
||||
if (ev == MouseInputEvent.Down)
|
||||
lastPos = new int2(e.Location);
|
||||
|
||||
if (ev == MouseInputEvent.Move && (e.Button == MouseButtons.Middle || e.Button == (MouseButtons.Left | MouseButtons.Right)))
|
||||
{
|
||||
var p = new int2(e.Location);
|
||||
viewport.Scroll(lastPos - p);
|
||||
lastPos = p;
|
||||
}
|
||||
|
||||
Game.viewport.DispatchMouseInput( world,
|
||||
new MouseInput
|
||||
{
|
||||
Button = (MouseButton)(int)e.Button,
|
||||
Event = ev,
|
||||
Location = new int2(e.Location),
|
||||
Modifiers = modifierKeys,
|
||||
});
|
||||
|
||||
if( sync != Game.world.SyncHash() )
|
||||
throw new InvalidOperationException( "Desync in DispatchMouseInput" );
|
||||
}
|
||||
|
||||
public static void HandleKeyDown( KeyEventArgs e )
|
||||
{
|
||||
//int sync = Game.world.SyncHash();
|
||||
|
||||
|
||||
//if( sync != Game.world.SyncHash() )
|
||||
// throw new InvalidOperationException( "Desync in OnKeyDown" );
|
||||
}
|
||||
|
||||
public static bool IsHost
|
||||
{
|
||||
get { return orderManager.Connection.LocalClientId == 0; }
|
||||
}
|
||||
|
||||
public static void HandleKeyPress( KeyPressEventArgs e, Modifiers modifiers )
|
||||
{
|
||||
int sync = Game.world.SyncHash();
|
||||
|
||||
if( e.KeyChar == '\r' )
|
||||
Game.chat.Toggle();
|
||||
else if( Game.chat.isChatting )
|
||||
Game.chat.TypeChar( e.KeyChar );
|
||||
else
|
||||
if( e.KeyChar >= '0' && e.KeyChar <= '9' )
|
||||
Game.controller.selection.DoControlGroup( world,
|
||||
e.KeyChar - '0', modifiers );
|
||||
|
||||
if( sync != Game.world.SyncHash() )
|
||||
throw new InvalidOperationException( "Desync in OnKeyPress" );
|
||||
}
|
||||
|
||||
public static void HandleModifierKeys(Modifiers mods)
|
||||
{
|
||||
controller.SetModifiers(mods);
|
||||
}
|
||||
|
||||
static Size GetResolution(Settings settings)
|
||||
{
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
if (Game.Settings.Width > 0 && Game.Settings.Height > 0)
|
||||
{
|
||||
desktopResolution.Width = Game.Settings.Width;
|
||||
desktopResolution.Height = Game.Settings.Height;
|
||||
}
|
||||
return new Size(
|
||||
desktopResolution.Width,
|
||||
desktopResolution.Height);
|
||||
}
|
||||
|
||||
public static void PreInit(Settings settings)
|
||||
{
|
||||
while (!Directory.Exists("mods"))
|
||||
{
|
||||
var current = Directory.GetCurrentDirectory();
|
||||
if (Directory.GetDirectoryRoot(current) == current)
|
||||
throw new InvalidOperationException("Unable to load MIX files.");
|
||||
Directory.SetCurrentDirectory("..");
|
||||
}
|
||||
|
||||
|
||||
LoadUserSettings(settings);
|
||||
Game.LobbyInfo.GlobalSettings.Mods = Game.Settings.InitialMods;
|
||||
|
||||
// Load the default mod to access required files
|
||||
Game.LoadModPackages(new Manifest(Game.LobbyInfo.GlobalSettings.Mods));
|
||||
|
||||
UiOverlay.ShowUnitDebug = Game.Settings.UnitDebug;
|
||||
WorldRenderer.ShowUnitPaths = Game.Settings.PathDebug;
|
||||
Renderer.SheetSize = Game.Settings.SheetSize;
|
||||
|
||||
bool windowed = !Game.Settings.Fullscreen;
|
||||
var resolution = GetResolution(settings);
|
||||
renderer = new Renderer(resolution, windowed);
|
||||
resolution = renderer.Resolution;
|
||||
|
||||
var controller = new Controller(); /* a bit of insane input routing */
|
||||
|
||||
Game.Initialize(Game.Settings.Map, renderer, new int2(resolution), Game.Settings.Player, controller);
|
||||
|
||||
// ShowCursor(false);
|
||||
Game.ResetTimer();
|
||||
}
|
||||
|
||||
static void LoadUserSettings(Settings settings)
|
||||
{
|
||||
Game.Settings = new UserSettings();
|
||||
var settingsFile = settings.GetValue("settings", "settings.ini");
|
||||
FileSystem.Mount("./");
|
||||
if (FileSystem.Exists(settingsFile))
|
||||
FieldLoader.Load(Game.Settings,
|
||||
new IniFile(FileSystem.Open(settingsFile)).GetSection("Settings"));
|
||||
FileSystem.UnmountAll();
|
||||
}
|
||||
|
||||
static bool quit;
|
||||
internal static void Run()
|
||||
{
|
||||
while (!quit)
|
||||
{
|
||||
Game.Tick();
|
||||
Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Exit()
|
||||
{
|
||||
quit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
139
OpenRA.Game/GameRules/ActorInfo.cs
Normal file
139
OpenRA.Game/GameRules/ActorInfo.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class ActorInfo
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly string Category;
|
||||
public readonly TypeDictionary Traits = new TypeDictionary();
|
||||
|
||||
public ActorInfo( string name, MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
var mergedNode = MergeWithParent( node, allUnits ).Nodes;
|
||||
|
||||
Name = name;
|
||||
MiniYaml categoryNode;
|
||||
if( mergedNode.TryGetValue( "Category", out categoryNode ) )
|
||||
Category = categoryNode.Value;
|
||||
|
||||
foreach( var t in mergedNode )
|
||||
if( t.Key != "Inherits" && t.Key != "Category" )
|
||||
Traits.Add( LoadTraitInfo( t.Key, t.Value ) );
|
||||
}
|
||||
|
||||
static MiniYaml GetParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
MiniYaml inherits;
|
||||
node.Nodes.TryGetValue( "Inherits", out inherits );
|
||||
if( inherits == null || string.IsNullOrEmpty( inherits.Value ) )
|
||||
return null;
|
||||
|
||||
MiniYaml parent;
|
||||
allUnits.TryGetValue( inherits.Value, out parent );
|
||||
if( parent == null )
|
||||
return null;
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
static MiniYaml MergeWithParent( MiniYaml node, Dictionary<string, MiniYaml> allUnits )
|
||||
{
|
||||
var parent = GetParent( node, allUnits );
|
||||
if( parent != null )
|
||||
return MiniYaml.Merge( node, MergeWithParent( parent, allUnits ) );
|
||||
return node;
|
||||
}
|
||||
|
||||
static Pair<Assembly, string>[] ModAssemblies;
|
||||
public static void LoadModAssemblies(Manifest m)
|
||||
{
|
||||
var asms = new List<Pair<Assembly, string>>();
|
||||
|
||||
// all the core stuff is in this assembly
|
||||
asms.Add(Pair.New(typeof(ITraitInfo).Assembly, typeof(ITraitInfo).Namespace));
|
||||
|
||||
// add the mods
|
||||
foreach (var a in m.Assemblies)
|
||||
asms.Add(Pair.New(Assembly.LoadFile(Path.GetFullPath(a)), Path.GetFileNameWithoutExtension(a)));
|
||||
ModAssemblies = asms.ToArray();
|
||||
}
|
||||
|
||||
static ITraitInfo LoadTraitInfo(string traitName, MiniYaml my)
|
||||
{
|
||||
if (traitName.Contains('@'))
|
||||
traitName = traitName.Substring(0, traitName.IndexOf('@'));
|
||||
|
||||
foreach (var mod in ModAssemblies)
|
||||
{
|
||||
var fullTypeName = mod.Second + "." + traitName + "Info";
|
||||
var info = (ITraitInfo)mod.First.CreateInstance(fullTypeName);
|
||||
if (info == null) continue;
|
||||
FieldLoader.Load(info, my);
|
||||
return info;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Cannot locate trait: {0}".F(traitName));
|
||||
}
|
||||
|
||||
public IEnumerable<ITraitInfo> TraitsInConstructOrder()
|
||||
{
|
||||
var ret = new List<ITraitInfo>();
|
||||
var t = Traits.WithInterface<ITraitInfo>().ToList();
|
||||
int index = 0;
|
||||
while( t.Count != 0 )
|
||||
{
|
||||
if( index >= t.Count )
|
||||
throw new InvalidOperationException( "Trait prerequisites not satisfied (or prerequisite loop)" );
|
||||
|
||||
var prereqs = PrerequisitesOf( t[ index ] );
|
||||
if( prereqs.Count == 0 || prereqs.All( n => ret.Any( x => x.GetType().IsSubclassOf( n ) ) ) )
|
||||
{
|
||||
ret.Add( t[ index ] );
|
||||
t.RemoveAt( index );
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
++index;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static List<Type> PrerequisitesOf( ITraitInfo info )
|
||||
{
|
||||
return info
|
||||
.GetType()
|
||||
.GetInterfaces()
|
||||
.Where( t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof( ITraitPrerequisite<> ) )
|
||||
.Select( t => t.GetGenericArguments()[ 0 ] )
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
74
OpenRA.Game/GameRules/Footprint.cs
Normal file
74
OpenRA.Game/GameRules/Footprint.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
static class Footprint
|
||||
{
|
||||
public static IEnumerable<int2> Tiles( string name, BuildingInfo buildingInfo, int2 topLeft )
|
||||
{
|
||||
var dim = buildingInfo.Dimensions;
|
||||
|
||||
var footprint = buildingInfo.Footprint.Where(x => !char.IsWhiteSpace(x));
|
||||
if (buildingInfo.Bib)
|
||||
{
|
||||
dim.Y += 1;
|
||||
footprint = footprint.Concat(new char[dim.X]);
|
||||
}
|
||||
|
||||
return TilesWhere( name, dim, footprint.ToArray(), a => a != '_' ).Select( t => t + topLeft );
|
||||
}
|
||||
|
||||
public static IEnumerable<int2> Tiles(Actor a, Traits.Building building)
|
||||
{
|
||||
return Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location );
|
||||
}
|
||||
|
||||
public static IEnumerable<int2> UnpathableTiles( string name, BuildingInfo buildingInfo, int2 position )
|
||||
{
|
||||
var footprint = buildingInfo.Footprint.Where( x => !char.IsWhiteSpace( x ) ).ToArray();
|
||||
foreach( var tile in TilesWhere( name, buildingInfo.Dimensions, footprint, a => a == 'x' ) )
|
||||
yield return tile + position;
|
||||
}
|
||||
|
||||
static IEnumerable<int2> TilesWhere( string name, int2 dim, char[] footprint, Func<char, bool> cond )
|
||||
{
|
||||
if( footprint.Length != dim.X * dim.Y )
|
||||
throw new InvalidOperationException( "Invalid footprint for " + name );
|
||||
int index = 0;
|
||||
|
||||
for( int y = 0 ; y < dim.Y ; y++ )
|
||||
for( int x = 0 ; x < dim.X ; x++ )
|
||||
if( cond( footprint[ index++ ] ) )
|
||||
yield return new int2( x, y );
|
||||
}
|
||||
|
||||
public static int2 AdjustForBuildingSize( BuildingInfo buildingInfo )
|
||||
{
|
||||
var dim = buildingInfo.Dimensions;
|
||||
return new int2( dim.X / 2, dim.Y > 1 ? ( dim.Y + 1 ) / 2 : 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
112
OpenRA.Game/GameRules/GeneralInfo.cs
Normal file
112
OpenRA.Game/GameRules/GeneralInfo.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class GeneralInfo
|
||||
{
|
||||
/* Special Weapons */
|
||||
public readonly float GapRegenInterval =0;
|
||||
public readonly int BadgerBombCount = 1;
|
||||
|
||||
/* Chrono Side Effects */
|
||||
public readonly float QuakeChance = 0;
|
||||
public readonly float QuakeDamage = 0; /* percent */
|
||||
public readonly float VortexChance = 0;
|
||||
public readonly int VortexDamage = 0;
|
||||
public readonly int VortexRange = 0;
|
||||
public readonly int VortexSpeed = 0;
|
||||
|
||||
/* Repair & Refit */
|
||||
public readonly float RefundPercent = 0;
|
||||
public readonly float ReloadRate = 0;
|
||||
public readonly float RepairPercent = 0;
|
||||
public readonly float RepairRate = 0;
|
||||
public readonly int RepairStep = 0;
|
||||
public readonly float URepairPercent = 0;
|
||||
public readonly int URepairStep = 0;
|
||||
|
||||
/* Combat & Damage */
|
||||
public readonly float TurboBoost = 1.5f;
|
||||
public readonly float BallisticScatter = 0;
|
||||
public readonly float C4Delay = 0;
|
||||
public readonly float ExpSpread = 0;
|
||||
public readonly int FireSupress = 0;
|
||||
public readonly float HomingScatter = 0;
|
||||
public readonly int MaxDamage = 0;
|
||||
public readonly int MinDamage = 0;
|
||||
public readonly bool OreExplosive = false;
|
||||
public readonly bool PlayerAutoCrush = false;
|
||||
public readonly bool PlayerReturnFire = false;
|
||||
public readonly bool PlayerScatter = false;
|
||||
public readonly bool TreeTargeting = false;
|
||||
public readonly int Incoming = 0;
|
||||
|
||||
/* Income & Production */
|
||||
public readonly float BuildSpeed = 0;
|
||||
public readonly float BuildupTime = 0;
|
||||
public readonly int GemValue = 0;
|
||||
public readonly int GoldValue = 0;
|
||||
public readonly float OreTruckRate = 0;
|
||||
public readonly bool SeparateAircraft = true;
|
||||
public readonly float SurvivorRate = 0;
|
||||
|
||||
/* Audo/Visual Map Controls */
|
||||
public readonly bool AllyReveal = true;
|
||||
public readonly float ConditionRed = 0;
|
||||
public readonly float ConditionYellow = 0;
|
||||
public readonly int DropZoneRadius = 0;
|
||||
public readonly bool EnemyHealth = true;
|
||||
public readonly int Gravity = 0;
|
||||
public readonly float IdleActionFrequency = 0;
|
||||
public readonly float MessageDelay = 0;
|
||||
public readonly float MovieTime = 0;
|
||||
public readonly bool NamedCivilians = false;
|
||||
public readonly float SavourDelay = 0;
|
||||
public readonly int ShroudRate = 0;
|
||||
public readonly int SpeakDelay = 0;
|
||||
public readonly int TimerWarning = 0;
|
||||
public readonly bool FlashLowPower = false;
|
||||
|
||||
/* Computer & Movement Controls */
|
||||
public readonly bool CurleyShuffle = false;
|
||||
public readonly float BaseBias = 0;
|
||||
public readonly float BaseDefenseDelay = 0;
|
||||
public readonly float CloseEnough = 0;
|
||||
public readonly int DamageDelay = 0;
|
||||
public readonly int GameSpeeBias = 0;
|
||||
public readonly int LZScanRadius = 0;
|
||||
public readonly bool MineAware = false;
|
||||
public readonly float Stray = 0;
|
||||
public readonly float SubmergeDelay = 0;
|
||||
public readonly float SuspendDelay = 0;
|
||||
public readonly int SuspendPriority = 0;
|
||||
public readonly float TeamDelay = 0;
|
||||
|
||||
/* Misc */
|
||||
[Obsolete]
|
||||
public readonly bool FineDiffControl = false;
|
||||
|
||||
/* OpenRA-specific */
|
||||
public readonly int LowPowerSlowdown = 3; /* build time multiplier */
|
||||
}
|
||||
}
|
||||
51
OpenRA.Game/GameRules/InfoLoader.cs
Normal file
51
OpenRA.Game/GameRules/InfoLoader.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class InfoLoader<T> : IEnumerable<KeyValuePair<string, T>>
|
||||
{
|
||||
readonly Dictionary<string, T> infos = new Dictionary<string, T>();
|
||||
|
||||
public InfoLoader(params Pair<string, Func<string,T>>[] srcs)
|
||||
{
|
||||
foreach (var src in srcs)
|
||||
foreach (var name in Rules.Categories[src.First])
|
||||
{
|
||||
var t = src.Second(name);
|
||||
FieldLoader.Load(t, Rules.AllRules.GetSection(name));
|
||||
infos[name] = t;
|
||||
}
|
||||
}
|
||||
|
||||
public T this[string name]
|
||||
{
|
||||
get { return infos[name.ToLowerInvariant()]; }
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, T>> GetEnumerator() { return infos.GetEnumerator(); }
|
||||
IEnumerator IEnumerable.GetEnumerator() { return infos.GetEnumerator(); }
|
||||
}
|
||||
}
|
||||
45
OpenRA.Game/GameRules/ProjectileInfo.cs
Normal file
45
OpenRA.Game/GameRules/ProjectileInfo.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class ProjectileInfo
|
||||
{
|
||||
public readonly bool AA = false;
|
||||
public readonly bool AG = true;
|
||||
public readonly bool ASW = false;
|
||||
public readonly bool Arcing = false;
|
||||
public readonly int Arm = 0;
|
||||
public readonly bool Degenerates = false;
|
||||
public readonly bool High = false;
|
||||
public readonly string Image = null;
|
||||
public readonly bool Inaccurate = false;
|
||||
public readonly bool Parachuted = false;
|
||||
public readonly bool Proximity = false;
|
||||
public readonly int ROT = 0;
|
||||
public readonly bool Rotates = false;
|
||||
public readonly bool Shadow = true;
|
||||
public readonly bool UnderWater = false;
|
||||
public readonly int RangeLimit = 0;
|
||||
|
||||
// OpenRA-specific:
|
||||
public readonly string Trail = null;
|
||||
}
|
||||
}
|
||||
82
OpenRA.Game/GameRules/Rules.cs
Executable file
82
OpenRA.Game/GameRules/Rules.cs
Executable file
@@ -0,0 +1,82 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.GameRules;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
public static class Rules
|
||||
{
|
||||
public static IniFile AllRules;
|
||||
public static Dictionary<string, List<string>> Categories = new Dictionary<string, List<string>>();
|
||||
public static InfoLoader<WeaponInfo> WeaponInfo;
|
||||
public static InfoLoader<WarheadInfo> WarheadInfo;
|
||||
public static InfoLoader<ProjectileInfo> ProjectileInfo;
|
||||
public static InfoLoader<VoiceInfo> VoiceInfo;
|
||||
public static GeneralInfo General;
|
||||
public static TechTree TechTree;
|
||||
|
||||
public static Dictionary<string, ActorInfo> Info;
|
||||
|
||||
public static void LoadRules(string map, Manifest m)
|
||||
{
|
||||
var legacyRules = m.LegacyRules.Reverse().ToList();
|
||||
legacyRules.Insert(0, map);
|
||||
AllRules = new IniFile(legacyRules.Select(a => FileSystem.Open(a)).ToArray());
|
||||
|
||||
General = new GeneralInfo();
|
||||
FieldLoader.Load(General, AllRules.GetSection("General"));
|
||||
|
||||
LoadCategories(
|
||||
"Weapon",
|
||||
"Warhead",
|
||||
"Projectile",
|
||||
"Voice");
|
||||
|
||||
WeaponInfo = new InfoLoader<WeaponInfo>(
|
||||
Pair.New<string, Func<string, WeaponInfo>>("Weapon", _ => new WeaponInfo()));
|
||||
WarheadInfo = new InfoLoader<WarheadInfo>(
|
||||
Pair.New<string, Func<string, WarheadInfo>>("Warhead", _ => new WarheadInfo()));
|
||||
ProjectileInfo = new InfoLoader<ProjectileInfo>(
|
||||
Pair.New<string, Func<string, ProjectileInfo>>("Projectile", _ => new ProjectileInfo()));
|
||||
VoiceInfo = new InfoLoader<VoiceInfo>(
|
||||
Pair.New<string, Func<string, VoiceInfo>>("Voice", _ => new VoiceInfo()));
|
||||
|
||||
var yamlRules = m.Rules.Reverse().Select(a => MiniYaml.FromFile(a)).Aggregate(MiniYaml.Merge);
|
||||
|
||||
ActorInfo.LoadModAssemblies(m);
|
||||
Info = new Dictionary<string, ActorInfo>();
|
||||
foreach( var kv in yamlRules )
|
||||
Info.Add(kv.Key.ToLowerInvariant(), new ActorInfo(kv.Key.ToLowerInvariant(), kv.Value, yamlRules));
|
||||
|
||||
TechTree = new TechTree();
|
||||
}
|
||||
|
||||
static void LoadCategories(params string[] types)
|
||||
{
|
||||
foreach (var t in types)
|
||||
Categories[t] = AllRules.GetSection(t + "Types").Select(x => x.Key.ToLowerInvariant()).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
100
OpenRA.Game/GameRules/TechTree.cs
Executable file
100
OpenRA.Game/GameRules/TechTree.cs
Executable file
@@ -0,0 +1,100 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class TechTree
|
||||
{
|
||||
readonly Cache<string, List<ActorInfo>> producesIndex = new Cache<string, List<ActorInfo>>(x => new List<ActorInfo>());
|
||||
|
||||
public TechTree()
|
||||
{
|
||||
foreach( var info in Rules.Info.Values )
|
||||
{
|
||||
var pi = info.Traits.GetOrDefault<ProductionInfo>();
|
||||
if (pi != null)
|
||||
foreach( var p in pi.Produces )
|
||||
producesIndex[ p ].Add( info );
|
||||
}
|
||||
}
|
||||
|
||||
public Cache<string, List<Actor>> GatherBuildings( Player player )
|
||||
{
|
||||
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
|
||||
foreach( var b in player.World.Queries.OwnedBy[player].Where( x=>x.Info.Traits.Contains<BuildingInfo>() ) )
|
||||
{
|
||||
ret[ b.Info.Name ].Add( b );
|
||||
var buildable = b.Info.Traits.GetOrDefault<BuildableInfo>();
|
||||
if( buildable != null )
|
||||
foreach( var alt in buildable.AlternateName )
|
||||
ret[ alt ].Add( b );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool CanBuild( ActorInfo info, Player player, Cache<string, List<Actor>> playerBuildings )
|
||||
{
|
||||
var bi = info.Traits.GetOrDefault<BuildableInfo>();
|
||||
if( bi == null ) return false;
|
||||
|
||||
if( !bi.Owner.Contains( player.Country.Race ) )
|
||||
return false;
|
||||
|
||||
foreach( var p in bi.Prerequisites )
|
||||
if( playerBuildings[ p ].Count == 0 )
|
||||
return false;
|
||||
|
||||
if( producesIndex[ info.Category ].All( x => playerBuildings[ x.Name ].Count == 0 ) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
|
||||
{
|
||||
var playerBuildings = GatherBuildings( player );
|
||||
foreach( var unit in AllBuildables( player, categories ) )
|
||||
if( CanBuild( unit, player, playerBuildings ) )
|
||||
yield return unit.Name;
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> AllBuildables(Player player, params string[] categories)
|
||||
{
|
||||
return Rules.Info.Values
|
||||
.Where( x => x.Name[ 0 ] != '^' )
|
||||
.Where( x => categories.Contains( x.Category ) )
|
||||
.Where( x => x.Traits.Contains<BuildableInfo>() );
|
||||
}
|
||||
|
||||
public IEnumerable<ActorInfo> UnitBuiltAt( ActorInfo info )
|
||||
{
|
||||
var builtAt = info.Traits.Get<BuildableInfo>().BuiltAt;
|
||||
if( builtAt.Length != 0 )
|
||||
return builtAt.Select( x => Rules.Info[ x.ToLowerInvariant() ] );
|
||||
else
|
||||
return producesIndex[ info.Category ];
|
||||
}
|
||||
}
|
||||
}
|
||||
53
OpenRA.Game/GameRules/UserSettings.cs
Normal file
53
OpenRA.Game/GameRules/UserSettings.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class UserSettings
|
||||
{
|
||||
// Debug settings
|
||||
public readonly bool UnitDebug = false;
|
||||
public readonly bool PathDebug = false;
|
||||
public readonly bool PerfGraph = true;
|
||||
|
||||
// Window settings
|
||||
public readonly int Width = 0;
|
||||
public readonly int Height = 0;
|
||||
public readonly bool Fullscreen = false;
|
||||
|
||||
// Internal game settings
|
||||
public readonly int Timestep = 40;
|
||||
public readonly int SheetSize = 512;
|
||||
|
||||
// External game settings
|
||||
public readonly string NetworkHost = "";
|
||||
public readonly int NetworkPort = 0;
|
||||
public readonly string Map = "scm12ea.ini";
|
||||
public readonly int Player = 1;
|
||||
public readonly string Replay = "";
|
||||
public readonly string PlayerName = "";
|
||||
public readonly string[] InitialMods = { "ra" };
|
||||
|
||||
// Gameplay options
|
||||
// TODO: These need to die
|
||||
public readonly bool RepairRequiresConyard = true;
|
||||
public readonly bool PowerDownBuildings = true;
|
||||
}
|
||||
}
|
||||
74
OpenRA.Game/GameRules/VoiceInfo.cs
Normal file
74
OpenRA.Game/GameRules/VoiceInfo.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class VoiceInfo
|
||||
{
|
||||
public readonly string[] SovietVariants = { ".aud" };
|
||||
public readonly string[] AlliedVariants = { ".aud" };
|
||||
public readonly string[] Select = { };
|
||||
public readonly string[] Move = { };
|
||||
public readonly string[] Attack = null;
|
||||
public readonly string[] Die = { };
|
||||
|
||||
public readonly Lazy<Dictionary<string, VoicePool>> Pools;
|
||||
|
||||
public VoiceInfo()
|
||||
{
|
||||
Pools = Lazy.New(() =>
|
||||
new Dictionary<string, VoicePool>
|
||||
{
|
||||
{ "Select", new VoicePool(Select) },
|
||||
{ "Move", new VoicePool(Move) },
|
||||
{ "Attack", new VoicePool( Attack ?? Move ) },
|
||||
{ "Die", new VoicePool(Die) },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class VoicePool
|
||||
{
|
||||
readonly string[] clips;
|
||||
readonly List<string> liveclips = new List<string>();
|
||||
|
||||
public VoicePool(params string[] clips)
|
||||
{
|
||||
this.clips = clips;
|
||||
}
|
||||
|
||||
public string GetNext()
|
||||
{
|
||||
if (liveclips.Count == 0)
|
||||
liveclips.AddRange(clips);
|
||||
|
||||
if (liveclips.Count == 0)
|
||||
return null; /* avoid crashing if there's no clips at all */
|
||||
|
||||
var i = Game.world.CosmeticRandom.Next(liveclips.Count);
|
||||
var s = liveclips[i];
|
||||
liveclips.RemoveAt(i);
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
OpenRA.Game/GameRules/WarheadInfo.cs
Normal file
46
OpenRA.Game/GameRules/WarheadInfo.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class WarheadInfo
|
||||
{
|
||||
public readonly int Spread = 1;
|
||||
public readonly float[] Verses = { 1, 1, 1, 1, 1 };
|
||||
public readonly bool Wall = false;
|
||||
public readonly bool Wood = false;
|
||||
public readonly bool Ore = false;
|
||||
public readonly int Explosion = 0;
|
||||
public readonly int InfDeath = 0;
|
||||
public readonly string ImpactSound = null;
|
||||
public readonly string WaterImpactSound = null;
|
||||
|
||||
public float EffectivenessAgainst(ArmorType at) { return Verses[ (int)at ]; }
|
||||
}
|
||||
|
||||
public enum ArmorType
|
||||
{
|
||||
none = 0,
|
||||
wood = 1,
|
||||
light = 2,
|
||||
heavy = 3,
|
||||
concrete = 4,
|
||||
}
|
||||
}
|
||||
41
OpenRA.Game/GameRules/WeaponInfo.cs
Executable file
41
OpenRA.Game/GameRules/WeaponInfo.cs
Executable file
@@ -0,0 +1,41 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
public class WeaponInfo
|
||||
{
|
||||
public readonly int Burst = 1;
|
||||
public readonly bool Charges = false;
|
||||
public readonly int Damage = 0;
|
||||
public readonly string Projectile = "Invisible";
|
||||
public readonly int ROF = 1; // in 1/15 second units.
|
||||
public readonly float Range = 0;
|
||||
public readonly string Report = null;
|
||||
public readonly int Speed = -1;
|
||||
public readonly bool TurboBoost = false;
|
||||
public readonly string Warhead = null;
|
||||
|
||||
public readonly bool RenderAsTesla = false;
|
||||
public readonly bool RenderAsLaser = false;
|
||||
public readonly bool UsePlayerColor = true;
|
||||
public readonly int BeamRadius = 1;
|
||||
}
|
||||
}
|
||||
150
OpenRA.Game/Graphics/Animation.cs
Normal file
150
OpenRA.Game/Graphics/Animation.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Animation
|
||||
{
|
||||
string name;
|
||||
public Sequence CurrentSequence { get; private set; }
|
||||
int frame = 0;
|
||||
bool backwards = false;
|
||||
bool tickAlways;
|
||||
|
||||
Func<int> facingFunc;
|
||||
|
||||
public string Name { get { return name; } }
|
||||
|
||||
public Animation( string name )
|
||||
: this( name, () => 0 )
|
||||
{
|
||||
}
|
||||
|
||||
public Animation( string name, Func<int> facingFunc )
|
||||
{
|
||||
this.name = name.ToLowerInvariant();
|
||||
this.tickFunc = () => { };
|
||||
this.facingFunc = facingFunc;
|
||||
}
|
||||
|
||||
public Sprite Image
|
||||
{
|
||||
get
|
||||
{
|
||||
return backwards
|
||||
? CurrentSequence.GetSprite(CurrentSequence.End - frame - 1, facingFunc())
|
||||
: CurrentSequence.GetSprite(frame, facingFunc());
|
||||
}
|
||||
}
|
||||
|
||||
public void Play( string sequenceName )
|
||||
{
|
||||
PlayThen(sequenceName, () => { });
|
||||
}
|
||||
|
||||
public void PlayRepeating( string sequenceName )
|
||||
{
|
||||
PlayThen( sequenceName, () => PlayRepeating( CurrentSequence.Name ) );
|
||||
}
|
||||
|
||||
public void ReplaceAnim(string sequenceName)
|
||||
{
|
||||
CurrentSequence = SequenceProvider.GetSequence(name, sequenceName);
|
||||
frame %= CurrentSequence.Length;
|
||||
}
|
||||
|
||||
public void PlayThen( string sequenceName, Action after )
|
||||
{
|
||||
after = after ?? ( () => { } );
|
||||
backwards = false;
|
||||
tickAlways = false;
|
||||
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
|
||||
frame = 0;
|
||||
tickFunc = () =>
|
||||
{
|
||||
++frame;
|
||||
if( frame >= CurrentSequence.Length )
|
||||
{
|
||||
frame = CurrentSequence.Length - 1;
|
||||
tickFunc = () => { };
|
||||
after();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void PlayBackwardsThen(string sequenceName, Action after)
|
||||
{
|
||||
PlayThen(sequenceName, after);
|
||||
backwards = true;
|
||||
}
|
||||
|
||||
public void PlayFetchIndex( string sequenceName, Func<int> func )
|
||||
{
|
||||
backwards = false;
|
||||
tickAlways = true;
|
||||
CurrentSequence = SequenceProvider.GetSequence( name, sequenceName );
|
||||
frame = func();
|
||||
tickFunc = () => frame = func();
|
||||
}
|
||||
|
||||
int timeUntilNextFrame;
|
||||
Action tickFunc;
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
Tick( 40 ); // tick one frame
|
||||
}
|
||||
|
||||
public bool HasSequence(string seq) { return SequenceProvider.HasSequence( name, seq ); }
|
||||
|
||||
public void Tick( int t )
|
||||
{
|
||||
if( tickAlways )
|
||||
tickFunc();
|
||||
else
|
||||
{
|
||||
timeUntilNextFrame -= t;
|
||||
while( timeUntilNextFrame <= 0 )
|
||||
{
|
||||
tickFunc();
|
||||
timeUntilNextFrame += 40; // 25 fps == 40 ms
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeImage(string newImage)
|
||||
{
|
||||
newImage = newImage.ToLowerInvariant();
|
||||
|
||||
if (name != newImage)
|
||||
{
|
||||
name = newImage.ToLowerInvariant();
|
||||
ReplaceAnim(CurrentSequence.Name);
|
||||
}
|
||||
}
|
||||
|
||||
public Sequence GetSequence( string sequenceName )
|
||||
{
|
||||
return SequenceProvider.GetSequence( name, sequenceName );
|
||||
}
|
||||
}
|
||||
}
|
||||
97
OpenRA.Game/Graphics/ChromeProvider.cs
Normal file
97
OpenRA.Game/Graphics/ChromeProvider.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class ChromeProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, MappedImage>> collections;
|
||||
static Dictionary<string, Sheet> cachedSheets;
|
||||
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
|
||||
|
||||
public static void Initialize(params string[] chromeFiles)
|
||||
{
|
||||
collections = new Dictionary<string, Dictionary<string, MappedImage>>();
|
||||
cachedSheets = new Dictionary<string, Sheet>();
|
||||
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
|
||||
|
||||
foreach (var f in chromeFiles)
|
||||
LoadChromeSource(f);
|
||||
}
|
||||
|
||||
static void LoadChromeSource(string filename)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
foreach (XmlElement eCollection in document.SelectNodes("/chrome/collection"))
|
||||
LoadChromeForCollection(eCollection);
|
||||
}
|
||||
|
||||
static void LoadChromeForCollection(XmlElement eCollection)
|
||||
{
|
||||
string elementName = eCollection.GetAttribute("name");
|
||||
string defaultSrc = (eCollection.HasAttribute("src") ? eCollection.GetAttribute("src") : null);
|
||||
|
||||
var images = eCollection.SelectNodes("./image").OfType<XmlElement>()
|
||||
.Select(e => new MappedImage(defaultSrc, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
collections.Add(elementName, images);
|
||||
}
|
||||
|
||||
public static Sprite GetImage(Renderer renderer, string collection, string image)
|
||||
{
|
||||
// Cached sprite
|
||||
if (cachedSprites.ContainsKey(collection) && cachedSprites[collection].ContainsKey(image))
|
||||
return cachedSprites[collection][image];
|
||||
|
||||
MappedImage mi;
|
||||
try { mi = collections[collection][image]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Collection `{0}` does not have an image `{1}`".F(collection, image));
|
||||
}
|
||||
|
||||
// Cached sheet
|
||||
Sheet sheet;
|
||||
if (cachedSheets.ContainsKey(mi.Src))
|
||||
sheet = cachedSheets[mi.Src];
|
||||
else
|
||||
{
|
||||
sheet = new Sheet(renderer, mi.Src);
|
||||
cachedSheets.Add(mi.Src, sheet);
|
||||
}
|
||||
|
||||
// Cache the sprite
|
||||
if (!cachedSprites.ContainsKey(collection))
|
||||
cachedSprites.Add(collection, new Dictionary<string, Sprite>());
|
||||
cachedSprites[collection].Add(image, mi.GetImage(renderer, sheet));
|
||||
|
||||
return cachedSprites[collection][image];
|
||||
}
|
||||
}
|
||||
}
|
||||
61
OpenRA.Game/Graphics/CursorSequence.cs
Normal file
61
OpenRA.Game/Graphics/CursorSequence.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class CursorSequence
|
||||
{
|
||||
readonly int start, length;
|
||||
|
||||
public int Start { get { return start; } }
|
||||
public int End { get { return start + length; } }
|
||||
public int Length { get { return length; } }
|
||||
|
||||
public readonly int2 Hotspot;
|
||||
|
||||
Sprite[] sprites;
|
||||
|
||||
public CursorSequence(string cursorSrc, XmlElement e)
|
||||
{
|
||||
sprites = CursorSheetBuilder.LoadAllSprites(cursorSrc);
|
||||
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - start;
|
||||
else
|
||||
length = 1;
|
||||
|
||||
int.TryParse( e.GetAttribute("x"), out Hotspot.X );
|
||||
int.TryParse( e.GetAttribute("y"), out Hotspot.Y );
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame)
|
||||
{
|
||||
return sprites[(frame % length) + start];
|
||||
}
|
||||
}
|
||||
}
|
||||
48
OpenRA.Game/Graphics/CursorSheetBuilder.cs
Normal file
48
OpenRA.Game/Graphics/CursorSheetBuilder.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class CursorSheetBuilder
|
||||
{
|
||||
static Cache<string, Sprite[]> cursors = new Cache<string, Sprite[]>(LoadCursors);
|
||||
static readonly string[] exts = { ".shp" };
|
||||
|
||||
static Sprite[] LoadCursors(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, a.Size)).ToArray();
|
||||
}
|
||||
catch (IndexOutOfRangeException) // This will occur when loading a custom (RA-format) .shp
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return cursors[filename]; }
|
||||
}
|
||||
}
|
||||
86
OpenRA.Game/Graphics/HardwarePalette.cs
Normal file
86
OpenRA.Game/Graphics/HardwarePalette.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class HardwarePalette : Sheet
|
||||
{
|
||||
public const int MaxPalettes = 64;
|
||||
int allocated = 0;
|
||||
|
||||
// We need to store the Palettes themselves for the remap palettes to work
|
||||
// We should probably try to fix this somehow
|
||||
static Dictionary<string, Palette> palettes;
|
||||
static Dictionary<string, int> indices;
|
||||
public HardwarePalette(Renderer renderer, Map map)
|
||||
: base(renderer,new Size(256, MaxPalettes))
|
||||
{
|
||||
palettes = new Dictionary<string, Palette>();
|
||||
indices = new Dictionary<string, int>();
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
try { return palettes[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
try { return indices[name]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Palette `{0}` does not exist".F(name));
|
||||
}
|
||||
}
|
||||
|
||||
public int AddPalette(string name, Palette p)
|
||||
{
|
||||
palettes.Add(name, p);
|
||||
indices.Add(name, allocated);
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
this[new Point(i, allocated)] = p.GetColor(i);
|
||||
}
|
||||
return allocated++;
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<IPaletteModifier> paletteMods)
|
||||
{
|
||||
var b = new Bitmap(Bitmap);
|
||||
foreach (var mod in paletteMods)
|
||||
mod.AdjustPalette(b);
|
||||
|
||||
Texture.SetData(b);
|
||||
Game.renderer.PaletteTexture = Texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
89
OpenRA.Game/Graphics/LineRenderer.cs
Normal file
89
OpenRA.Game/Graphics/LineRenderer.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class LineRenderer
|
||||
{
|
||||
Renderer renderer;
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer; /* kindof a waste of space, but the GPU likes indexing, oh well */
|
||||
|
||||
const int linesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[ 2 * linesPerBatch ];
|
||||
ushort[] indices = new ushort[ 2 * linesPerBatch ];
|
||||
int lines = 0;
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public LineRenderer( Renderer renderer )
|
||||
{
|
||||
this.renderer = renderer;
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer(vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if( lines > 0 )
|
||||
{
|
||||
renderer.LineShader.Render( () =>
|
||||
{
|
||||
vertexBuffer.SetData( vertices );
|
||||
indexBuffer.SetData( indices );
|
||||
renderer.DrawBatch( vertexBuffer, indexBuffer,
|
||||
nv, ni / 2, null, PrimitiveType.LineList );
|
||||
} );
|
||||
|
||||
nv = 0; ni = 0;
|
||||
lines = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawLine( float2 start, float2 end, Color startColor, Color endColor )
|
||||
{
|
||||
indices[ ni++ ] = (ushort)nv;
|
||||
|
||||
vertices[ nv++ ] = new Vertex( start,
|
||||
new float2( startColor.R / 255.0f, startColor.G / 255.0f ),
|
||||
new float2( startColor.B / 255.0f, startColor.A / 255.0f ) );
|
||||
|
||||
indices[ ni++ ] = (ushort)nv;
|
||||
|
||||
vertices[ nv++ ] = new Vertex( end,
|
||||
new float2( endColor.R / 255.0f, endColor.G / 255.0f ),
|
||||
new float2( endColor.B / 255.0f, endColor.A / 255.0f ) );
|
||||
|
||||
if( ++lines >= linesPerBatch )
|
||||
Flush();
|
||||
}
|
||||
|
||||
public void FillRect( RectangleF r, Color color )
|
||||
{
|
||||
for (float y = r.Top; y < r.Bottom; y++)
|
||||
{
|
||||
DrawLine(new float2(r.Left, y), new float2(r.Right, y), color, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
OpenRA.Game/Graphics/MappedImage.cs
Normal file
51
OpenRA.Game/Graphics/MappedImage.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class MappedImage
|
||||
{
|
||||
readonly Rectangle rect;
|
||||
public readonly string Src;
|
||||
public readonly string Name;
|
||||
|
||||
public MappedImage(string defaultSrc, XmlElement e)
|
||||
{
|
||||
Src = (e.HasAttribute("src")) ? e.GetAttribute("src") : defaultSrc;
|
||||
Name = e.GetAttribute("name");
|
||||
if (Src == null)
|
||||
throw new InvalidDataException("Image src missing");
|
||||
|
||||
rect = new Rectangle(int.Parse(e.GetAttribute("x")),
|
||||
int.Parse(e.GetAttribute("y")),
|
||||
int.Parse(e.GetAttribute("width")),
|
||||
int.Parse(e.GetAttribute("height")));
|
||||
}
|
||||
|
||||
public Sprite GetImage(Renderer r, Sheet s)
|
||||
{
|
||||
return new Sprite(s, rect, TextureChannel.Alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
213
OpenRA.Game/Graphics/Minimap.cs
Normal file
213
OpenRA.Game/Graphics/Minimap.cs
Normal file
@@ -0,0 +1,213 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class Minimap
|
||||
{
|
||||
readonly World world;
|
||||
Sheet sheet, mapOnlySheet;
|
||||
SpriteRenderer rgbaRenderer;
|
||||
LineRenderer lineRenderer;
|
||||
Sprite sprite, mapOnlySprite;
|
||||
Bitmap terrain, oreLayer;
|
||||
Rectangle bounds;
|
||||
|
||||
Sprite ownedSpawnPoint;
|
||||
Sprite unownedSpawnPoint;
|
||||
|
||||
const int alpha = 230;
|
||||
|
||||
public void Tick() { }
|
||||
|
||||
public Minimap(World world, Renderer r)
|
||||
{
|
||||
this.world = world;
|
||||
sheet = new Sheet(r, new Size(128, 128));
|
||||
mapOnlySheet = new Sheet(r, new Size(128, 128));
|
||||
|
||||
lineRenderer = new LineRenderer(r);
|
||||
rgbaRenderer = new SpriteRenderer(r, true, r.RgbaSpriteShader);
|
||||
var size = Math.Max(world.Map.Width, world.Map.Height);
|
||||
var dw = (size - world.Map.Width) / 2;
|
||||
var dh = (size - world.Map.Height) / 2;
|
||||
|
||||
bounds = new Rectangle(world.Map.Offset.X - dw, world.Map.Offset.Y - dh, size, size);
|
||||
|
||||
sprite = new Sprite(sheet, bounds, TextureChannel.Alpha);
|
||||
mapOnlySprite = new Sprite(mapOnlySheet, bounds, TextureChannel.Alpha);
|
||||
|
||||
shroudColor = Color.FromArgb(alpha, Color.Black);
|
||||
|
||||
ownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "owned");
|
||||
unownedSpawnPoint = ChromeProvider.GetImage(r, "spawnpoints", "unowned");
|
||||
}
|
||||
|
||||
public static Rectangle MakeMinimapBounds(Map m)
|
||||
{
|
||||
var size = Math.Max(m.Width, m.Height);
|
||||
var dw = (size - m.Width) / 2;
|
||||
var dh = (size - m.Height) / 2;
|
||||
|
||||
return new Rectangle(m.Offset.X - dw, m.Offset.Y - dh, size, size);
|
||||
}
|
||||
|
||||
static Cache<string, Color[]> terrainTypeColors = new Cache<string, Color[]>(
|
||||
theater =>
|
||||
{
|
||||
var pal = Game.world.WorldRenderer.GetPalette("terrain");
|
||||
return new[] {
|
||||
theater == "snow" ? 0xe3 :0x1a,
|
||||
0x63, 0x2f, 0x1f, 0x14, 0x64, 0x1f, 0x68, 0x6b, 0x6d, 0x88 }
|
||||
.Select(a => Color.FromArgb(alpha, pal.GetColor(a))).ToArray();
|
||||
});
|
||||
|
||||
static Color shroudColor;
|
||||
|
||||
public void InvalidateOre() { oreLayer = null; }
|
||||
|
||||
public static Bitmap RenderTerrainBitmap(Map map, TileSet tileset)
|
||||
{
|
||||
var colors = terrainTypeColors[map.Theater.ToLowerInvariant()];
|
||||
var terrain = new Bitmap(128, 128);
|
||||
for (var y = 0; y < 128; y++)
|
||||
for (var x = 0; x < 128; x++)
|
||||
terrain.SetPixel(x, y, map.IsInMap(x, y)
|
||||
? colors[tileset.GetWalkability(map.MapTiles[x, y])]
|
||||
: shroudColor);
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public static Bitmap RenderTerrainBitmapWithSpawnPoints(Map map, TileSet tileset)
|
||||
{
|
||||
/* todo: do this a bit nicer */
|
||||
|
||||
var terrain = RenderTerrainBitmap(map, tileset);
|
||||
foreach (var sp in map.SpawnPoints)
|
||||
terrain.SetPixel(sp.X, sp.Y, Color.White);
|
||||
|
||||
return terrain;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (terrain == null)
|
||||
terrain = RenderTerrainBitmap(world.Map, world.TileSet);
|
||||
|
||||
if (oreLayer == null)
|
||||
{
|
||||
var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()];
|
||||
oreLayer = new Bitmap(terrain);
|
||||
for (var y = world.Map.YOffset; y < world.Map.YOffset + world.Map.Height; y++)
|
||||
for (var x = world.Map.XOffset; x < world.Map.XOffset + world.Map.Width; x++)
|
||||
if (world.Map.ContainsResource(new int2(x, y)))
|
||||
oreLayer.SetPixel(x, y, colors[(int)TerrainMovementType.Ore]);
|
||||
}
|
||||
|
||||
mapOnlySheet.Texture.SetData(oreLayer);
|
||||
|
||||
if (!world.Queries.OwnedBy[world.LocalPlayer].WithTrait<ProvidesRadar>().Any())
|
||||
return;
|
||||
|
||||
var bitmap = new Bitmap(oreLayer);
|
||||
var bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
unsafe
|
||||
{
|
||||
var colors = terrainTypeColors[world.Map.Theater.ToLowerInvariant()];
|
||||
int* c = (int*)bitmapData.Scan0;
|
||||
|
||||
foreach (var a in world.Queries.WithTrait<Unit>().Where( a => a.Actor.Owner != null ))
|
||||
*(c + (a.Actor.Location.Y * bitmapData.Stride >> 2) + a.Actor.Location.X) =
|
||||
Color.FromArgb(alpha, a.Actor.Owner.Color).ToArgb();
|
||||
|
||||
for (var y = world.Map.YOffset; y < world.Map.YOffset + world.Map.Height; y++)
|
||||
for (var x = world.Map.XOffset; x < world.Map.XOffset + world.Map.Width; x++)
|
||||
{
|
||||
if (!world.LocalPlayer.Shroud.DisplayOnRadar(x, y))
|
||||
{
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) = shroudColor.ToArgb();
|
||||
continue;
|
||||
}
|
||||
var b = world.WorldActor.traits.Get<BuildingInfluence>().GetBuildingAt(new int2(x, y));
|
||||
if (b != null)
|
||||
*(c + (y * bitmapData.Stride >> 2) + x) =
|
||||
(b.Owner != null ? Color.FromArgb(alpha, b.Owner.Color) : colors[4]).ToArgb();
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bitmapData);
|
||||
sheet.Texture.SetData(bitmap);
|
||||
}
|
||||
|
||||
public void Draw(RectangleF rect, bool mapOnly)
|
||||
{
|
||||
rgbaRenderer.DrawSprite(mapOnly ? mapOnlySprite : sprite,
|
||||
new float2(rect.X, rect.Y), "chrome", new float2(rect.Width, rect.Height));
|
||||
rgbaRenderer.Flush();
|
||||
}
|
||||
|
||||
int2 TransformCellToMinimapPixel(RectangleF viewRect, int2 p)
|
||||
{
|
||||
var fx = (float)(p.X - bounds.X) / bounds.Width;
|
||||
var fy = (float)(p.Y - bounds.Y) / bounds.Height;
|
||||
|
||||
return new int2(
|
||||
(int)(viewRect.Width * fx + viewRect.Left) - 8,
|
||||
(int)(viewRect.Height * fy + viewRect.Top) - 8);
|
||||
}
|
||||
|
||||
public void DrawSpawnPoints(RectangleF rect)
|
||||
{
|
||||
var points = world.Map.SpawnPoints
|
||||
.Select( (sp,i) => Pair.New(sp,world.players.Values.FirstOrDefault(
|
||||
p => p.SpawnPointIndex == i + 1 ) ))
|
||||
.ToList();
|
||||
|
||||
foreach (var p in points)
|
||||
{
|
||||
var pos = TransformCellToMinimapPixel(rect, p.First);
|
||||
|
||||
if (p.Second == null)
|
||||
rgbaRenderer.DrawSprite(unownedSpawnPoint, pos, "chrome");
|
||||
else
|
||||
{
|
||||
lineRenderer.FillRect(new RectangleF(
|
||||
Game.viewport.Location.X + pos.X + 2,
|
||||
Game.viewport.Location.Y + pos.Y + 2,
|
||||
12, 12), p.Second.Color);
|
||||
|
||||
rgbaRenderer.DrawSprite(ownedSpawnPoint, pos, "chrome");
|
||||
}
|
||||
}
|
||||
|
||||
lineRenderer.Flush();
|
||||
rgbaRenderer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
114
OpenRA.Game/Graphics/OverlayRenderer.cs
Executable file
114
OpenRA.Game/Graphics/OverlayRenderer.cs
Executable file
@@ -0,0 +1,114 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class OverlayRenderer
|
||||
{
|
||||
static string[] overlaySpriteNames =
|
||||
{
|
||||
"sbag", "cycl", "brik", "fenc", "wood",
|
||||
"gold01", "gold02", "gold03", "gold04",
|
||||
"gem01", "gem02", "gem03", "gem04",
|
||||
"v12", "v13", "v14", "v15", "v16", "v17", "v18",
|
||||
"fpls", "wcrate", "scrate", "barb", "sbag",
|
||||
};
|
||||
|
||||
static string[] smudgeSpriteNames =
|
||||
{
|
||||
"bib3", "bib2", "bib1", "sc1", "sc2", "sc3", "sc4", "sc5", "sc6",
|
||||
"cr1", "cr2", "cr3", "cr4", "cr5", "cr6",
|
||||
};
|
||||
|
||||
readonly Sprite[][] overlaySprites;
|
||||
readonly Sprite[] smudgeSprites;
|
||||
|
||||
SpriteRenderer spriteRenderer;
|
||||
Map map;
|
||||
|
||||
public OverlayRenderer( Renderer renderer, Map map )
|
||||
{
|
||||
this.spriteRenderer = new SpriteRenderer( renderer, true );
|
||||
this.map = map;
|
||||
|
||||
overlaySprites = overlaySpriteNames.Select(f => SpriteSheetBuilder.LoadAllSprites(f)).ToArray();
|
||||
smudgeSprites = smudgeSpriteNames.SelectMany(f => SpriteSheetBuilder.LoadAllSprites(f)).ToArray();
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var shroud = Game.world.LocalPlayer.Shroud;
|
||||
|
||||
for (int y = map.YOffset; y < map.YOffset + map.Height; y++)
|
||||
for (int x = map.XOffset; x < map.XOffset + map.Width; x++)
|
||||
{
|
||||
if (!shroud.IsExplored(new int2(x,y))) continue;
|
||||
|
||||
var tr = map.MapTiles[x,y];
|
||||
if (tr.smudge != 0 && tr.smudge <= smudgeSprites.Length)
|
||||
{
|
||||
var location = new int2(x, y);
|
||||
spriteRenderer.DrawSprite(smudgeSprites[tr.smudge - 1],
|
||||
Game.CellSize * (float2)location, "terrain");
|
||||
}
|
||||
|
||||
var o = tr.overlay;
|
||||
if (o < overlaySprites.Length)
|
||||
{
|
||||
var location = new int2(x, y);
|
||||
var sprites = overlaySprites[o];
|
||||
var spriteIndex = 0;
|
||||
if (Ore.overlayIsFence[o]) spriteIndex = NearbyFences(x, y);
|
||||
else if (Ore.overlayIsOre[o]) spriteIndex = map.MapTiles[x,y].density - 1;
|
||||
else if (Ore.overlayIsGems[o]) spriteIndex = map.MapTiles[x,y].density - 1;
|
||||
spriteRenderer.DrawSprite(sprites[spriteIndex],
|
||||
Game.CellSize * (float2)location, "terrain");
|
||||
}
|
||||
}
|
||||
|
||||
spriteRenderer.Flush();
|
||||
}
|
||||
|
||||
bool IsFence( int x, int y )
|
||||
{
|
||||
var o = map.MapTiles[ x, y ].overlay;
|
||||
if (o < Ore.overlayIsFence.Length)
|
||||
return Ore.overlayIsFence[o];
|
||||
return false;
|
||||
}
|
||||
|
||||
int NearbyFences( int x, int y )
|
||||
{
|
||||
int ret = 0;
|
||||
if( IsFence( x, y - 1 ) )
|
||||
ret |= 1;
|
||||
if( IsFence( x + 1, y ) )
|
||||
ret |= 2;
|
||||
if( IsFence( x, y + 1 ) )
|
||||
ret |= 4;
|
||||
if( IsFence( x - 1, y ) )
|
||||
ret |= 8;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
OpenRA.Game/Graphics/Renderer.cs
Normal file
134
OpenRA.Game/Graphics/Renderer.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Support;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
internal class Renderer
|
||||
{
|
||||
internal static int SheetSize;
|
||||
|
||||
readonly IGraphicsDevice device;
|
||||
|
||||
public IShader SpriteShader { get; private set; } /* note: shared shader params */
|
||||
public IShader LineShader { get; private set; }
|
||||
public IShader RgbaSpriteShader { get; private set; }
|
||||
public IShader WorldSpriteShader { get; private set; }
|
||||
|
||||
public ITexture PaletteTexture;
|
||||
|
||||
public readonly SpriteFont RegularFont, BoldFont;
|
||||
|
||||
public Size Resolution { get { return device.WindowSize; } }
|
||||
|
||||
public Renderer(Size resolution, bool windowed)
|
||||
{
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowed, false );
|
||||
|
||||
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
|
||||
LineShader = device.CreateShader(FileSystem.Open("shaders/line.fx"));
|
||||
RgbaSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-rgba.fx"));
|
||||
WorldSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-shp.fx"));
|
||||
|
||||
// RegularFont = device.CreateFont( "FreeSans.ttf" );
|
||||
// BoldFont = device.CreateFont( "FreeSansBold.ttf" );
|
||||
|
||||
RegularFont = new SpriteFont(this, "FreeSans.ttf", 14);
|
||||
BoldFont = new SpriteFont(this, "FreeSansBold.ttf", 14);
|
||||
}
|
||||
|
||||
IGraphicsDevice CreateDevice( Assembly rendererDll, int width, int height, bool windowed, bool vsync )
|
||||
{
|
||||
foreach( RendererAttribute r in rendererDll.GetCustomAttributes( typeof( RendererAttribute ), false ) )
|
||||
{
|
||||
return (IGraphicsDevice)r.Type.GetConstructor( new Type[] { typeof( int ), typeof( int ), typeof( bool ), typeof( bool ) } )
|
||||
.Invoke( new object[] { width, height, windowed, vsync } );
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IGraphicsDevice Device { get { return device; } }
|
||||
|
||||
public void BeginFrame(float2 r1, float2 r2, float2 scroll)
|
||||
{
|
||||
device.Begin();
|
||||
device.Clear(Color.Black);
|
||||
|
||||
SetShaderParams( SpriteShader, r1, r2, scroll );
|
||||
SetShaderParams( LineShader, r1, r2, scroll );
|
||||
SetShaderParams( RgbaSpriteShader, r1, r2, scroll );
|
||||
SetShaderParams( WorldSpriteShader, r1, r2, scroll );
|
||||
}
|
||||
|
||||
private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
|
||||
{
|
||||
s.SetValue( "Palette", PaletteTexture );
|
||||
s.SetValue( "Scroll", scroll.X, scroll.Y );
|
||||
s.SetValue( "r1", r1.X, r1.Y );
|
||||
s.SetValue( "r2", r2.X, r2.Y );
|
||||
s.Commit();
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
{
|
||||
device.End();
|
||||
device.Present();
|
||||
}
|
||||
|
||||
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||
Range<int> vertexRange, Range<int> indexRange, ITexture texture, PrimitiveType type, IShader shader)
|
||||
where T : struct
|
||||
{
|
||||
shader.SetValue("DiffuseTexture", texture);
|
||||
shader.Commit();
|
||||
|
||||
vertices.Bind();
|
||||
indices.Bind();
|
||||
|
||||
device.DrawIndexedPrimitives(type, vertexRange, indexRange);
|
||||
|
||||
PerfHistory.Increment("batches", 1);
|
||||
}
|
||||
|
||||
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
|
||||
int vertexPool, int numPrimitives, ITexture texture, PrimitiveType type)
|
||||
where T : struct
|
||||
{
|
||||
SpriteShader.SetValue("DiffuseTexture", texture);
|
||||
SpriteShader.Commit();
|
||||
|
||||
vertices.Bind();
|
||||
indices.Bind();
|
||||
|
||||
device.DrawIndexedPrimitives(type, vertexPool, numPrimitives);
|
||||
|
||||
PerfHistory.Increment("batches", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
70
OpenRA.Game/Graphics/Sequence.cs
Normal file
70
OpenRA.Game/Graphics/Sequence.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Xml;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sequence
|
||||
{
|
||||
readonly Sprite[] sprites;
|
||||
readonly int start, length, facings;
|
||||
|
||||
public readonly string Name;
|
||||
public int Start { get { return start; } }
|
||||
public int End { get { return start + length; } }
|
||||
public int Length { get { return length; } }
|
||||
public int Facings { get { return facings; } }
|
||||
|
||||
public Sequence(string unit, XmlElement e)
|
||||
{
|
||||
string srcOverride = e.GetAttribute("src");
|
||||
Name = e.GetAttribute("name");
|
||||
|
||||
sprites = SpriteSheetBuilder.LoadAllSprites(string.IsNullOrEmpty(srcOverride) ? unit : srcOverride );
|
||||
start = int.Parse(e.GetAttribute("start"));
|
||||
|
||||
if (e.GetAttribute("length") == "*" || e.GetAttribute("end") == "*")
|
||||
length = sprites.Length - Start;
|
||||
else if (e.HasAttribute("length"))
|
||||
length = int.Parse(e.GetAttribute("length"));
|
||||
else if (e.HasAttribute("end"))
|
||||
length = int.Parse(e.GetAttribute("end")) - int.Parse(e.GetAttribute("start"));
|
||||
else
|
||||
length = 1;
|
||||
|
||||
if( e.HasAttribute( "facings" ) )
|
||||
facings = int.Parse( e.GetAttribute( "facings" ) );
|
||||
else
|
||||
facings = 1;
|
||||
}
|
||||
|
||||
public Sprite GetSprite( int frame )
|
||||
{
|
||||
return GetSprite( frame, 0 );
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame, int facing)
|
||||
{
|
||||
var f = Traits.Util.QuantizeFacing( facing, facings );
|
||||
return sprites[ (f * length) + ( frame % length ) + start ];
|
||||
}
|
||||
}
|
||||
}
|
||||
101
OpenRA.Game/Graphics/SequenceProvider.cs
Normal file
101
OpenRA.Game/Graphics/SequenceProvider.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class SequenceProvider
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, Sequence>> units;
|
||||
static Dictionary<string, CursorSequence> cursors;
|
||||
|
||||
public static void Initialize(params string[] sequenceFiles)
|
||||
{
|
||||
units = new Dictionary<string, Dictionary<string, Sequence>>();
|
||||
cursors = new Dictionary<string, CursorSequence>();
|
||||
|
||||
foreach (var f in sequenceFiles)
|
||||
LoadSequenceSource(f);
|
||||
}
|
||||
|
||||
static void LoadSequenceSource(string filename)
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(FileSystem.Open(filename));
|
||||
|
||||
foreach (XmlElement eUnit in document.SelectNodes("/sequences/unit"))
|
||||
LoadSequencesForUnit(eUnit);
|
||||
|
||||
foreach (XmlElement eCursor in document.SelectNodes("/sequences/cursor"))
|
||||
LoadSequencesForCursor(eCursor);
|
||||
}
|
||||
|
||||
static void LoadSequencesForCursor(XmlElement eCursor)
|
||||
{
|
||||
string cursorSrc = eCursor.GetAttribute("src");
|
||||
|
||||
foreach (XmlElement eSequence in eCursor.SelectNodes("./sequence"))
|
||||
cursors.Add(eSequence.GetAttribute("name"), new CursorSequence(cursorSrc, eSequence));
|
||||
|
||||
Log.Write("* LoadSequencesForCursor() done");
|
||||
}
|
||||
|
||||
static void LoadSequencesForUnit(XmlElement eUnit)
|
||||
{
|
||||
string unitName = eUnit.GetAttribute("name");
|
||||
Log.Write("Loading sequence {0}", unitName);
|
||||
var sequences = eUnit.SelectNodes("./sequence").OfType<XmlElement>()
|
||||
.Select(e => new Sequence(unitName, e))
|
||||
.ToDictionary(s => s.Name);
|
||||
|
||||
units.Add(unitName, sequences);
|
||||
}
|
||||
|
||||
public static Sequence GetSequence(string unitName, string sequenceName)
|
||||
{
|
||||
try { return units[unitName][sequenceName]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName));
|
||||
}
|
||||
}
|
||||
|
||||
public static bool HasSequence(string unit, string seq)
|
||||
{
|
||||
return units[unit].ContainsKey(seq);
|
||||
}
|
||||
|
||||
public static CursorSequence GetCursorSequence(string cursor)
|
||||
{
|
||||
try { return cursors[cursor]; }
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Cursor does not have a sequence `{0}`".F(cursor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
OpenRA.Game/Graphics/Sheet.cs
Normal file
72
OpenRA.Game/Graphics/Sheet.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sheet
|
||||
{
|
||||
readonly Renderer renderer;
|
||||
protected readonly Bitmap bitmap;
|
||||
|
||||
ITexture texture;
|
||||
|
||||
internal Sheet(Renderer renderer, Size size)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.bitmap = new Bitmap(size.Width, size.Height);
|
||||
}
|
||||
|
||||
internal Sheet(Renderer renderer, string filename)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.bitmap = (Bitmap)Image.FromStream(FileSystem.Open(filename));
|
||||
}
|
||||
|
||||
void Resolve()
|
||||
{
|
||||
texture = renderer.Device.CreateTexture(bitmap);
|
||||
}
|
||||
|
||||
public ITexture Texture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (texture == null)
|
||||
Resolve();
|
||||
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
public Size Size { get { return bitmap.Size; } }
|
||||
|
||||
protected Color this[Point p]
|
||||
{
|
||||
get { return bitmap.GetPixel(p.X, p.Y); }
|
||||
set { bitmap.SetPixel(p.X, p.Y, value); }
|
||||
}
|
||||
|
||||
public Bitmap Bitmap { get { return bitmap; } } // for perf
|
||||
}
|
||||
}
|
||||
119
OpenRA.Game/Graphics/SheetBuilder.cs
Normal file
119
OpenRA.Game/Graphics/SheetBuilder.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SheetBuilder
|
||||
{
|
||||
public static SheetBuilder SharedInstance;
|
||||
public static void Initialize(Renderer r)
|
||||
{
|
||||
SharedInstance = new SheetBuilder(r, TextureChannel.Red);
|
||||
}
|
||||
|
||||
public SheetBuilder(Renderer r, TextureChannel ch)
|
||||
{
|
||||
renderer = r;
|
||||
current = null;
|
||||
rowHeight = 0;
|
||||
channel = null;
|
||||
initialChannel = ch;
|
||||
}
|
||||
|
||||
public Sprite Add(byte[] src, Size size)
|
||||
{
|
||||
Sprite rect = Allocate(size);
|
||||
Util.FastCopyIntoChannel(rect, src);
|
||||
return rect;
|
||||
}
|
||||
|
||||
public Sprite Add(Size size, byte paletteIndex)
|
||||
{
|
||||
byte[] data = new byte[size.Width * size.Height];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
data[i] = paletteIndex;
|
||||
|
||||
return Add(data, size);
|
||||
}
|
||||
|
||||
Sheet NewSheet() { return new Sheet( renderer, new Size( Renderer.SheetSize, Renderer.SheetSize ) ); }
|
||||
|
||||
Renderer renderer;
|
||||
Sheet current = null;
|
||||
int rowHeight = 0;
|
||||
Point p;
|
||||
TextureChannel? channel = null;
|
||||
TextureChannel initialChannel;
|
||||
|
||||
TextureChannel? NextChannel(TextureChannel? t)
|
||||
{
|
||||
if (t == null)
|
||||
return initialChannel;
|
||||
|
||||
switch (t.Value)
|
||||
{
|
||||
case TextureChannel.Red: return TextureChannel.Green;
|
||||
case TextureChannel.Green: return TextureChannel.Blue;
|
||||
case TextureChannel.Blue: return TextureChannel.Alpha;
|
||||
case TextureChannel.Alpha: return null;
|
||||
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Sprite Allocate(Size imageSize)
|
||||
{
|
||||
if (current == null)
|
||||
{
|
||||
current = NewSheet();
|
||||
channel = NextChannel(null);
|
||||
}
|
||||
|
||||
if (imageSize.Width + p.X > current.Size.Width)
|
||||
{
|
||||
p = new Point(0, p.Y + rowHeight);
|
||||
rowHeight = imageSize.Height;
|
||||
}
|
||||
|
||||
if (imageSize.Height > rowHeight)
|
||||
rowHeight = imageSize.Height;
|
||||
|
||||
if (p.Y + imageSize.Height > current.Size.Height)
|
||||
{
|
||||
|
||||
if (null == (channel = NextChannel(channel)))
|
||||
{
|
||||
current = NewSheet();
|
||||
channel = NextChannel(channel);
|
||||
}
|
||||
|
||||
rowHeight = imageSize.Height;
|
||||
p = new Point(0,0);
|
||||
}
|
||||
|
||||
Sprite rect = new Sprite(current, new Rectangle(p, imageSize), channel.Value);
|
||||
p.X += imageSize.Width;
|
||||
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
71
OpenRA.Game/Graphics/Sprite.cs
Normal file
71
OpenRA.Game/Graphics/Sprite.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sprite
|
||||
{
|
||||
public readonly Rectangle bounds;
|
||||
public readonly Sheet sheet;
|
||||
public readonly TextureChannel channel;
|
||||
public readonly RectangleF uv;
|
||||
public readonly float2 size;
|
||||
|
||||
readonly float2[] uvhax;
|
||||
|
||||
internal Sprite(Sheet sheet, Rectangle bounds, TextureChannel channel)
|
||||
{
|
||||
this.bounds = bounds;
|
||||
this.sheet = sheet;
|
||||
this.channel = channel;
|
||||
|
||||
uv = new RectangleF(
|
||||
(float)(bounds.Left) / sheet.Size.Width,
|
||||
(float)(bounds.Top) / sheet.Size.Height,
|
||||
(float)(bounds.Width) / sheet.Size.Width,
|
||||
(float)(bounds.Height) / sheet.Size.Height);
|
||||
|
||||
uvhax = new float2[]
|
||||
{
|
||||
new float2( uv.Left, uv.Top ),
|
||||
new float2( uv.Right, uv.Top ),
|
||||
new float2( uv.Left, uv.Bottom ),
|
||||
new float2( uv.Right, uv.Bottom ),
|
||||
};
|
||||
|
||||
this.size = new float2(bounds.Size);
|
||||
}
|
||||
|
||||
public float2 FastMapTextureCoords( int k )
|
||||
{
|
||||
return uvhax[ k ];
|
||||
}
|
||||
}
|
||||
|
||||
public enum TextureChannel
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
Alpha = 3,
|
||||
}
|
||||
}
|
||||
116
OpenRA.Game/Graphics/SpriteFont.cs
Normal file
116
OpenRA.Game/Graphics/SpriteFont.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using Tao.FreeType;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SpriteFont
|
||||
{
|
||||
int size;
|
||||
public SpriteFont(Renderer r, string name, int size)
|
||||
{
|
||||
this.size = size;
|
||||
|
||||
if (0 != FT.FT_New_Face(library, name, 0, out face))
|
||||
throw new InvalidOperationException("FT_New_Face failed");
|
||||
|
||||
FT.FT_Set_Pixel_Sizes(face, 0, (uint)size);
|
||||
glyphs = new Cache<char, GlyphInfo>(CreateGlyph);
|
||||
|
||||
// setup a 1-channel SheetBuilder for our private use
|
||||
if (builder == null) builder = new SheetBuilder(r, TextureChannel.Alpha);
|
||||
|
||||
// precache glyphs for U+0020 - U+007f
|
||||
for (var n = (char)0x20; n < (char)0x7f; n++)
|
||||
if (glyphs[n] == null)
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public void DrawText(SpriteRenderer r, string text, float2 location, Color c)
|
||||
{
|
||||
location.Y += size; // baseline vs top
|
||||
|
||||
var p = location;
|
||||
foreach (var s in text)
|
||||
{
|
||||
if (s == '\n')
|
||||
{
|
||||
location.Y += size;
|
||||
p = location;
|
||||
continue;
|
||||
}
|
||||
|
||||
var g = glyphs[s];
|
||||
r.DrawSprite(g.Sprite,
|
||||
new float2(
|
||||
(int)Math.Round(p.X + g.Offset.X, 0),
|
||||
p.Y + g.Offset.Y),
|
||||
"chrome");
|
||||
p.X += g.Advance;
|
||||
}
|
||||
|
||||
r.Flush();
|
||||
}
|
||||
|
||||
public int2 Measure(string text)
|
||||
{
|
||||
return new int2((int)text.Split( '\n' ).Max( s => s.Sum(a => glyphs[a].Advance)), size);
|
||||
}
|
||||
|
||||
Cache<char, GlyphInfo> glyphs;
|
||||
IntPtr face;
|
||||
|
||||
GlyphInfo CreateGlyph(char c)
|
||||
{
|
||||
var index = FT.FT_Get_Char_Index(face, (uint)c);
|
||||
FT.FT_Load_Glyph(face, index, FT.FT_LOAD_RENDER);
|
||||
|
||||
var _face = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec));
|
||||
var _glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(_face.glyph, typeof(FT_GlyphSlotRec));
|
||||
|
||||
var s = builder.Allocate(new Size(_glyph.metrics.width >> 6, _glyph.metrics.height >> 6));
|
||||
|
||||
var g = new GlyphInfo
|
||||
{
|
||||
Sprite = s,
|
||||
Advance = _glyph.metrics.horiAdvance / 64f,
|
||||
Offset = { X = _glyph.bitmap_left, Y = -_glyph.bitmap_top }
|
||||
};
|
||||
|
||||
unsafe
|
||||
{
|
||||
var p = (byte*)_glyph.bitmap.buffer;
|
||||
|
||||
for (var j = 0; j < s.size.Y; j++)
|
||||
{
|
||||
for (var i = 0; i < s.size.X; i++)
|
||||
if (p[i] != 0)
|
||||
s.sheet.Bitmap.SetPixel(i + s.bounds.Left, j + s.bounds.Top,
|
||||
Color.FromArgb(p[i], 0xff, 0xff, 0xff));
|
||||
|
||||
p += _glyph.bitmap.pitch;
|
||||
}
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
static SpriteFont()
|
||||
{
|
||||
FT.FT_Init_FreeType(out library);
|
||||
}
|
||||
|
||||
static IntPtr library;
|
||||
static SheetBuilder builder;
|
||||
}
|
||||
|
||||
class GlyphInfo
|
||||
{
|
||||
public float Advance;
|
||||
public int2 Offset;
|
||||
public Sprite Sprite;
|
||||
}
|
||||
}
|
||||
91
OpenRA.Game/Graphics/SpriteRenderer.cs
Normal file
91
OpenRA.Game/Graphics/SpriteRenderer.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class SpriteRenderer
|
||||
{
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer;
|
||||
Renderer renderer;
|
||||
IShader shader;
|
||||
|
||||
const int spritesPerBatch = 1024;
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * spritesPerBatch];
|
||||
ushort[] indices = new ushort[6 * spritesPerBatch];
|
||||
Sheet currentSheet = null;
|
||||
int sprites = 0;
|
||||
int nv = 0, ni = 0;
|
||||
|
||||
public SpriteRenderer(Renderer renderer, bool allowAlpha, IShader shader)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.shader = shader;
|
||||
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
}
|
||||
|
||||
public SpriteRenderer(Renderer renderer, bool allowAlpha)
|
||||
: this(renderer, allowAlpha, renderer.SpriteShader) { }
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if (sprites > 0)
|
||||
{
|
||||
shader.SetValue( "DiffuseTexture", currentSheet.Texture );
|
||||
shader.Render(() =>
|
||||
{
|
||||
vertexBuffer.SetData(vertices);
|
||||
indexBuffer.SetData(indices);
|
||||
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
new Range<int>(0, nv),
|
||||
new Range<int>(0, ni),
|
||||
currentSheet.Texture, PrimitiveType.TriangleList,
|
||||
shader);
|
||||
});
|
||||
|
||||
nv = 0; ni = 0;
|
||||
currentSheet = null;
|
||||
sprites = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette)
|
||||
{
|
||||
DrawSprite(s, location, palette, s.size);
|
||||
}
|
||||
|
||||
public void DrawSprite(Sprite s, float2 location, string palette, float2 size)
|
||||
{
|
||||
if (s.sheet != currentSheet)
|
||||
Flush();
|
||||
|
||||
currentSheet = s.sheet;
|
||||
Util.FastCreateQuad(vertices, indices, location.ToInt2(), s, Game.world.WorldRenderer.GetPaletteIndex(palette), nv, ni, size);
|
||||
nv += 4; ni += 6;
|
||||
if (++sprites >= spritesPerBatch)
|
||||
Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
50
OpenRA.Game/Graphics/SpriteSheetBuilder.cs
Normal file
50
OpenRA.Game/Graphics/SpriteSheetBuilder.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class SpriteSheetBuilder
|
||||
{
|
||||
public static void Initialize( Map map )
|
||||
{
|
||||
exts = new[] {
|
||||
"." + map.Theater.Substring( 0, 3 ).ToLowerInvariant(),
|
||||
".shp",
|
||||
".tem",
|
||||
".sno",
|
||||
".int" };
|
||||
sprites = new Cache<string, Sprite[]>( LoadSprites );
|
||||
}
|
||||
|
||||
static Cache<string, Sprite[]> sprites;
|
||||
static string[] exts;
|
||||
|
||||
static Sprite[] LoadSprites(string filename)
|
||||
{
|
||||
var shp = new ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
return shp.Select(a => SheetBuilder.SharedInstance.Add(a.Image, shp.Size)).ToArray();
|
||||
}
|
||||
|
||||
public static Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }
|
||||
}
|
||||
}
|
||||
110
OpenRA.Game/Graphics/TerrainRenderer.cs
Normal file
110
OpenRA.Game/Graphics/TerrainRenderer.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
class TerrainRenderer
|
||||
{
|
||||
IVertexBuffer<Vertex> vertexBuffer;
|
||||
IIndexBuffer indexBuffer;
|
||||
Sheet terrainSheet;
|
||||
|
||||
Renderer renderer;
|
||||
Map map;
|
||||
OverlayRenderer overlayRenderer;
|
||||
|
||||
public TerrainRenderer(World world, Renderer renderer, WorldRenderer wr)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.map = world.Map;
|
||||
|
||||
Size tileSize = new Size( Game.CellSize, Game.CellSize );
|
||||
|
||||
var tileMapping = new Cache<TileReference, Sprite>(
|
||||
x => SheetBuilder.SharedInstance.Add(world.TileSet.GetBytes(x), tileSize));
|
||||
|
||||
Vertex[] vertices = new Vertex[4 * map.Height * map.Width];
|
||||
ushort[] indices = new ushort[6 * map.Height * map.Width];
|
||||
|
||||
int nv = 0;
|
||||
int ni = 0;
|
||||
for( int j = map.YOffset ; j < map.YOffset + map.Height ; j++ )
|
||||
for( int i = map.XOffset ; i < map.XOffset + map.Width; i++ )
|
||||
{
|
||||
Sprite tile = tileMapping[map.MapTiles[i, j]];
|
||||
// TODO: The zero below should explicitly refer to the terrain palette, but this code is called
|
||||
// before the palettes are created
|
||||
Util.FastCreateQuad(vertices, indices, Game.CellSize * new float2(i, j), tile, 0, nv, ni, tile.size);
|
||||
nv += 4;
|
||||
ni += 6;
|
||||
}
|
||||
|
||||
terrainSheet = tileMapping[map.MapTiles[map.XOffset, map.YOffset]].sheet;
|
||||
|
||||
vertexBuffer = renderer.Device.CreateVertexBuffer( vertices.Length );
|
||||
vertexBuffer.SetData( vertices );
|
||||
|
||||
indexBuffer = renderer.Device.CreateIndexBuffer( indices.Length );
|
||||
indexBuffer.SetData( indices );
|
||||
|
||||
overlayRenderer = new OverlayRenderer( renderer, map );
|
||||
}
|
||||
|
||||
public void Draw( Viewport viewport )
|
||||
{
|
||||
int indicesPerRow = map.Width * 6;
|
||||
int verticesPerRow = map.Width * 4;
|
||||
|
||||
int visibleRows = (int)(viewport.Height / 24.0f + 2);
|
||||
|
||||
int firstRow = (int)((viewport.Location.Y) / 24.0f - map.YOffset);
|
||||
int lastRow = firstRow + visibleRows;
|
||||
|
||||
if (lastRow < 0 || firstRow > map.Height)
|
||||
return;
|
||||
|
||||
if (firstRow < 0) firstRow = 0;
|
||||
if (lastRow > map.Height) lastRow = map.Height;
|
||||
|
||||
if (!Game.world.LocalPlayer.Shroud.HasGPS && Game.world.LocalPlayer.Shroud.bounds.HasValue)
|
||||
{
|
||||
var r = Game.world.LocalPlayer.Shroud.bounds.Value;
|
||||
if (firstRow < r.Top - map.YOffset)
|
||||
firstRow = r.Top - map.YOffset;
|
||||
|
||||
if (firstRow > r.Bottom - map.YOffset)
|
||||
firstRow = r.Bottom - map.YOffset;
|
||||
}
|
||||
|
||||
renderer.SpriteShader.SetValue( "DiffuseTexture", terrainSheet.Texture );
|
||||
renderer.SpriteShader.Render(() =>
|
||||
renderer.DrawBatch(vertexBuffer, indexBuffer,
|
||||
new Range<int>(verticesPerRow * firstRow, verticesPerRow * lastRow),
|
||||
new Range<int>(indicesPerRow * firstRow, indicesPerRow * lastRow),
|
||||
terrainSheet.Texture, PrimitiveType.TriangleList, renderer.SpriteShader));
|
||||
|
||||
overlayRenderer.Draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
131
OpenRA.Game/Graphics/Util.cs
Normal file
131
OpenRA.Game/Graphics/Util.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
static class Util
|
||||
{
|
||||
public static string[] ReadAllLines(Stream s)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
using (StreamReader reader = new StreamReader(s))
|
||||
while(!reader.EndOfStream)
|
||||
{
|
||||
var line = reader.ReadLine();
|
||||
if( !string.IsNullOrEmpty( line ) && line[0] != '#' )
|
||||
result.Add( line );
|
||||
}
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static T[] MakeArray<T>(int count, Converter<int, T> f)
|
||||
{
|
||||
T[] result = new T[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
result[i] = f(i);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static float[] channelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
|
||||
|
||||
public static void FastCreateQuad(Vertex[] vertices, ushort[] indices, float2 o, Sprite r, int palette, int nv, int ni, float2 size)
|
||||
{
|
||||
var attrib = new float2(palette / (float)HardwarePalette.MaxPalettes, channelSelect[(int)r.channel]);
|
||||
|
||||
vertices[nv] = new Vertex(o,
|
||||
r.FastMapTextureCoords(0), attrib);
|
||||
vertices[nv + 1] = new Vertex(new float2(o.X + size.X, o.Y),
|
||||
r.FastMapTextureCoords(1), attrib);
|
||||
vertices[nv + 2] = new Vertex(new float2(o.X, o.Y + size.Y),
|
||||
r.FastMapTextureCoords(2), attrib);
|
||||
vertices[nv + 3] = new Vertex(new float2(o.X + size.X, o.Y + size.Y),
|
||||
r.FastMapTextureCoords(3), attrib);
|
||||
|
||||
indices[ni] = (ushort)(nv);
|
||||
indices[ni + 1] = indices[ni + 3] = (ushort)(nv + 1);
|
||||
indices[ni + 2] = indices[ni + 5] = (ushort)(nv + 2);
|
||||
indices[ni + 4] = (ushort)(nv + 3);
|
||||
}
|
||||
|
||||
public static void FastCopyIntoChannel(Sprite dest, byte[] src)
|
||||
{
|
||||
var bitmap = dest.sheet.Bitmap;
|
||||
BitmapData bits = null;
|
||||
uint[] channelMasks = { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 };
|
||||
int[] shifts = { 16, 8, 0, 24 };
|
||||
|
||||
uint mask = channelMasks[(int)dest.channel];
|
||||
int shift = shifts[(int)dest.channel];
|
||||
|
||||
try
|
||||
{
|
||||
bits = bitmap.LockBits(dest.bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
|
||||
int width = dest.bounds.Width;
|
||||
int height = dest.bounds.Height;
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* srcbase = &src[0])
|
||||
{
|
||||
byte* s = srcbase;
|
||||
uint* t = (uint*)bits.Scan0.ToPointer();
|
||||
int stride = bits.Stride >> 2;
|
||||
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
uint* p = t;
|
||||
for (int i = 0; i < width; i++, p++)
|
||||
*p = (*p & ~mask) | ((mask & ((uint)*s++) << shift));
|
||||
t += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
bitmap.UnlockBits(bits);
|
||||
}
|
||||
}
|
||||
|
||||
public static Color Lerp(float t, Color a, Color b)
|
||||
{
|
||||
return Color.FromArgb(
|
||||
LerpChannel(t, a.A, b.A),
|
||||
LerpChannel(t, a.R, b.R),
|
||||
LerpChannel(t, a.G, b.G),
|
||||
LerpChannel(t, a.B, b.B));
|
||||
}
|
||||
|
||||
public static int LerpChannel(float t, int a, int b)
|
||||
{
|
||||
return (int)((1 - t) * a + t * b);
|
||||
}
|
||||
}
|
||||
}
|
||||
151
OpenRA.Game/Graphics/Viewport.cs
Normal file
151
OpenRA.Game/Graphics/Viewport.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
interface IHandleInput
|
||||
{
|
||||
bool HandleInput(World world, MouseInput mi);
|
||||
}
|
||||
|
||||
class Viewport
|
||||
{
|
||||
readonly float2 screenSize;
|
||||
float2 scrollPosition;
|
||||
readonly Renderer renderer;
|
||||
|
||||
public float2 Location { get { return scrollPosition; } }
|
||||
|
||||
public int Width { get { return (int)screenSize.X; } }
|
||||
public int Height { get { return (int)screenSize.Y; } }
|
||||
|
||||
SpriteRenderer cursorRenderer;
|
||||
int2 mousePos;
|
||||
float cursorFrame = 0f;
|
||||
|
||||
public void Scroll(float2 delta)
|
||||
{
|
||||
scrollPosition = scrollPosition + delta;
|
||||
}
|
||||
|
||||
public IEnumerable<IHandleInput> regions { get { return new IHandleInput[] { Game.chrome, Game.controller }; } }
|
||||
|
||||
public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
|
||||
{
|
||||
this.screenSize = screenSize;
|
||||
this.renderer = renderer;
|
||||
cursorRenderer = new SpriteRenderer(renderer, true);
|
||||
|
||||
this.scrollPosition = Game.CellSize* mapStart;
|
||||
}
|
||||
|
||||
public void DrawRegions( World world )
|
||||
{
|
||||
world.WorldRenderer.palette.Update(world.Queries.WithTraitMultiple<IPaletteModifier>().Select(t=>t.Trait));
|
||||
|
||||
float2 r1 = new float2(2, -2) / screenSize;
|
||||
float2 r2 = new float2(-1, 1);
|
||||
|
||||
renderer.BeginFrame(r1, r2, scrollPosition);
|
||||
|
||||
if( Game.orderManager.GameStarted )
|
||||
{
|
||||
world.WorldRenderer.Draw();
|
||||
Game.chrome.Draw( world );
|
||||
|
||||
|
||||
if( Game.orderManager.Connection.ConnectionState == ConnectionState.NotConnected )
|
||||
Game.chrome.DrawDialog("Connection lost.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// what a hack. as soon as we have some real chrome stuff...
|
||||
|
||||
switch( Game.orderManager.Connection.ConnectionState )
|
||||
{
|
||||
case ConnectionState.Connecting:
|
||||
Game.chrome.DrawDialog("Connecting to {0}:{1}...".F( Game.Settings.NetworkHost, Game.Settings.NetworkPort ));
|
||||
break;
|
||||
case ConnectionState.NotConnected:
|
||||
Game.chrome.DrawDialog("Connection failed.");
|
||||
break;
|
||||
case ConnectionState.Connected:
|
||||
Game.chrome.DrawLobby( world );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var cursorName = Game.chrome.HitTest(mousePos) ? "default" : Game.controller.ChooseCursor( world );
|
||||
var c = new Cursor(cursorName);
|
||||
cursorRenderer.DrawSprite(c.GetSprite((int)cursorFrame), mousePos + Location - c.GetHotspot(), "cursor");
|
||||
cursorRenderer.Flush();
|
||||
|
||||
renderer.EndFrame();
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
cursorFrame += 0.5f;
|
||||
}
|
||||
|
||||
IHandleInput dragRegion = null;
|
||||
public void DispatchMouseInput(World world, MouseInput mi)
|
||||
{
|
||||
if (mi.Event == MouseInputEvent.Move)
|
||||
mousePos = mi.Location;
|
||||
|
||||
if (dragRegion != null) {
|
||||
dragRegion.HandleInput( world, mi );
|
||||
if (mi.Event == MouseInputEvent.Up) dragRegion = null;
|
||||
return;
|
||||
}
|
||||
|
||||
dragRegion = regions.FirstOrDefault(r => r.HandleInput(world, mi));
|
||||
if (mi.Event != MouseInputEvent.Down)
|
||||
dragRegion = null;
|
||||
}
|
||||
|
||||
public float2 ViewToWorld(MouseInput mi)
|
||||
{
|
||||
return (1 / 24.0f) * (new float2(mi.Location.X, mi.Location.Y) + Location);
|
||||
}
|
||||
|
||||
public void Center(IEnumerable<Actor> actors)
|
||||
{
|
||||
if (!actors.Any()) return;
|
||||
|
||||
var avgPos = (1f / actors.Count()) * actors
|
||||
.Select(a => a.CenterLocation)
|
||||
.Aggregate((a, b) => a + b);
|
||||
|
||||
scrollPosition = (avgPos - .5f * new float2(Width, Height)).ToInt2();
|
||||
}
|
||||
|
||||
public void GoToStartLocation( Player player )
|
||||
{
|
||||
Center( player.World.Queries.OwnedBy[ player ].WithTrait<Selectable>().Select( a => a.Actor ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
315
OpenRA.Game/Graphics/WorldRenderer.cs
Normal file
315
OpenRA.Game/Graphics/WorldRenderer.cs
Normal file
@@ -0,0 +1,315 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007,2009,2010 Chris Forbes, Robert Pepperell, Matthew Bowra-Dean, Paul Chote, Alli Witheford.
|
||||
* This file is part of OpenRA.
|
||||
*
|
||||
* OpenRA is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OpenRA is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with OpenRA. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
public class WorldRenderer
|
||||
{
|
||||
readonly World world;
|
||||
internal readonly TerrainRenderer terrainRenderer;
|
||||
internal readonly SpriteRenderer spriteRenderer;
|
||||
internal readonly LineRenderer lineRenderer;
|
||||
internal readonly UiOverlay uiOverlay;
|
||||
internal readonly Renderer renderer;
|
||||
internal readonly HardwarePalette palette;
|
||||
|
||||
public static bool ShowUnitPaths = false;
|
||||
|
||||
internal WorldRenderer(World world, Renderer renderer)
|
||||
{
|
||||
this.world = world;
|
||||
this.renderer = renderer;
|
||||
|
||||
terrainRenderer = new TerrainRenderer(world, renderer, this);
|
||||
spriteRenderer = new SpriteRenderer(renderer, true);
|
||||
lineRenderer = new LineRenderer(renderer);
|
||||
uiOverlay = new UiOverlay(spriteRenderer);
|
||||
palette = new HardwarePalette(renderer, world.Map);
|
||||
Log.Write("Created worldrenderer");
|
||||
}
|
||||
|
||||
public int GetPaletteIndex(string name)
|
||||
{
|
||||
return palette.GetPaletteIndex(name);
|
||||
}
|
||||
|
||||
public Palette GetPalette(string name)
|
||||
{
|
||||
return palette.GetPalette(name);
|
||||
}
|
||||
|
||||
public void AddPalette(string name, Palette pal)
|
||||
{
|
||||
palette.AddPalette(name, pal);
|
||||
}
|
||||
|
||||
void DrawSpriteList(RectangleF rect,
|
||||
IEnumerable<Renderable> images)
|
||||
{
|
||||
foreach (var image in images)
|
||||
{
|
||||
var loc = image.Pos;
|
||||
|
||||
if (loc.X > rect.Right || loc.X < rect.Left - image.Sprite.bounds.Width)
|
||||
continue;
|
||||
if (loc.Y > rect.Bottom || loc.Y < rect.Top - image.Sprite.bounds.Height)
|
||||
continue;
|
||||
|
||||
spriteRenderer.DrawSprite(image.Sprite, loc, image.Palette);
|
||||
}
|
||||
}
|
||||
|
||||
class SpriteComparer : IComparer<Renderable>
|
||||
{
|
||||
public int Compare(Renderable x, Renderable y)
|
||||
{
|
||||
var result = x.ZOffset.CompareTo(y.ZOffset);
|
||||
if (result == 0)
|
||||
result = x.Pos.Y.CompareTo(y.Pos.Y);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle GetBoundsRect()
|
||||
{
|
||||
if (!world.LocalPlayer.Shroud.HasGPS && world.LocalPlayer.Shroud.bounds.HasValue)
|
||||
{
|
||||
var r = world.LocalPlayer.Shroud.bounds.Value;
|
||||
|
||||
var left = (int)(Game.CellSize * r.Left - Game.viewport.Location.X);
|
||||
var top = (int)(Game.CellSize * r.Top - Game.viewport.Location.Y);
|
||||
var right = left + (int)(Game.CellSize * r.Width);
|
||||
var bottom = top + (int)(Game.CellSize * r.Height);
|
||||
|
||||
if (left < 0) left = 0;
|
||||
if (top < 0) top = 0;
|
||||
if (right > Game.viewport.Width) right = Game.viewport.Width;
|
||||
if (bottom > Game.viewport.Height) bottom = Game.viewport.Height;
|
||||
|
||||
return new Rectangle(left, top, right - left, bottom - top);
|
||||
}
|
||||
else
|
||||
return new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height);
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
var bounds = GetBoundsRect();
|
||||
renderer.Device.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
|
||||
|
||||
terrainRenderer.Draw(Game.viewport);
|
||||
|
||||
var comparer = new SpriteComparer();
|
||||
|
||||
bounds.Offset((int)Game.viewport.Location.X, (int)Game.viewport.Location.Y);
|
||||
|
||||
var renderables = world.Actors.SelectMany(a => a.Render())
|
||||
.OrderBy(r => r, comparer);
|
||||
|
||||
DrawSpriteList(bounds, renderables);
|
||||
|
||||
foreach (var e in world.Effects)
|
||||
DrawSpriteList(bounds, e.Render());
|
||||
|
||||
uiOverlay.Draw( world );
|
||||
|
||||
spriteRenderer.Flush();
|
||||
|
||||
DrawBandBox();
|
||||
|
||||
if (Game.controller.orderGenerator != null)
|
||||
Game.controller.orderGenerator.Render( world );
|
||||
|
||||
world.LocalPlayer.Shroud.Draw(spriteRenderer);
|
||||
|
||||
lineRenderer.Flush();
|
||||
spriteRenderer.Flush();
|
||||
}
|
||||
|
||||
void DrawBandBox()
|
||||
{
|
||||
var selbox = Game.controller.SelectionBox;
|
||||
if (selbox == null) return;
|
||||
|
||||
var a = selbox.Value.First;
|
||||
var b = new float2(selbox.Value.Second.X - a.X, 0);
|
||||
var c = new float2(0, selbox.Value.Second.Y - a.Y);
|
||||
|
||||
lineRenderer.DrawLine(a, a + b, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a + b, a + b + c, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a + b + c, a + c, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a, a + c, Color.White, Color.White);
|
||||
|
||||
foreach (var u in world.SelectActorsInBox(selbox.Value.First, selbox.Value.Second))
|
||||
DrawSelectionBox(u, Color.Yellow, false);
|
||||
}
|
||||
|
||||
public void DrawSelectionBox(Actor selectedUnit, Color c, bool drawHealthBar)
|
||||
{
|
||||
var bounds = selectedUnit.GetBounds(true);
|
||||
|
||||
var xy = new float2(bounds.Left, bounds.Top);
|
||||
var Xy = new float2(bounds.Right, bounds.Top);
|
||||
var xY = new float2(bounds.Left, bounds.Bottom);
|
||||
var XY = new float2(bounds.Right, bounds.Bottom);
|
||||
|
||||
lineRenderer.DrawLine(xy, xy + new float2(4, 0), c, c);
|
||||
lineRenderer.DrawLine(xy, xy + new float2(0, 4), c, c);
|
||||
lineRenderer.DrawLine(Xy, Xy + new float2(-4, 0), c, c);
|
||||
lineRenderer.DrawLine(Xy, Xy + new float2(0, 4), c, c);
|
||||
|
||||
lineRenderer.DrawLine(xY, xY + new float2(4, 0), c, c);
|
||||
lineRenderer.DrawLine(xY, xY + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(XY, XY + new float2(-4, 0), c, c);
|
||||
lineRenderer.DrawLine(XY, XY + new float2(0, -4), c, c);
|
||||
|
||||
if (drawHealthBar)
|
||||
{
|
||||
DrawHealthBar(selectedUnit, xy, Xy);
|
||||
DrawControlGroup(selectedUnit, xy);
|
||||
|
||||
// Only display pips and tags to the owner
|
||||
if (selectedUnit.Owner == world.LocalPlayer)
|
||||
{
|
||||
DrawPips(selectedUnit, xY);
|
||||
DrawTags(selectedUnit, new float2(.5f * (bounds.Left + bounds.Right ), xy.Y));
|
||||
}
|
||||
}
|
||||
|
||||
if (ShowUnitPaths)
|
||||
{
|
||||
var mobile = selectedUnit.traits.GetOrDefault<Mobile>();
|
||||
if (mobile != null)
|
||||
{
|
||||
var path = mobile.GetCurrentPath();
|
||||
var start = selectedUnit.Location;
|
||||
|
||||
foreach (var step in path)
|
||||
{
|
||||
lineRenderer.DrawLine(
|
||||
Game.CellSize * start + new float2(12, 12),
|
||||
Game.CellSize * step + new float2(12, 12),
|
||||
Color.Red, Color.Red);
|
||||
start = step;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawHealthBar(Actor selectedUnit, float2 xy, float2 Xy)
|
||||
{
|
||||
var c = Color.Gray;
|
||||
lineRenderer.DrawLine(xy + new float2(0, -2), xy + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(Xy + new float2(0, -2), Xy + new float2(0, -4), c, c);
|
||||
|
||||
var healthAmount = (float)selectedUnit.Health / selectedUnit.Info.Traits.Get<OwnedActorInfo>().HP;
|
||||
var healthColor = (healthAmount < Rules.General.ConditionRed) ? Color.Red
|
||||
: (healthAmount < Rules.General.ConditionYellow) ? Color.Yellow
|
||||
: Color.LimeGreen;
|
||||
|
||||
var healthColor2 = Color.FromArgb(
|
||||
255,
|
||||
healthColor.R / 2,
|
||||
healthColor.G / 2,
|
||||
healthColor.B / 2);
|
||||
|
||||
var z = float2.Lerp(xy, Xy, healthAmount);
|
||||
|
||||
lineRenderer.DrawLine(z + new float2(0, -4), Xy + new float2(0, -4), c, c);
|
||||
lineRenderer.DrawLine(z + new float2(0, -2), Xy + new float2(0, -2), c, c);
|
||||
|
||||
lineRenderer.DrawLine(xy + new float2(0, -3), z + new float2(0, -3), healthColor, healthColor);
|
||||
lineRenderer.DrawLine(xy + new float2(0, -2), z + new float2(0, -2), healthColor2, healthColor2);
|
||||
lineRenderer.DrawLine(xy + new float2(0, -4), z + new float2(0, -4), healthColor2, healthColor2);
|
||||
}
|
||||
|
||||
// depends on the order of pips in TraitsInterfaces.cs!
|
||||
static readonly string[] pipStrings = { "pip-empty", "pip-green", "pip-yellow", "pip-red", "pip-gray" };
|
||||
static readonly string[] tagStrings = { "", "tag-fake", "tag-primary" };
|
||||
|
||||
void DrawControlGroup(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
var group = Game.controller.selection.GetControlGroupForActor(selectedUnit);
|
||||
if (group == null) return;
|
||||
|
||||
var pipImages = new Animation("pips");
|
||||
pipImages.PlayFetchIndex("groups", () => (int)group);
|
||||
pipImages.Tick();
|
||||
spriteRenderer.DrawSprite(pipImages.Image, basePosition + new float2(-8, 1), "chrome");
|
||||
}
|
||||
|
||||
void DrawPips(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
// If a mod wants to implement a unit with multiple pip sources, then they are placed on multiple rows
|
||||
var pipxyBase = basePosition + new float2(-12, -7); // Correct for the offset in the shp file
|
||||
var pipxyOffset = new float2(0, 0); // Correct for offset due to multiple columns/rows
|
||||
|
||||
foreach (var pips in selectedUnit.traits.WithInterface<IPips>())
|
||||
{
|
||||
foreach (var pip in pips.GetPips(selectedUnit))
|
||||
{
|
||||
var pipImages = new Animation("pips");
|
||||
pipImages.PlayRepeating(pipStrings[(int)pip]);
|
||||
spriteRenderer.DrawSprite(pipImages.Image, pipxyBase + pipxyOffset, "chrome");
|
||||
pipxyOffset += new float2(4, 0);
|
||||
|
||||
if (pipxyOffset.X+5 > selectedUnit.GetBounds(false).Width)
|
||||
{
|
||||
pipxyOffset.X = 0;
|
||||
pipxyOffset.Y -= 4;
|
||||
}
|
||||
}
|
||||
// Increment row
|
||||
pipxyOffset.X = 0;
|
||||
pipxyOffset.Y -= 5;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTags(Actor selectedUnit, float2 basePosition)
|
||||
{
|
||||
// If a mod wants to implement a unit with multiple tags, then they are placed on multiple rows
|
||||
var tagxyBase = basePosition + new float2(-16, 2); // Correct for the offset in the shp file
|
||||
var tagxyOffset = new float2(0, 0); // Correct for offset due to multiple rows
|
||||
|
||||
foreach (var tags in selectedUnit.traits.WithInterface<ITags>())
|
||||
{
|
||||
foreach (var tag in tags.GetTags())
|
||||
{
|
||||
if (tag == TagType.None)
|
||||
continue;
|
||||
|
||||
var tagImages = new Animation("pips");
|
||||
tagImages.PlayRepeating(tagStrings[(int)tag]);
|
||||
spriteRenderer.DrawSprite(tagImages.Image, tagxyBase + tagxyOffset, "chrome");
|
||||
|
||||
// Increment row
|
||||
tagxyOffset.Y += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user