Merge branch 'master' of git://github.com/chrisforbes/OpenRA

This commit is contained in:
Caleb Anderson
2010-01-09 15:08:33 -06:00
101 changed files with 5785 additions and 629 deletions

View File

@@ -46,5 +46,10 @@ namespace OpenRa
if( i.Value is T )
yield return (T)i.Value;
}
public IEnumerator<object> GetEnumerator()
{
return WithInterface<object>().GetEnumerator();
}
}
}

View File

@@ -10,12 +10,16 @@ namespace OpenRa.Game
{
class Actor
{
[Sync]
public readonly TypeDictionary traits = new TypeDictionary();
public readonly UnitInfo Info;
public readonly uint ActorID;
[Sync]
public int2 Location;
[Sync]
public Player Owner;
[Sync]
public int Health;
IActivity currentActivity;
@@ -101,7 +105,7 @@ namespace OpenRa.Game
if (underCursor != null && !underCursor.Info.Selectable)
underCursor = null;
return traits.WithInterface<IOrder>()
return traits.WithInterface<IIssueOrder>()
.Select( x => x.IssueOrder( this, xy, mi, underCursor ) )
.FirstOrDefault( x => x != null );
}

View File

@@ -15,9 +15,9 @@ namespace OpenRa.Game
{
readonly Renderer renderer;
readonly LineRenderer lineRenderer;
readonly Sheet specialBin;
readonly SpriteRenderer chromeRenderer;
readonly Sprite specialBinSprite;
readonly Sheet chromeTexture;
readonly SpriteRenderer rgbaRenderer;
readonly Sprite[] specialBinSprites;
readonly Sprite moneyBinSprite;
readonly Sprite tooltipSprite;
readonly Sprite powerIndicatorSprite;
@@ -39,7 +39,7 @@ namespace OpenRa.Game
readonly Sprite optionsBottomRight;
readonly Sprite optionsBackground;
readonly SpriteRenderer buildPaletteRenderer;
readonly SpriteRenderer shpRenderer;
readonly Animation cantBuild;
readonly Animation ready;
readonly Animation clock;
@@ -47,6 +47,7 @@ namespace OpenRa.Game
readonly List<Pair<Rectangle, Action<bool>>> buttons = new List<Pair<Rectangle, Action<bool>>>();
readonly List<Sprite> digitSprites;
readonly Dictionary<string, Sprite[]> tabSprites;
readonly Dictionary<string, Sprite> spsprites;
readonly Sprite[] shimSprites;
readonly Sprite blank;
@@ -55,23 +56,34 @@ namespace OpenRa.Game
bool hadRadar = false;
bool optionsPressed = false;
const int MinRows = 4;
string currentTab = "Building";
static string[] groups = new string[] { "Building", "Defense", "Infantry", "Vehicle", "Plane", "Ship" };
readonly Dictionary<string, Sprite> sprites;
const int NumClockFrames = 54;
public Chrome(Renderer r)
{
// Positioning of chrome elements
// Build palette
paletteColumns = 4;
paletteOrigin = new int2(Game.viewport.Width - paletteColumns * 64 - 9 - 20, 240 - 9);
paletteOrigin = new int2(Game.viewport.Width - paletteColumns * 64 - 9 - 20, 282);
this.renderer = r;
specialBin = new Sheet(renderer, "specialbin.png");
chromeRenderer = new SpriteRenderer(renderer, true, renderer.RgbaSpriteShader);
chromeTexture = new Sheet(renderer, "specialbin.png");
rgbaRenderer = new SpriteRenderer(renderer, true, renderer.RgbaSpriteShader);
lineRenderer = new LineRenderer(renderer);
buildPaletteRenderer = new SpriteRenderer(renderer, true);
shpRenderer = new SpriteRenderer(renderer, true);
specialBinSprite = new Sprite(specialBin, new Rectangle(0, 0, 32, 192), TextureChannel.Alpha);
moneyBinSprite = new Sprite(specialBin, new Rectangle(512 - 320, 0, 320, 32), TextureChannel.Alpha);
tooltipSprite = new Sprite(specialBin, new Rectangle(0, 288, 272, 136), TextureChannel.Alpha);
specialBinSprites = new []
{
new Sprite(chromeTexture, new Rectangle(0, 0, 32, 51), TextureChannel.Alpha),
new Sprite(chromeTexture, new Rectangle(0, 51, 32, 51 /*144*/), TextureChannel.Alpha),
new Sprite(chromeTexture, new Rectangle(0, 192-39, 32, 39 ), TextureChannel.Alpha),
};
moneyBinSprite = new Sprite(chromeTexture, new Rectangle(512 - 320, 0, 320, 32), TextureChannel.Alpha);
tooltipSprite = new Sprite(chromeTexture, new Rectangle(0, 288, 272, 136), TextureChannel.Alpha);
var powerIndicator = new Animation("power");
powerIndicator.PlayRepeating("power-level-indicator");
@@ -116,10 +128,15 @@ namespace OpenRa.Game
u => u,
u => SpriteSheetBuilder.LoadAllSprites(Rules.UnitInfo[u].Icon ?? (u + "icon"))[0]);
spsprites = Rules.SupportPowerInfo
.ToDictionary(
u => u.Key,
u => SpriteSheetBuilder.LoadAllSprites(u.Value.Image)[0]);
tabSprites = groups.Select(
(g, i) => Pair.New(g,
OpenRa.Game.Graphics.Util.MakeArray(3,
n => new Sprite(specialBin,
n => new Sprite(chromeTexture,
new Rectangle(512 - (n + 1) * 27, 64 + i * 40, 27, 40),
TextureChannel.Alpha))))
.ToDictionary(a => a.First, a => a.Second);
@@ -128,15 +145,15 @@ namespace OpenRa.Game
cantBuild.PlayFetchIndex("idle", () => 0);
digitSprites = Graphics.Util.MakeArray(10, a => a)
.Select(n => new Sprite(specialBin, new Rectangle(32 + 13 * n, 0, 13, 17), TextureChannel.Alpha)).ToList();
.Select(n => new Sprite(chromeTexture, new Rectangle(32 + 13 * n, 0, 13, 17), TextureChannel.Alpha)).ToList();
shimSprites = new[]
{
new Sprite( specialBin, new Rectangle( 0, 192, 9, 10 ), TextureChannel.Alpha ),
new Sprite( specialBin, new Rectangle( 0, 202, 9, 10 ), TextureChannel.Alpha ),
new Sprite( specialBin, new Rectangle( 0, 216, 9, 48 ), TextureChannel.Alpha ),
new Sprite( specialBin, new Rectangle( 11, 192, 64, 10 ), TextureChannel.Alpha ),
new Sprite( specialBin, new Rectangle( 11, 202, 64, 10 ), TextureChannel.Alpha ),
new Sprite( chromeTexture, new Rectangle( 0, 192, 9, 10 ), TextureChannel.Alpha ),
new Sprite( chromeTexture, new Rectangle( 0, 202, 9, 10 ), TextureChannel.Alpha ),
new Sprite( chromeTexture, new Rectangle( 0, 216, 9, 48 ), TextureChannel.Alpha ),
new Sprite( chromeTexture, new Rectangle( 11, 192, 64, 10 ), TextureChannel.Alpha ),
new Sprite( chromeTexture, new Rectangle( 11, 202, 64, 10 ), TextureChannel.Alpha ),
};
ready = new Animation("pips");
@@ -163,15 +180,15 @@ namespace OpenRa.Game
DrawMinimap();
chromeRenderer.DrawSprite(specialBinSprite, float2.Zero, PaletteType.Chrome);
chromeRenderer.DrawSprite(moneyBinSprite, new float2(Game.viewport.Width - 320, 0), PaletteType.Chrome);
rgbaRenderer.DrawSprite(moneyBinSprite, new float2(Game.viewport.Width - 320, 0), PaletteType.Chrome);
DrawMoney();
DrawPower();
chromeRenderer.Flush();
rgbaRenderer.Flush();
DrawButtons();
int paletteHeight = DrawBuildPalette(currentTab);
DrawSupportPowers();
DrawBuildTabs(paletteHeight);
DrawChat();
DrawOptionsMenu();
@@ -186,9 +203,10 @@ namespace OpenRa.Game
if (hasRadar != hadRadar)
Sound.Play((hasRadar) ? "radaron2.aud" : "radardn1.aud");
hadRadar = hasRadar;
var isJammed = false; // todo: MRJ can do this
if (hasRadar)
Game.minimap.Draw(new float2(Game.viewport.Width - 256, 8));
Game.minimap.Draw(new float2(Game.viewport.Width - 247, 10), hasRadar, isJammed);
}
void AddButton(Rectangle r, Action<bool> b) { buttons.Add(Pair.New(r, b)); }
@@ -220,24 +238,20 @@ namespace OpenRa.Game
// Don't let tabs overlap the bevel
if (y > paletteOrigin.Y + paletteHeight - tabHeight - 9 && y < paletteOrigin.Y + paletteHeight)
{
y += tabHeight;
}
// Stick tabs to the edge of the screen
if (y > paletteOrigin.Y + paletteHeight)
{
x = Game.viewport.Width - tabWidth;
}
chromeRenderer.DrawSprite(q.Value[index], new float2(x, y), PaletteType.Chrome);
rgbaRenderer.DrawSprite(q.Value[index], new float2(x, y), PaletteType.Chrome);
buttons.Add(Pair.New(new Rectangle(x, y, tabWidth, tabHeight),
(Action<bool>)(isLmb => currentTab = groupName)));
y += tabHeight;
}
chromeRenderer.Flush();
rgbaRenderer.Flush();
}
void CheckDeadTab( string groupName )
@@ -259,7 +273,7 @@ namespace OpenRa.Game
var x = Game.viewport.Width - 155;
foreach (var d in moneyDigits.Reverse())
{
chromeRenderer.DrawSprite(digitSprites[d - '0'], new float2(x, 6), PaletteType.Chrome);
rgbaRenderer.DrawSprite(digitSprites[d - '0'], new float2(x, 6), PaletteType.Chrome);
x -= 14;
}
}
@@ -270,11 +284,11 @@ namespace OpenRa.Game
void DrawPower()
{
//draw background
float2 powerOrigin = Game.viewport.Location+new float2(Game.viewport.Width - 20, 240 - 9);
float2 powerOrigin = Game.viewport.Location + new float2(Game.viewport.Width - 20, paletteOrigin.Y);
buildPaletteRenderer.DrawSprite(powerLevelTopSprite, powerOrigin, PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(powerLevelBottomSprite, powerOrigin + new float2(0, powerLevelTopSprite.size.Y), PaletteType.Chrome);
buildPaletteRenderer.Flush();
shpRenderer.DrawSprite(powerLevelTopSprite, powerOrigin, PaletteType.Chrome);
shpRenderer.DrawSprite(powerLevelBottomSprite, powerOrigin + new float2(0, powerLevelTopSprite.size.Y), PaletteType.Chrome);
shpRenderer.Flush();
float2 top = powerOrigin + new float2(0, 15);
float2 bottom = powerOrigin + new float2(0, powerLevelTopSprite.size.Y + powerLevelBottomSprite.size.Y) - new float2(0, 50);
@@ -306,43 +320,12 @@ namespace OpenRa.Game
//draw indicator
float2 drainedPosition = new float2(bottom.X + 2, lastPowerDrainedPos.Value + Game.viewport.Location.Y);
buildPaletteRenderer.DrawSprite(powerIndicatorSprite, drainedPosition, PaletteType.Chrome);
buildPaletteRenderer.Flush();
shpRenderer.DrawSprite(powerIndicatorSprite, drainedPosition, PaletteType.Chrome);
shpRenderer.Flush();
}
void DrawButtons()
{
// Chronoshift
Rectangle chronoshiftRect = new Rectangle(6, 14, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
var chronoshiftDrawPos = Game.viewport.Location + new float2(chronoshiftRect.Location);
var hasChronosphere = Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<Chronosphere>());
if (!hasChronosphere)
repairButton.ReplaceAnim("disabled");
else
{
//repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal");
AddButton(chronoshiftRect, isLmb => HandleChronosphereButton());
}
buildPaletteRenderer.DrawSprite(repairButton.Image, chronoshiftDrawPos, PaletteType.Chrome);
// Iron Curtain
Rectangle curtainRect = new Rectangle(6, 14+50, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
var curtainDrawPos = Game.viewport.Location + new float2(curtainRect.Location);
var hasCurtain = Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<IronCurtain>());
if (!hasCurtain)
repairButton.ReplaceAnim("disabled");
else
{
//repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal");
AddButton(curtainRect, isLmb => HandleIronCurtainButton());
}
buildPaletteRenderer.DrawSprite(repairButton.Image, curtainDrawPos, PaletteType.Chrome);
// Repair
Rectangle repairRect = new Rectangle(Game.viewport.Width - 120, 5, repairButton.Image.bounds.Width, repairButton.Image.bounds.Height);
var repairDrawPos = Game.viewport.Location + new float2(repairRect.Location);
@@ -356,7 +339,7 @@ namespace OpenRa.Game
repairButton.ReplaceAnim(Game.controller.orderGenerator is RepairOrderGenerator ? "pressed" : "normal");
AddButton(repairRect, isLmb => Game.controller.ToggleInputMode<RepairOrderGenerator>());
}
buildPaletteRenderer.DrawSprite(repairButton.Image, repairDrawPos, PaletteType.Chrome);
shpRenderer.DrawSprite(repairButton.Image, repairDrawPos, PaletteType.Chrome);
// Sell
Rectangle sellRect = new Rectangle(Game.viewport.Width - 80, 5,
@@ -367,8 +350,8 @@ namespace OpenRa.Game
sellButton.ReplaceAnim(Game.controller.orderGenerator is SellOrderGenerator ? "pressed" : "normal");
AddButton(sellRect, isLmb => Game.controller.ToggleInputMode<SellOrderGenerator>());
buildPaletteRenderer.DrawSprite(sellButton.Image, sellDrawPos, PaletteType.Chrome);
buildPaletteRenderer.Flush();
shpRenderer.DrawSprite(sellButton.Image, sellDrawPos, PaletteType.Chrome);
shpRenderer.Flush();
if (Game.Settings.PowerDownBuildings)
{
@@ -381,12 +364,12 @@ namespace OpenRa.Game
pwrdownButton.ReplaceAnim(Game.controller.orderGenerator is PowerDownOrderGenerator ? "pressed" : "normal");
AddButton(pwrdownRect, isLmb => Game.controller.ToggleInputMode<PowerDownOrderGenerator>());
buildPaletteRenderer.DrawSprite(pwrdownButton.Image, pwrdownDrawPos, PaletteType.Chrome);
shpRenderer.DrawSprite(pwrdownButton.Image, pwrdownDrawPos, PaletteType.Chrome);
}
buildPaletteRenderer.Flush();
shpRenderer.Flush();
//Options
Rectangle optionsRect = new Rectangle(0 + 40,0, optionsButton.Image.bounds.Width,
Rectangle optionsRect = new Rectangle(0,0, optionsButton.Image.bounds.Width,
optionsButton.Image.bounds.Height);
var optionsDrawPos = Game.viewport.Location + new float2(optionsRect.Location);
@@ -394,8 +377,8 @@ namespace OpenRa.Game
optionsButton.ReplaceAnim(optionsPressed ? "left-pressed" : "left-normal");
AddButton(optionsRect, isLmb => optionsPressed = !optionsPressed);
buildPaletteRenderer.DrawSprite(optionsButton.Image, optionsDrawPos, PaletteType.Chrome);
buildPaletteRenderer.Flush();
shpRenderer.DrawSprite(optionsButton.Image, optionsDrawPos, PaletteType.Chrome);
shpRenderer.Flush();
renderer.DrawText("Options", new int2(80, -2) , Color.White);
}
@@ -413,37 +396,25 @@ namespace OpenRa.Game
var backgroundDrawPos = menuDrawPos + new float2( (width - optionsBackground.bounds.Width)/2, (height - optionsBackground.bounds.Height)/2);
//draw background
buildPaletteRenderer.DrawSprite(optionsBackground, backgroundDrawPos, PaletteType.Chrome);
shpRenderer.DrawSprite(optionsBackground, backgroundDrawPos, PaletteType.Chrome);
//draw borders
buildPaletteRenderer.DrawSprite(optionsTopLeft, menuDrawPos, PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsLeft, menuDrawPos + new float2(0, optionsTopLeft.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsBottomLeft, menuDrawPos + new float2(0, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height), PaletteType.Chrome);
shpRenderer.DrawSprite(optionsTopLeft, menuDrawPos, PaletteType.Chrome);
shpRenderer.DrawSprite(optionsLeft, menuDrawPos + new float2(0, optionsTopLeft.bounds.Height), PaletteType.Chrome);
shpRenderer.DrawSprite(optionsBottomLeft, menuDrawPos + new float2(0, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsTop, menuDrawPos + new float2(optionsTopLeft.bounds.Width, 0), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsTopRight, menuDrawPos + new float2(optionsTopLeft.bounds.Width + optionsTop.bounds.Width, 0), PaletteType.Chrome);
shpRenderer.DrawSprite(optionsTop, menuDrawPos + new float2(optionsTopLeft.bounds.Width, 0), PaletteType.Chrome);
shpRenderer.DrawSprite(optionsTopRight, menuDrawPos + new float2(optionsTopLeft.bounds.Width + optionsTop.bounds.Width, 0), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsBottom, menuDrawPos + new float2(optionsTopLeft.bounds.Width, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height +adjust), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsBottomRight, menuDrawPos + new float2(optionsBottomLeft.bounds.Width + optionsBottom.bounds.Width, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height), PaletteType.Chrome);
shpRenderer.DrawSprite(optionsBottom, menuDrawPos + new float2(optionsTopLeft.bounds.Width, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height +adjust), PaletteType.Chrome);
shpRenderer.DrawSprite(optionsBottomRight, menuDrawPos + new float2(optionsBottomLeft.bounds.Width + optionsBottom.bounds.Width, optionsTopLeft.bounds.Height + optionsLeft.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.DrawSprite(optionsRight, menuDrawPos + new float2(optionsTopLeft.bounds.Width + optionsTop.bounds.Width + adjust + 1, optionsTopRight.bounds.Height), PaletteType.Chrome);
shpRenderer.DrawSprite(optionsRight, menuDrawPos + new float2(optionsTopLeft.bounds.Width + optionsTop.bounds.Width + adjust + 1, optionsTopRight.bounds.Height), PaletteType.Chrome);
buildPaletteRenderer.Flush();
shpRenderer.Flush();
}
}
void HandleChronosphereButton()
{
if (Game.controller.ToggleInputMode<ChronosphereSelectOrderGenerator>())
Sound.Play("slcttgt1.aud");
}
void HandleIronCurtainButton()
{
if (Game.controller.ToggleInputMode<IronCurtainOrderGenerator>())
Sound.Play("slcttgt1.aud");
}
void DrawChat()
{
var chatpos = new int2(400, Game.viewport.Height - 20);
@@ -464,22 +435,6 @@ namespace OpenRa.Game
renderer.DrawText(line.b, p, line.a);
renderer.DrawText(line.c, p + new int2(size.X + 10, 0), Color.White);
}
string currentTab = "Building";
static string[] groups = new string[] { "Building", "Defense", "Infantry", "Vehicle", "Plane", "Ship" };
Dictionary<string, Sprite> sprites;
const int NumClockFrames = 54;
Func<int> ClockAnimFrame(string group)
{
return () =>
{
var queue = Game.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
var producing = queue.CurrentItem( group );
if (producing == null) return 0;
return (producing.TotalTime - producing.RemainingTime) * NumClockFrames / producing.TotalTime;
};
}
// Return an int telling us the y coordinate at the bottom of the palette
int DrawBuildPalette(string queueName)
@@ -511,7 +466,7 @@ namespace OpenRa.Game
var drawPos = Game.viewport.Location + new float2(rect.Location);
var isBuildingSomething = queue.CurrentItem(queueName) != null;
buildPaletteRenderer.DrawSprite(sprites[item], drawPos, PaletteType.Chrome);
shpRenderer.DrawSprite(sprites[item], drawPos, PaletteType.Chrome);
var firstOfThis = queue.AllItems(queueName).FirstOrDefault(a => a.Item == item);
@@ -527,7 +482,7 @@ namespace OpenRa.Game
* NumClockFrames / firstOfThis.TotalTime);
clock.Tick();
buildPaletteRenderer.DrawSprite(clock.Image, drawPos, PaletteType.Chrome);
shpRenderer.DrawSprite(clock.Image, drawPos, PaletteType.Chrome);
if (firstOfThis.Done)
{
@@ -567,28 +522,28 @@ namespace OpenRa.Game
{
var rect = new Rectangle(origin.X + x * 64, origin.Y + 48 * y, 64, 48);
var drawPos = Game.viewport.Location + new float2(rect.Location);
buildPaletteRenderer.DrawSprite(blank, drawPos, PaletteType.Chrome);
shpRenderer.DrawSprite(blank, drawPos, PaletteType.Chrome);
AddButton(rect, _ => { });
if (++x == columns) { x = 0; y++; }
}
foreach (var ob in overlayBits)
buildPaletteRenderer.DrawSprite(ob.First, ob.Second, PaletteType.Chrome);
shpRenderer.DrawSprite(ob.First, ob.Second, PaletteType.Chrome);
buildPaletteRenderer.Flush();
shpRenderer.Flush();
for (var j = 0; j < y; j++)
chromeRenderer.DrawSprite(shimSprites[2], new float2(origin.X - 9, origin.Y + 48 * j), PaletteType.Chrome);
rgbaRenderer.DrawSprite(shimSprites[2], new float2(origin.X - 9, origin.Y + 48 * j), PaletteType.Chrome);
chromeRenderer.DrawSprite(shimSprites[0], new float2(origin.X - 9, origin.Y - 9), PaletteType.Chrome);
chromeRenderer.DrawSprite(shimSprites[1], new float2(origin.X - 9, origin.Y - 1 + 48 * y), PaletteType.Chrome);
rgbaRenderer.DrawSprite(shimSprites[0], new float2(origin.X - 9, origin.Y - 9), PaletteType.Chrome);
rgbaRenderer.DrawSprite(shimSprites[1], new float2(origin.X - 9, origin.Y - 1 + 48 * y), PaletteType.Chrome);
for (var i = 0; i < columns; i++)
{
chromeRenderer.DrawSprite(shimSprites[3], new float2(origin.X + 64 * i, origin.Y - 9), PaletteType.Chrome);
chromeRenderer.DrawSprite(shimSprites[4], new float2(origin.X + 64 * i, origin.Y - 1 + 48 * y), PaletteType.Chrome);
rgbaRenderer.DrawSprite(shimSprites[3], new float2(origin.X + 64 * i, origin.Y - 9), PaletteType.Chrome);
rgbaRenderer.DrawSprite(shimSprites[4], new float2(origin.X + 64 * i, origin.Y - 1 + 48 * y), PaletteType.Chrome);
}
chromeRenderer.Flush();
rgbaRenderer.Flush();
if (tooltipItem != null)
DrawProductionTooltip(tooltipItem, new int2(Game.viewport.Width, origin.Y + y * 48 + 9)/*tooltipPos*/);
@@ -682,8 +637,8 @@ namespace OpenRa.Game
void DrawProductionTooltip(string unit, int2 pos)
{
var p = pos.ToFloat2() - new float2(tooltipSprite.size.X, 0);
chromeRenderer.DrawSprite(tooltipSprite, p, PaletteType.Chrome);
chromeRenderer.Flush();
rgbaRenderer.DrawSprite(tooltipSprite, p, PaletteType.Chrome);
rgbaRenderer.Flush();
var info = Rules.UnitInfo[unit];
@@ -717,5 +672,100 @@ namespace OpenRa.Game
renderer.DrawText(info.LongDesc.Replace( "\\n", "\n" ), p.ToInt2(), Color.White);
}
}
void DrawSupportPowers()
{
var numPowers = Game.LocalPlayer.SupportPowers.Values
.Where(a => a.IsAvailable).Count();
if (numPowers == 0) return;
rgbaRenderer.DrawSprite(specialBinSprites[0], new float2(0,14), PaletteType.Chrome);
for (var i = 1; i < numPowers; i++)
rgbaRenderer.DrawSprite(specialBinSprites[1], new float2(0, 14 + i * 51), PaletteType.Chrome);
rgbaRenderer.DrawSprite(specialBinSprites[2], new float2(0, 14 + numPowers * 51), PaletteType.Chrome);
rgbaRenderer.Flush();
var y = 24;
string tooltipItem = null;
int2 tooltipPos = int2.Zero;
foreach (var sp in Game.LocalPlayer.SupportPowers)
{
var image = spsprites[sp.Key];
if (sp.Value.IsAvailable)
{
var drawPos = Game.viewport.Location + new float2(5, y);
shpRenderer.DrawSprite(image, drawPos, PaletteType.Chrome);
clock.PlayFetchIndex("idle",
() => (sp.Value.TotalTime - sp.Value.RemainingTime)
* NumClockFrames / sp.Value.TotalTime);
clock.Tick();
shpRenderer.DrawSprite(clock.Image, drawPos, PaletteType.Chrome);
var rect = new Rectangle(5, y, 64, 48);
if (sp.Value.IsDone)
{
ready.Play("ready");
shpRenderer.DrawSprite(ready.Image,
drawPos + new float2((64 - ready.Image.size.X) / 2, 2),
PaletteType.Chrome);
AddButton(rect, HandleSupportPower( sp.Value ));
}
if (rect.Contains(lastMousePos.ToPoint()))
{
tooltipItem = sp.Key;
tooltipPos = drawPos.ToInt2() + new int2(72, 0) - Game.viewport.Location.ToInt2();
}
y += 51;
}
}
shpRenderer.Flush();
if (tooltipItem != null)
DrawSupportPowerTooltip(tooltipItem, tooltipPos);
}
Action<bool> HandleSupportPower(SupportPower sp)
{
return b => { if (b) sp.Activate(); };
}
string FormatTime(int ticks)
{
var seconds = ticks / 25;
var minutes = seconds / 60;
return "{0:D2}:{1:D2}".F(minutes, seconds % 60);
}
void DrawSupportPowerTooltip(string sp, int2 pos)
{
rgbaRenderer.DrawSprite(tooltipSprite, pos, PaletteType.Chrome);
rgbaRenderer.Flush();
var info = Rules.SupportPowerInfo[sp];
pos += new int2(5, 5);
renderer.DrawText2(info.Description, pos, Color.White);
var timer = "Charge Time: {0}".F(FormatTime(Game.LocalPlayer.SupportPowers[sp].RemainingTime));
DrawRightAligned(timer, pos + new int2((int)tooltipSprite.size.X - 10, 0), Color.White);
if (info.LongDesc != null)
{
pos += new int2(0, 25);
renderer.DrawText(info.LongDesc.Replace("\\n", "\n"), pos, Color.White);
}
}
}
}

View File

@@ -147,14 +147,24 @@ namespace OpenRa.Game
public Cursor ChooseCursor()
{
var mi = new MouseInput
{
Location = (Game.CellSize * MousePosition - Game.viewport.Location).ToInt2(),
Button = MouseButton.Right,
Modifiers = GetModifierKeys(),
};
int sync = Game.world.SyncHash();
return orderGenerator.GetCursor(MousePosition.ToInt2(), mi);
try
{
var mi = new MouseInput
{
Location = ( Game.CellSize * MousePosition - Game.viewport.Location ).ToInt2(),
Button = MouseButton.Right,
Modifiers = GetModifierKeys(),
};
return orderGenerator.GetCursor( MousePosition.ToInt2(), mi );
}
finally
{
if( sync != Game.world.SyncHash() )
throw new InvalidOperationException( "Desync in Controller.ChooseCursor" );
}
}
Cache<int, List<Actor>> controlGroups = new Cache<int, List<Actor>>(_ => new List<Actor>());

0
OpenRa.Game/Effects/Bullet.cs Normal file → Executable file
View File

0
OpenRa.Game/Effects/Corpse.cs Normal file → Executable file
View File

0
OpenRa.Game/Effects/DelayedAction.cs Normal file → Executable file
View File

0
OpenRa.Game/Effects/Explosion.cs Normal file → Executable file
View File

0
OpenRa.Game/Effects/FlashTarget.cs Normal file → Executable file
View File

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects
{
class GpsSatellite : IEffect
{
readonly float heightPerTick = 10;
float2 offset;
Animation anim = new Animation("sputnik");
public GpsSatellite(float2 offset)
{
this.offset = offset;
anim.PlayRepeating("idle");
}
public void Tick()
{
anim.Tick();
offset.Y -= heightPerTick;
if (offset.Y < 0)
Game.world.AddFrameEndTask(w => w.Remove(this));
}
public IEnumerable<Renderable> Render()
{
yield return new Renderable(anim.Image,offset, PaletteType.Gold);
}
}
}

0
OpenRa.Game/Effects/IEffect.cs Normal file → Executable file
View File

0
OpenRa.Game/Effects/InvulnEffect.cs Normal file → Executable file
View File

0
OpenRa.Game/Effects/Missile.cs Normal file → Executable file
View File

0
OpenRa.Game/Effects/MoveFlash.cs Normal file → Executable file
View File

20
OpenRa.Game/Effects/PowerDownIndicator.cs Normal file → Executable file
View File

@@ -9,7 +9,10 @@ namespace OpenRa.Game.Effects
Actor a;
Building b;
Animation anim = new Animation("powerdown");
bool removeNextFrame = false;
bool indicatorState = true;
int stateTicks = 0;
public PowerDownIndicator(Actor a)
{
this.a = a;
@@ -19,8 +22,19 @@ namespace OpenRa.Game.Effects
public void Tick()
{
if (!b.Disabled || a.IsDead)
if (removeNextFrame == true)
Game.world.AddFrameEndTask(w => w.Remove(this));
// Fix off-by one frame bug with undisabling causing low-power
if (!b.Disabled || a.IsDead)
removeNextFrame = true;
// Flash power icon
if (++stateTicks == 15)
{
stateTicks = 0;
indicatorState = !indicatorState;
}
}
public IEnumerable<Renderable> Render()
@@ -28,7 +42,7 @@ namespace OpenRa.Game.Effects
foreach (var r in a.Render())
yield return r.WithPalette(PaletteType.Disabled);
if (b.ManuallyDisabled)
if (b.ManuallyDisabled && indicatorState)
yield return new Renderable(anim.Image,
a.CenterLocation - .5f * anim.Image.size, PaletteType.Chrome);
}

0
OpenRa.Game/Effects/RepairIndicator.cs Normal file → Executable file
View File

View File

@@ -0,0 +1,37 @@
using System.Collections.Generic;
using OpenRa.Game.Graphics;
using OpenRa.Game.Traits;
namespace OpenRa.Game.Effects
{
class SatelliteLaunch : IEffect
{
int frame = 0;
Actor a;
Animation doors = new Animation("atek");
float2 doorOffset = new float2(-4,0);
public SatelliteLaunch(Actor a)
{
this.a = a;
doors.PlayThen("active",
() => Game.world.AddFrameEndTask(w => w.Remove(this)));
}
public void Tick()
{
doors.Tick();
if (++frame == 19)
{
Game.world.AddFrameEndTask(w => w.Add(new GpsSatellite(a.CenterLocation - .5f * doors.Image.size + doorOffset)));
}
}
public IEnumerable<Renderable> Render()
{
yield return new Renderable(doors.Image,
a.CenterLocation - .5f * doors.Image.size + doorOffset, PaletteType.Gold);
}
}
}

0
OpenRa.Game/Effects/Smoke.cs Normal file → Executable file
View File

View File

@@ -1,169 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="OpenRa.Game.Game">
<Position X="9.5" Y="9.25" Width="2.25" />
<Members>
<Method Name="FindUnits" Hidden="true" />
<Field Name="lastTime" Hidden="true" />
<Method Name="LoadMapActors" Hidden="true" />
<Field Name="localPlayerIndex" Hidden="true" />
<Field Name="oreFrequency" Hidden="true" />
<Field Name="oreTicks" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAaAkDQAABJAAQEEBEECEgAQQUBAAAAAIYAKBCAAwiA=</HashCode>
<FileName>Game.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="world" />
<Field Name="viewport" />
<Field Name="controller" />
<Field Name="PathFinder" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.Controller">
<Position X="6.5" Y="10.75" Width="1.75" />
<Members>
<Method Name="ApplyOrders" Hidden="true" />
<Method Name="CombineSelection" Hidden="true" />
<Field Name="controlGroups" Hidden="true" />
<Method Name="CursorForOrderString" Hidden="true" />
<Field Name="dragEnd" Hidden="true" />
<Field Name="dragStart" Hidden="true" />
<Field Name="GetModifierKeys" Hidden="true" />
<Field Name="recentOrders" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAACAACoAAAAAAAAAAQDEgQAABAAABAAAAAAKAACCAA=</HashCode>
<FileName>Controller.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="orderGenerator" />
</ShowAsAssociation>
<Lollipop Position="0.2" />
</Class>
<Class Name="OpenRa.Game.Graphics.Viewport">
<Position X="13.5" Y="10.25" Width="1.75" />
<Members>
<Field Name="cursorFrame" Hidden="true" />
<Field Name="cursorRenderer" Hidden="true" />
<Field Name="dragRegion" Hidden="true" />
<Field Name="mousePos" Hidden="true" />
<Field Name="renderer" Hidden="true" />
<Field Name="screenSize" Hidden="true" />
<Field Name="scrollPosition" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAIAAAAABAAACABCAAYAEEAAAABAAAAAAAAgAEEIwBE=</HashCode>
<FileName>Graphics\Viewport.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.World">
<Position X="4.75" Y="17.25" Width="2" />
<Members>
<Field Name="actors" Hidden="true" />
<Field Name="effects" Hidden="true" />
<Field Name="frameEndActions" Hidden="true" />
<Field Name="nextAID" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAIAACABAAABgAAAAYQABAAEAAAAAAAAAAAAAAAAQBA=</HashCode>
<FileName>World.cs</FileName>
</TypeIdentifier>
<ShowAsCollectionAssociation>
<Property Name="Actors" />
</ShowAsCollectionAssociation>
</Class>
<Class Name="OpenRa.Game.Actor">
<Position X="9.5" Y="16.75" Width="1.75" />
<Members>
<Field Name="currentActivity" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AgEACACAAAAAAAAAAQIAEIAkAQQAAAAAABAgAEAAQgA=</HashCode>
<FileName>Actor.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="Owner" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.GameRules.UnitInfo" Collapsed="true">
<Position X="11" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>ACIAAAKAAJAgwiAAgAAAgFQAJAhQAHAAGCACAADIRAA=</HashCode>
<FileName>GameRules\UnitInfo.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.Player">
<Position X="11.75" Y="16.75" Width="2.25" />
<Members>
<Field Name="displayCashDeltaPerFrame" Hidden="true" />
<Method Name="GiveAdvice" Hidden="true" />
<Method Name="UpdatePower" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>QEEEAAQAAAIAQQAACAMAACCAAAAAAA0gCAEAAQABQAA=</HashCode>
<FileName>Player.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.GameRules.MobileInfo" Collapsed="true">
<Position X="9.75" Y="3.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAQAAAAAAAAAAAABAQAAAAAAAAAAAAAAAAg=</HashCode>
<FileName>GameRules\UnitInfo.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.GameRules.BuildingInfo" Collapsed="true">
<Position X="13.25" Y="3.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAJQAAAIAAAAgAAACAAAABIAAAICAAABAAAAQAAAAgA=</HashCode>
<FileName>GameRules\UnitInfo.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.GameRules.InfantryInfo" Collapsed="true">
<Position X="8.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAEEAAAAABIAAAAAAAAAAAAAAAACAAAQA=</HashCode>
<FileName>GameRules\UnitInfo.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.GameRules.VehicleInfo" Collapsed="true">
<Position X="11" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAEAAAAAAAAAAAAAEAAAAAAAAAAAAAAA=</HashCode>
<FileName>GameRules\UnitInfo.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.GameRules.ActorInfo" Collapsed="true">
<Position X="11" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>GameRules\ActorInfo.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.PathFinder">
<Position X="9.25" Y="6.25" Width="1.75" />
<Members>
<Method Name="AvoidUnitsNear" Hidden="true" />
<Method Name="CheckSanePath" Hidden="true" />
<Method Name="CheckSanePath2" Hidden="true" />
<Method Name="FindBidiPath" Hidden="true" />
<Method Name="IsBlocked" Hidden="true" />
<Method Name="MakeBidiPath" Hidden="true" />
<Method Name="MakePath" Hidden="true" />
<Field Name="passableCost" Hidden="true" />
</Members>
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAgAACAAAICAAgAEoAAMAAAAAAAAgA=</HashCode>
<FileName>PathFinder.cs</FileName>
</TypeIdentifier>
</Class>
<Interface Name="OpenRa.Game.IOrderGenerator">
<Position X="3.5" Y="12" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAQAA=</HashCode>
<FileName>IOrderGenerator.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -84,11 +84,12 @@ namespace OpenRa.Game
Rules.Map.InitOreDensity();
worldRenderer = new WorldRenderer(renderer);
minimap = new Minimap(renderer);
SequenceProvider.Initialize(usingAftermath);
viewport = new Viewport(clientSize, Rules.Map.Offset, Rules.Map.Offset + Rules.Map.Size, renderer);
minimap = new Minimap(renderer);
BuildingInfluence = new BuildingInfluenceMap();
UnitInfluence = new UnitInfluenceMap();

View File

@@ -5,10 +5,11 @@ using System.Text;
using OpenRa.FileFormats;
using OpenRa.Game.Graphics;
using IjwFramework.Types;
using System.Collections;
namespace OpenRa.Game.GameRules
{
class InfoLoader<T>
class InfoLoader<T> : IEnumerable<KeyValuePair<string, T>>
{
readonly Dictionary<string, T> infos = new Dictionary<string, T>();
@@ -28,9 +29,7 @@ namespace OpenRa.Game.GameRules
get { return infos[name.ToLowerInvariant()]; }
}
public IEnumerator<KeyValuePair<string, T>> GetEnumerator()
{
return infos.GetEnumerator();
}
public IEnumerator<KeyValuePair<string, T>> GetEnumerator() { return infos.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return infos.GetEnumerator(); }
}
}

View File

@@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.GameRules
{
public class SupportPowerInfo
{
public readonly bool Powered = true;
public readonly bool OneShot = false;
public readonly int ChargeTime = 0;
public readonly float ChargeTime = 0;
public readonly string Image;
public readonly string Description = "";
public readonly string LongDesc = "";
public readonly string[] Prerequisite = { };
public readonly int TechLevel = -1;
public readonly bool GivenAuto = true;
public readonly string Impl = null;
}
}

View File

@@ -43,7 +43,7 @@ namespace OpenRa.Game.GameRules
return false;
return true;
}
}
public IEnumerable<string> BuildableItems( Player player, params string[] categories )
{

View File

@@ -1,131 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="OpenRa.Game.Graphics.Animation">
<Position X="15.75" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQCgACAAAAAAAAAAAAAAAAAAAAEABAEgAAAAQQIQAA=</HashCode>
<FileName>Graphics\Animation.cs</FileName>
</TypeIdentifier>
<ShowAsCollectionAssociation>
<Property Name="Images" />
</ShowAsCollectionAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.Viewport">
<Position X="4.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAQAABAAAgAAAAIYAAEAAAABCAAAAAABgAAAAgAE=</HashCode>
<FileName>Graphics\Viewport.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="renderer" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.HardwarePalette">
<Position X="9.75" Y="10" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
<FileName>Graphics\HardwarePalette.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.Graphics.Region" Collapsed="true">
<Position X="18.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AIQAAAAAAAAAggAABAIAIAQCAAAAAGAAAAAAAAAQAAA=</HashCode>
<FileName>Graphics\Region.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.Graphics.Renderer">
<Position X="4.25" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>QACAEAAGAAAAAgMAAAAAAAAAAAAAAAAAAAAAAEAAAAA=</HashCode>
<FileName>Graphics\Renderer.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="OpenRa.Game.Graphics.Sheet">
<Position X="9.75" Y="6" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAACAgAAACAgAAAAIAAAAAgAAAAIAAAAggAA=</HashCode>
<FileName>Graphics\Sheet.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="renderer" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.SheetBuilder">
<Position X="1.25" Y="6" Width="1.5" />
<TypeIdentifier>
<HashCode>AQIACAAAAAAAIQAAAAAAAAAAgAAAAIAAAEAAAAACgAA=</HashCode>
<FileName>Graphics\SheetBuilder.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="renderer" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.Sprite">
<Position X="12.75" Y="6.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAQAAIAAAAIAAAAAAAAAAAAABAAACAAAEAgA=</HashCode>
<FileName>Graphics\Sprite.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="sheet" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.SpriteRenderer">
<Position X="6.75" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAQQAAAAECAAAAAAAAAAAAAABAQABAAAAAAAACIwAQ=</HashCode>
<FileName>Graphics\SpriteRenderer.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="currentSheet" />
<Field Name="renderer" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.SpriteSheetBuilder">
<Position X="12.75" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAACAAAA=</HashCode>
<FileName>Graphics\SpriteSheetBuilder.cs</FileName>
</TypeIdentifier>
<ShowAsCollectionAssociation>
<Field Name="sprites" />
</ShowAsCollectionAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.TerrainRenderer">
<Position X="7" Y="2.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AACQEAAAAAAAAgAAAAAACAAAABgAAAAAAAAAAAAAgAA=</HashCode>
<FileName>Graphics\TerrainRenderer.cs</FileName>
</TypeIdentifier>
<ShowAsAssociation>
<Field Name="renderer" />
<Field Name="terrainSheet" />
</ShowAsAssociation>
</Class>
<Class Name="OpenRa.Game.Graphics.UnitSheetBuilder">
<Position X="15.75" Y="6" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAgAAAAAAAAAAAAAAAAQAAAAAAAQAAAACAAAA=</HashCode>
<FileName>Graphics\UnitSheetBuilder.cs</FileName>
</TypeIdentifier>
<ShowAsCollectionAssociation>
<Field Name="sprites" />
</ShowAsCollectionAssociation>
</Class>
<Struct Name="OpenRa.Game.Graphics.Vertex" Collapsed="true">
<Position X="18.25" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAgAAACAAFJgAQAAAAA=</HashCode>
<FileName>Graphics\Vertex.cs</FileName>
</TypeIdentifier>
</Struct>
<Enum Name="OpenRa.Game.Graphics.TextureChannel" Collapsed="true">
<Position X="18.25" Y="3" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAgAAAAAAAAAAAAAAABAAAAAAABAAAAA=</HashCode>
<FileName>Graphics\Sprite.cs</FileName>
</TypeIdentifier>
</Enum>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -2,32 +2,47 @@
using System.Linq;
using OpenRa.Game.Traits;
using OpenRa.FileFormats;
using System.Drawing.Imaging;
namespace OpenRa.Game.Graphics
{
class Minimap
{
Sheet sheet;
SpriteRenderer spriteRenderer;
SpriteRenderer rgbaRenderer;
SpriteRenderer shpRenderer;
Sprite sprite;
Bitmap terrain, oreLayer;
Animation radarAnim, alliesAnim, sovietAnim;
public void Tick() { }
public Minimap(Renderer r)
{
sheet = new Sheet(r, new Size(128, 128));
spriteRenderer = new SpriteRenderer(r, true, r.RgbaSpriteShader);
shpRenderer = new SpriteRenderer(r, true);
rgbaRenderer = new SpriteRenderer(r, true, r.RgbaSpriteShader);
sprite = new Sprite(sheet, new Rectangle(0, 0, 128, 128), TextureChannel.Alpha);
sovietAnim = new Animation("ussrradr");
sovietAnim.PlayRepeating("idle");
alliesAnim = new Animation("natoradr");
alliesAnim.PlayRepeating("idle");
radarAnim = Game.LocalPlayer.Race == Race.Allies ? alliesAnim : sovietAnim;
}
// todo: extract these from the palette
Color[] terrainTypeColors;
public void InvalidateOre() { oreLayer = null; }
public void Update()
{
radarAnim = Game.LocalPlayer.Race == Race.Allies ? alliesAnim : sovietAnim;
radarAnim.Tick();
if (!Game.world.Actors.Any(a => a.Owner == Game.LocalPlayer && a.traits.Contains<ProvidesRadar>()))
return;
if (terrainTypeColors == null)
{
var pal = new Palette(FileSystem.Open(Rules.Map.Theater + ".pal"));
@@ -65,25 +80,59 @@ namespace OpenRa.Game.Graphics
}
var bitmap = new Bitmap(oreLayer);
for( var y = 0; y < 128; y++ )
for (var x = 0; x < 128; x++)
var bitmapData = bitmap.LockBits(new Rectangle( 0,0,bitmap.Width, bitmap.Height ),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
int* c = (int *)bitmapData.Scan0;
for (var y = 0; y < 128; y++)
for (var x = 0; x < 128; x++)
{
var b = Game.BuildingInfluence.GetBuildingAt(new int2(x, y));
if (b != null)
*(c + (y * bitmapData.Stride >> 2) + x) =
(b.Owner != null ? Chat.paletteColors[(int)b.Owner.Palette] : terrainTypeColors[4]).ToArgb();
}
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<Unit>()))
*(c + (a.Location.Y * bitmapData.Stride >> 2) + a.Location.X) = Chat.paletteColors[(int)a.Owner.Palette].ToArgb();
unchecked
{
var b = Game.BuildingInfluence.GetBuildingAt(new int2(x, y));
if (b != null)
bitmap.SetPixel(x, y, b.Owner != null ? Chat.paletteColors[(int)b.Owner.Palette] : terrainTypeColors[4]);
for (var y = 0; y < 128; y++)
for (var x = 0; x < 128; x++)
if (!Game.LocalPlayer.Shroud.IsExplored(new int2(x, y)))
*(c + (y * bitmapData.Stride >> 2) + x) = (int)0xff000000;
}
}
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<Unit>()))
bitmap.SetPixel(a.Location.X, a.Location.Y, Chat.paletteColors[(int)a.Owner.Palette]);
bitmap.UnlockBits(bitmapData);
sheet.Texture.SetData(bitmap);
}
public void Draw(float2 pos)
public void Draw(float2 pos, bool hasRadar, bool isJammed)
{
spriteRenderer.DrawSprite(sprite, pos, PaletteType.Chrome, new float2(256,256));
spriteRenderer.Flush();
if (hasRadar && radarAnim.CurrentSequence.Name == "idle")
radarAnim.PlayThen("open", () => radarAnim.PlayRepeating("active"));
if (hasRadar && radarAnim.CurrentSequence.Name == "no-power")
radarAnim.PlayBackwardsThen("close", () => radarAnim.PlayRepeating("active"));
if (!hasRadar && radarAnim.CurrentSequence.Name == "active")
radarAnim.PlayThen("close", () => radarAnim.PlayRepeating("no-power"));
if (isJammed && radarAnim.CurrentSequence.Name == "active")
radarAnim.PlayRepeating("jammed");
if (!isJammed && radarAnim.CurrentSequence.Name == "jammed")
radarAnim.PlayRepeating("active");
shpRenderer.DrawSprite(radarAnim.Image, pos + Game.viewport.Location - new float2( 290-256,0), PaletteType.Chrome, new float2(290, 272));
shpRenderer.Flush();
if (radarAnim.CurrentSequence.Name == "active")
{
rgbaRenderer.DrawSprite(sprite, pos - new float2((290-256)/2, -5), PaletteType.Chrome, new float2(256, 256));
rgbaRenderer.Flush();
}
}
}
}

View File

@@ -95,6 +95,8 @@ namespace OpenRa.Game
void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e)
{
int sync = Game.world.SyncHash();
Game.viewport.DispatchMouseInput(
new MouseInput
{
@@ -103,6 +105,9 @@ namespace OpenRa.Game
Location = new int2(e.Location),
Modifiers = (Modifiers)(int)ModifierKeys,
});
if( sync != Game.world.SyncHash() )
throw new InvalidOperationException( "Desync in DispatchMouseInput" );
}
protected override void OnMouseDown(MouseEventArgs e)
@@ -136,6 +141,8 @@ namespace OpenRa.Game
{
base.OnKeyDown(e);
int sync = Game.world.SyncHash();
/* hack hack hack */
if (e.KeyCode == Keys.F8 && !Game.orderManager.GameStarted)
{
@@ -156,16 +163,24 @@ namespace OpenRa.Game
if (!Game.chat.isChatting)
if (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9)
Game.controller.DoControlGroup( (int)e.KeyCode - (int)Keys.D0, (Modifiers)(int)e.Modifiers );
if( sync != Game.world.SyncHash() )
throw new InvalidOperationException( "Desync in OnKeyDown" );
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
int sync = Game.world.SyncHash();
if (e.KeyChar == '\r')
Game.chat.Toggle();
else if (Game.chat.isChatting)
Game.chat.TypeChar(e.KeyChar);
if( sync != Game.world.SyncHash() )
throw new InvalidOperationException( "Desync in OnKeyPress" );
}
}

View File

@@ -83,10 +83,12 @@
<Compile Include="Effects\Corpse.cs" />
<Compile Include="Effects\DelayedAction.cs" />
<Compile Include="Effects\FlashTarget.cs" />
<Compile Include="Effects\GpsSatellite.cs" />
<Compile Include="Effects\InvulnEffect.cs" />
<Compile Include="Effects\MoveFlash.cs" />
<Compile Include="Effects\PowerDownIndicator.cs" />
<Compile Include="Effects\RepairIndicator.cs" />
<Compile Include="Effects\SatelliteLaunch.cs" />
<Compile Include="Effects\Smoke.cs" />
<Compile Include="Effects\TeslaZap.cs" />
<Compile Include="Exts.cs" />
@@ -119,8 +121,15 @@
<Compile Include="Shroud.cs" />
<Compile Include="Smudge.cs" />
<Compile Include="Sound.cs" />
<Compile Include="SupportPower.cs" />
<Compile Include="SupportPowers\ChronospherePower.cs" />
<Compile Include="SupportPowers\GpsSatellite.cs" />
<Compile Include="SupportPowers\IronCurtainPower.cs" />
<Compile Include="SupportPowers\ISupportPowerImpl.cs" />
<Compile Include="SupportPowers\NullPower.cs" />
<Compile Include="Support\Stopwatch.cs" />
<Compile Include="Support\PerfHistory.cs" />
<Compile Include="Sync.cs" />
<Compile Include="Traits\AcceptsOre.cs" />
<Compile Include="Traits\Activities\Attack.cs" />
<Compile Include="Traits\Activities\CaptureBuilding.cs" />
@@ -162,6 +171,7 @@
<Compile Include="Traits\Activities\Repair.cs" />
<Compile Include="Traits\Activities\ReturnToBase.cs" />
<Compile Include="Traits\Activities\Sell.cs" />
<Compile Include="Traits\Activities\Steal.cs" />
<Compile Include="Traits\Activities\Teleport.cs" />
<Compile Include="BuildingInfluenceMap.cs" />
<Compile Include="Orders\IOrderGenerator.cs" />
@@ -216,6 +226,7 @@
<Compile Include="Traits\Explodes.cs" />
<Compile Include="Traits\ChronoshiftDeploy.cs" />
<Compile Include="Traits\Fake.cs" />
<Compile Include="Traits\GpsLaunchSite.cs" />
<Compile Include="Traits\Harvester.cs" />
<Compile Include="Traits\Helicopter.cs" />
<Compile Include="Traits\InvisibleToOthers.cs" />
@@ -255,6 +266,7 @@
<Compile Include="Traits\StoresOre.cs" />
<Compile Include="Traits\Submarine.cs" />
<Compile Include="Traits\TakeCover.cs" />
<Compile Include="Traits\Thief.cs" />
<Compile Include="Traits\TraitsInterfaces.cs" />
<Compile Include="Traits\Tree.cs" />
<Compile Include="Traits\Turreted.cs" />
@@ -299,10 +311,6 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<None Include="Game Code.cd" />
<None Include="Graphics\Graphics.cd" />
</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.

View File

@@ -1,19 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OpenRa.Game.Traits;
using OpenRa.Game.SupportPowers;
namespace OpenRa.Game.Orders
{
class ChronoshiftDestinationOrderGenerator : IOrderGenerator
{
public readonly Actor self;
SupportPower power;
public ChronoshiftDestinationOrderGenerator(Actor self)
public ChronoshiftDestinationOrderGenerator(Actor self, SupportPower power)
{
this.self = self;
this.power = power;
}
public IEnumerable<Order> Order(int2 xy, MouseInput mi)
@@ -23,8 +25,8 @@ namespace OpenRa.Game.Orders
Game.controller.CancelInputMode();
yield break;
}
yield return new Order("Chronoshift", self, null, xy, null);
yield return new Order("Chronoshift", self, null, xy,
power != null ? power.Name : null);
}
public void Tick() {}

View File

@@ -1,14 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Game.GameRules;
using OpenRa.Game.Traits;
using OpenRa.Game.SupportPowers;
namespace OpenRa.Game.Orders
{
class ChronosphereSelectOrderGenerator : IOrderGenerator
{
SupportPower power;
public ChronosphereSelectOrderGenerator(SupportPower power)
{
this.power = power;
}
public IEnumerable<Order> Order(int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
@@ -30,9 +36,7 @@ namespace OpenRa.Game.Orders
var unit = underCursor != null ? underCursor.Info as UnitInfo : null;
if (unit != null)
{
yield return new Order("ChronosphereSelect", underCursor, null, int2.Zero, null);
}
yield return new Order("ChronosphereSelect", underCursor, null, int2.Zero, power.Name);
}
}

View File

@@ -1,14 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Game.GameRules;
using OpenRa.Game.Traits;
using OpenRa.Game.SupportPowers;
namespace OpenRa.Game.Orders
{
class IronCurtainOrderGenerator : IOrderGenerator
{
SupportPower power;
public IronCurtainOrderGenerator(SupportPower power)
{
this.power = power;
}
public IEnumerable<Order> Order(int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
@@ -30,9 +36,7 @@ namespace OpenRa.Game.Orders
var unit = underCursor != null ? underCursor.Info as UnitInfo : null;
if (unit != null)
{
yield return new Order("IronCurtain", underCursor, null, int2.Zero, null);
}
yield return new Order("IronCurtain", underCursor, null, int2.Zero, power.Name);
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using OpenRa.Game.SupportPowers;
namespace OpenRa.Game
{
@@ -12,7 +13,7 @@ namespace OpenRa.Game
public readonly int2 TargetLocation;
public readonly string TargetString;
public bool IsImmediate;
public Actor Subject { get { return ActorFromUInt(SubjectId); } }
public Actor TargetActor { get { return ActorFromUInt(TargetActorId); } }
public Player Player { get { return Subject.Owner; } }
@@ -20,8 +21,8 @@ namespace OpenRa.Game
public Order(string orderString, Actor subject,
Actor targetActor, int2 targetLocation, string targetString)
: this( orderString, UIntFromActor( subject ),
UIntFromActor( targetActor ), targetLocation, targetString ) {}
UIntFromActor( targetActor ), targetLocation, targetString) {}
Order(string orderString, uint subjectId,
uint targetActorId, int2 targetLocation, string targetString)
{

View File

@@ -86,6 +86,7 @@ namespace OpenRa.Game.Orders
case "Infiltrate": return Cursor.Enter;
case "Capture": return Cursor.Capture;
case "Harvest": return Cursor.AttackMove;
case "Steal" : return Cursor.Enter;
default:
return null;
}

View File

@@ -97,7 +97,7 @@ namespace OpenRa.Game.Orders
default:
{
foreach (var t in order.Subject.traits.WithInterface<IOrder>())
foreach (var t in order.Subject.traits.WithInterface<IResolveOrder>())
t.ResolveOrder(order.Subject, order);
break;
}

View File

@@ -28,6 +28,7 @@ namespace OpenRa.Game
public bool IsReady;
public Shroud Shroud = new Shroud();
public Dictionary<string, SupportPower> SupportPowers;
public Player( Actor playerActor, int index, PaletteType palette, string playerName, Race race, string internalName )
{
@@ -37,6 +38,10 @@ namespace OpenRa.Game
this.InternalName = internalName;
this.PlayerName = playerName;
this.Race = race;
SupportPowers = Rules.SupportPowerInfo.ToDictionary(
spi => spi.Key,
spi => new SupportPower(spi.Key, spi.Value, this));
}
void UpdatePower()
@@ -126,6 +131,9 @@ namespace OpenRa.Game
UpdatePower();
UpdateOreCapacity();
foreach (var sp in SupportPowers.Values)
sp.Tick();
if (this == Game.LocalPlayer)
{
var totalMoney = Cash + Ore;

View File

@@ -13,10 +13,21 @@ namespace OpenRa.Game
Sprite[] shadowBits = SpriteSheetBuilder.LoadAllSprites("shadow");
Sprite[,] sprites = new Sprite[128, 128];
bool dirty;
public bool IsExplored(int2 xy)
bool hasGPS = false;
public bool HasGPS
{
return explored[ xy.X, xy.Y ];
get { return hasGPS; }
set { hasGPS = value; dirty = true;}
}
public bool IsExplored(int2 xy) { return IsExplored(xy.X, xy.Y); }
public bool IsExplored(int x, int y)
{
if (hasGPS)
return true;
return explored[ x, y ];
}
public void Explore(Actor a)
@@ -27,48 +38,47 @@ namespace OpenRa.Game
dirty = true;
}
static readonly byte[] ShroudTiles =
{
0xf,0xf,0xf,0xf,
0xf,0xf,0xf,0xf,
0xf,0xf,0xf,0xf,
0xf,0xf,0xf,0xf,
0,7,13,0,
14,6,12,4,
11,3,9,1,
0,2,8,0,
};
static readonly byte[] ExtraShroudTiles =
{
46, 41, 42, 38,
43, 45, 39, 35,
40, 37, 44, 34,
36, 33, 32, 47,
};
Sprite ChooseShroud(int i, int j)
{
// bits are for exploredness: left, right, up, down, self
var n = new[] {
0xf,0xf,0xf,0xf,
0xf,0x0f,0x0f,0xf,
0xf,0x0f,0x0f,0xf,
0xf,0xf,0xf,0xf,
0,7,13,0,
14,6,12,4,
11,3,9,1,
0,2,8,0,
};
var v = 0;
if (explored[i - 1, j]) v |= 1;
if (explored[i + 1, j]) v |= 2;
if (explored[i, j - 1]) v |= 4;
if (explored[i, j + 1]) v |= 8;
if (explored[i, j]) v |= 16;
if (IsExplored(i - 1, j)) v |= 1;
if (IsExplored(i + 1, j)) v |= 2;
if (IsExplored(i, j - 1)) v |= 4;
if (IsExplored(i, j + 1)) v |= 8;
if (IsExplored(i, j)) v |= 16;
var x = n[v];
var x = ShroudTiles[v];
if (x != 0)
return shadowBits[x];
if (x == 0)
{
// bits are for exploredness: TL, TR, BR, BL
var m = new[] {
46, 41, 42, 38,
43, 45, 39, 35,
40, 37, 44, 34,
36, 33, 32, 47,
};
var u = 0;
if (explored[i - 1, j - 1]) u |= 1;
if (explored[i + 1, j - 1]) u |= 2;
if (explored[i + 1, j + 1]) u |= 4;
if (explored[i - 1, j + 1]) u |= 8;
return shadowBits[m[u]];
}
return shadowBits[x];
// bits are for exploredness: TL, TR, BR, BL
var u = 0;
if (IsExplored(i - 1, j - 1)) u |= 1;
if (IsExplored(i + 1, j - 1)) u |= 2;
if (IsExplored(i + 1, j + 1)) u |= 4;
if (IsExplored(i - 1, j + 1)) u |= 8;
return shadowBits[ExtraShroudTiles[u]];
}
public void Draw(SpriteRenderer r)

104
OpenRa.Game/SupportPower.cs Normal file
View File

@@ -0,0 +1,104 @@
using System;
using System.Linq;
using OpenRa.Game.GameRules;
using OpenRa.Game.SupportPowers;
namespace OpenRa.Game
{
// todo: fix this to route Activate through the orders system (otherwise desync in netplay)
class SupportPower
{
public readonly SupportPowerInfo Info;
public readonly Player Owner;
public readonly ISupportPowerImpl Impl;
public readonly string Name;
static ISupportPowerImpl ConstructPowerImpl(string implName)
{
var type = typeof(ISupportPowerImpl).Assembly.GetType(
typeof(ISupportPowerImpl).Namespace + "." + implName, true, false);
var ctor = type.GetConstructor(Type.EmptyTypes);
return (ISupportPowerImpl)ctor.Invoke(new object[] { });
}
public SupportPower(string name, SupportPowerInfo info, Player owner)
{
Name = name;
Info = info;
Owner = owner;
RemainingTime = TotalTime = (int)(info.ChargeTime * 60 * 25);
Impl = ConstructPowerImpl(info.Impl);
}
public bool IsUsed;
public bool IsAvailable { get; private set; }
public bool IsDone { get { return RemainingTime == 0; } }
public int RemainingTime { get; private set; }
public int TotalTime { get; private set; }
bool notifiedReady = false;
bool notifiedCharging = false;
public void Tick()
{
if (Info.OneShot && IsUsed)
return;
if (Info.GivenAuto)
{
var buildings = Rules.TechTree.GatherBuildings(Owner);
var effectivePrereq = Info.Prerequisite
.Select( a => a.ToLowerInvariant() )
.Where( a => Rules.UnitInfo[a].Owner
.Any( r => r == Owner.Race ));
IsAvailable = Info.TechLevel > -1
&& effectivePrereq.Any()
&& effectivePrereq.All(a => buildings[a].Count > 0);
}
if (IsAvailable && (!Info.Powered || Owner.GetPowerState() == PowerState.Normal))
{
if (RemainingTime > 0) --RemainingTime;
if (!notifiedCharging)
{
Impl.IsChargingNotification(this);
notifiedCharging = true;
}
}
if (RemainingTime == 0
&& Impl != null
&& !notifiedReady)
{
Impl.IsReadyNotification(this);
notifiedReady = true;
}
}
public void Activate()
{
if (Impl != null)
Impl.Activate(this);
}
public void FinishActivate()
{
if (Info.OneShot)
{
IsUsed = true;
IsAvailable = false;
}
RemainingTime = TotalTime;
notifiedReady = false;
notifiedCharging = false;
}
public void Give(bool requireCharge) // called by crate/spy/etc code
{
IsAvailable = true;
IsUsed = false;
RemainingTime = requireCharge ? TotalTime : 0;
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using OpenRa.Game.Orders;
using OpenRa.Game.Traits;
namespace OpenRa.Game.SupportPowers
{
class ChronospherePower : ISupportPowerImpl
{
public void IsReadyNotification(SupportPower p) { Sound.Play("chrordy1.aud"); }
public void IsChargingNotification(SupportPower p) { Sound.Play("chrochr1.aud"); }
public void OnFireNotification(Actor target, int2 xy)
{
p.FinishActivate();
Game.controller.CancelInputMode();
Sound.Play("chrono2.aud");
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<ChronoshiftPaletteEffect>()))
a.traits.Get<ChronoshiftPaletteEffect>().DoChronoshift();
// Play chronosphere active anim
var chronosphere = Game.world.Actors.Where(a => a.Owner == p.Owner && a.traits.Contains<Chronosphere>()).FirstOrDefault();
if (chronosphere != null)
chronosphere.traits.Get<RenderBuilding>().PlayCustomAnim(chronosphere, "active");
}
SupportPower p;
public void Activate(SupportPower p)
{
this.p = p;
Game.controller.orderGenerator = new ChronosphereSelectOrderGenerator(p);
Sound.Play("slcttgt1.aud");
}
}
}

View File

@@ -0,0 +1,32 @@
using System.Linq;
using OpenRa.Game.Effects;
using OpenRa.Game.Traits;
namespace OpenRa.Game.SupportPowers
{
class GpsSatellite : ISupportPowerImpl
{
const int revealDelay = 15 * 25;
public void OnFireNotification(Actor a, int2 xy) { }
public void IsChargingNotification(SupportPower p) { }
public void IsReadyNotification(SupportPower p)
{
var launchSite = Game.world.Actors
.FirstOrDefault(a => a.Owner == p.Owner && a.traits.Contains<GpsLaunchSite>());
if (launchSite == null)
return;
Game.world.AddFrameEndTask(w =>
{
w.Add(new SatelliteLaunch(launchSite));
w.Add(new DelayedAction(revealDelay, () => p.Owner.Shroud.HasGPS = true));
});
p.FinishActivate();
}
public void Activate(SupportPower p) {}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.SupportPowers
{
interface ISupportPowerImpl
{
void Activate(SupportPower p);
void OnFireNotification(Actor target, int2 xy);
void IsChargingNotification(SupportPower p);
void IsReadyNotification(SupportPower p);
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRa.Game.Orders;
using OpenRa.Game.Traits;
namespace OpenRa.Game.SupportPowers
{
class IronCurtainPower : ISupportPowerImpl
{
public void IsReadyNotification(SupportPower p)
{
Sound.Play("ironrdy1.aud");
}
public void IsChargingNotification(SupportPower p)
{
Sound.Play("ironchg1.aud");
}
public void OnFireNotification(Actor target, int2 xy)
{
p.FinishActivate();
Game.controller.CancelInputMode();
Sound.Play("ironcur9.aud");
// Play active anim
var ironCurtain = Game.world.Actors
.Where(a => a.Owner == p.Owner && a.traits.Contains<IronCurtain>())
.FirstOrDefault();
if (ironCurtain != null)
ironCurtain.traits.Get<RenderBuilding>().PlayCustomAnim(ironCurtain, "active");
}
SupportPower p;
public void Activate(SupportPower p)
{
this.p = p;
// Pick a building to use
Game.controller.orderGenerator = new IronCurtainOrderGenerator(p);
Sound.Play("slcttgt1.aud");
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.SupportPowers
{
class NullPower : ISupportPowerImpl
{
public void OnFireNotification(Actor a, int2 xy) { }
public void IsReadyNotification(SupportPower p) { }
public void IsChargingNotification(SupportPower p) { }
public void Activate(SupportPower p)
{
// if this was a real power, i'd do something here!
throw new NotImplementedException();
}
}
}

107
OpenRa.Game/Sync.cs Executable file
View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using IjwFramework.Collections;
namespace OpenRa.Game
{
class SyncAttribute : Attribute { }
static class Sync
{
static Cache<Type, Func<object, int>> hashFuncCache = new Cache<Type, Func<object, int>>( t => GenerateHashFunc( t ) );
public static int CalculateSyncHash( object obj )
{
return hashFuncCache[ obj.GetType() ]( obj );
}
public static Func<object,int> GenerateHashFunc( Type t )
{
var d = new DynamicMethod( "hash_{0}".F( t.Name ), typeof( int ), new Type[] { typeof( object ) }, t );
var il = d.GetILGenerator();
var this_ = il.DeclareLocal( t ).LocalIndex;
il.Emit( OpCodes.Ldarg_0 );
il.Emit( OpCodes.Castclass, t );
il.Emit( OpCodes.Stloc, this_ );
il.Emit( OpCodes.Ldc_I4_0 );
const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
foreach( var field in t.GetFields( bf ).Where( x => x.GetCustomAttributes( typeof( SyncAttribute ), true ).Length != 0 ) )
{
il.Emit( OpCodes.Ldloc, this_ );
il.Emit( OpCodes.Ldfld, field );
if( field.FieldType == typeof( int ) )
{
il.Emit( OpCodes.Xor );
}
else if( field.FieldType == typeof( bool ) )
{
var l = il.DefineLabel();
il.Emit( OpCodes.Ldc_I4, 0xaaa );
il.Emit( OpCodes.Brtrue, l );
il.Emit( OpCodes.Pop );
il.Emit( OpCodes.Ldc_I4, 0x555 );
il.MarkLabel( l );
il.Emit( OpCodes.Xor );
}
else if( field.FieldType == typeof( int2 ) )
{
il.EmitCall( OpCodes.Call, ( (Func<int2, int>)hash_int2 ).Method, null );
il.Emit( OpCodes.Xor );
}
else if( field.FieldType == typeof( TypeDictionary ) )
{
il.EmitCall( OpCodes.Call, ( (Func<TypeDictionary, int>)hash_tdict ).Method, null );
il.Emit( OpCodes.Xor );
}
else if( field.FieldType == typeof( Actor ) )
{
il.EmitCall( OpCodes.Call, ( (Func<Actor, int>)hash_actor ).Method, null );
il.Emit( OpCodes.Xor );
}
else if( field.FieldType == typeof( Player ) )
{
il.EmitCall( OpCodes.Call, ( (Func<Player, int>)hash_player ).Method, null );
il.Emit( OpCodes.Xor );
}
else
throw new NotImplementedException( "SyncAttribute on unhashable field" );
}
il.Emit( OpCodes.Ret );
return (Func<object,int>)d.CreateDelegate( typeof( Func<object,int> ) );
}
internal static int hash_int2( int2 i2 )
{
return ( ( i2.X * 5 ) ^ ( i2.Y * 3 ) ) / 4;
}
internal static int hash_tdict( TypeDictionary d )
{
int ret = 0;
foreach( var o in d )
ret += CalculateSyncHash( o );
return ret;
}
internal static int hash_actor( Actor a )
{
if( a != null )
return (int)( a.ActorID << 16 );
return 0;
}
internal static int hash_player( Player p )
{
if( p != null )
return p.Index * 0x567;
return 0;
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Game.Traits.Activities
{
class Steal : IActivity
{
Actor target;
public Steal(Actor target) { this.target = target; }
public IActivity NextActivity { get; set; }
public IActivity Tick(Actor self)
{
if (target == null || target.IsDead) return NextActivity;
if (target.Owner == self.Owner) return NextActivity;
foreach (var t in target.traits.WithInterface<IAcceptThief>())
t.OnSteal(target, self);
return NextActivity;
}
public void Cancel(Actor self) { target = null; NextActivity = null; }
}
}

View File

@@ -6,12 +6,14 @@ using OpenRa.Game.Effects;
namespace OpenRa.Game.Traits
{
class AttackBase : IOrder, ITick
class AttackBase : IIssueOrder, IResolveOrder, ITick
{
public Actor target;
[Sync] public Actor target;
// time (in frames) until each weapon can fire again.
[Sync]
protected int primaryFireDelay = 0;
[Sync]
protected int secondaryFireDelay = 0;
int primaryBurst;

View File

@@ -7,7 +7,7 @@ namespace OpenRa.Game.Traits
public AttackFrontal(Actor self, int facingTolerance)
: base(self) { FacingTolerance = facingTolerance; }
int FacingTolerance;
readonly int FacingTolerance;
public override void Tick(Actor self)
{

View File

@@ -9,11 +9,13 @@ using OpenRa.Game.Graphics;
namespace OpenRa.Game.Traits
{
class Building : INotifyDamage, IOrder, ITick
class Building : INotifyDamage, IResolveOrder, ITick
{
readonly Actor self;
public readonly BuildingInfo unitInfo;
[Sync]
bool isRepairing = false;
[Sync]
bool manuallyDisabled = false;
public bool ManuallyDisabled { get { return manuallyDisabled; } }
public bool Disabled { get { return (manuallyDisabled || (unitInfo.Powered && self.Owner.GetPowerState() != PowerState.Normal)); } }
@@ -44,11 +46,6 @@ namespace OpenRa.Game.Traits
Sound.Play("kaboom22.aud");
}
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{
return null; // sell/repair orders are issued through Chrome, not here.
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Sell")

View File

@@ -2,7 +2,7 @@
namespace OpenRa.Game.Traits
{
class C4Demolition : IOrder
class C4Demolition : IIssueOrder, IResolveOrder
{
public C4Demolition(Actor self) { }

View File

@@ -7,7 +7,7 @@ using OpenRa.Game.Traits.Activities;
namespace OpenRa.Game.Traits
{
class Cargo : IPips, IOrder
class Cargo : IPips, IIssueOrder, IResolveOrder
{
List<Actor> cargo = new List<Actor>();

View File

@@ -4,11 +4,12 @@ using OpenRa.Game.Orders;
namespace OpenRa.Game.Traits
{
class ChronoshiftDeploy : IOrder, ISpeedModifier, ITick, IPips
class ChronoshiftDeploy : IIssueOrder, IResolveOrder, ISpeedModifier, ITick, IPips
{
// Recharge logic
[Sync]
int chargeTick = 0; // How long until we can chronoshift again?
int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts?
readonly int chargeLength = (int)(Rules.Aftermath.ChronoTankDuration * 60 * 25); // How long between shifts?
public ChronoshiftDeploy(Actor self) { }
@@ -38,7 +39,7 @@ namespace OpenRa.Game.Traits
if (order.OrderString == "ChronoshiftSelf" && movement.CanEnterCell(order.TargetLocation))
{
// Cannot chronoshift into unexplored location
if (!Game.LocalPlayer.Shroud.IsExplored(order.TargetLocation))
if (!self.Owner.Shroud.IsExplored(order.TargetLocation))
return;
Game.controller.CancelInputMode();

View File

@@ -2,16 +2,17 @@
using OpenRa.Game.Orders;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
namespace OpenRa.Game.Traits
{
class Chronoshiftable : IOrder, ISpeedModifier, ITick
class Chronoshiftable : IResolveOrder, ISpeedModifier, ITick
{
// Return-to-sender logic
[Sync]
int2 chronoshiftOrigin;
[Sync]
int chronoshiftReturnTicks = 0;
public Chronoshiftable(Actor self) { }
public void Tick(Actor self)
@@ -31,55 +32,42 @@ namespace OpenRa.Game.Traits
}
}
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{
return null; // Chronoshift order is issued through Chrome.
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "ChronosphereSelect")
{
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self);
var power = self.Owner.SupportPowers[order.TargetString];
Game.controller.orderGenerator = new ChronoshiftDestinationOrderGenerator(self, power);
}
var movement = self.traits.WithInterface<IMovement>().FirstOrDefault();
if (order.OrderString == "Chronoshift" && movement.CanEnterCell(order.TargetLocation))
{
// Cannot chronoshift into unexplored location
if (!Game.LocalPlayer.Shroud.IsExplored(order.TargetLocation))
if (!self.Owner.Shroud.IsExplored(order.TargetLocation))
return;
// Set up return-to-sender info
chronoshiftOrigin = self.Location;
chronoshiftReturnTicks = (int)(Rules.General.ChronoDuration * 60 * 25);
var chronosphere = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<Chronosphere>()).FirstOrDefault();
// Kill cargo
if (Rules.General.ChronoKillCargo && self.traits.Contains<Cargo>())
{
var cargo = self.traits.Get<Cargo>();
while (!cargo.IsEmpty(self))
{
if (chronosphere != null)
chronosphere.Owner.Kills++;
order.Player.Kills++;
cargo.Unload(self);
}
}
// Set up the teleport
Game.controller.CancelInputMode();
self.CancelActivity();
self.QueueActivity(new Activities.Teleport(order.TargetLocation));
Sound.Play("chrono2.aud");
foreach (var a in Game.world.Actors.Where(a => a.traits.Contains<ChronoshiftPaletteEffect>()))
a.traits.Get<ChronoshiftPaletteEffect>().DoChronoshift();
// Play chronosphere active anim
if (chronosphere != null)
chronosphere.traits.Get<RenderBuilding>().PlayCustomAnim(chronosphere, "active");
var power = self.Owner.SupportPowers[order.TargetString].Impl;
power.OnFireNotification(self, self.Location);
}
}

View File

@@ -6,6 +6,7 @@ namespace OpenRa.Game.Traits
{
class Cloak : IRenderModifier, INotifyAttack, ITick
{
[Sync]
int remainingUncloakTime = 2; /* setup for initial cloak */
public Cloak(Actor self) {}

View File

@@ -3,7 +3,7 @@ using OpenRa.Game.Traits.Activities;
namespace OpenRa.Game.Traits
{
class ConstructionYard : IOrder, IMovement
class ConstructionYard : IIssueOrder, IResolveOrder, IMovement
{
readonly Actor self;

View File

@@ -6,7 +6,7 @@ using OpenRa.Game.Orders;
namespace OpenRa.Game.Traits
{
class DemoTruck : Chronoshiftable, IOrder, INotifyDamage
class DemoTruck : Chronoshiftable, IResolveOrder, INotifyDamage
{
readonly Actor self;
public DemoTruck(Actor self)

View File

@@ -2,7 +2,7 @@
namespace OpenRa.Game.Traits
{
class EngineerCapture : IOrder
class EngineerCapture : IIssueOrder, IResolveOrder
{
public const int EngineerDamage = 300; // todo: push into rules, as a weapon

View File

@@ -0,0 +1,6 @@
using OpenRa.Game.Effects;
namespace OpenRa.Game.Traits
{
class GpsLaunchSite { public GpsLaunchSite(Actor self) { } }
}

View File

@@ -3,9 +3,11 @@ using OpenRa.Game.Traits.Activities;
namespace OpenRa.Game.Traits
{
class Harvester : IOrder, IPips
class Harvester : IIssueOrder, IResolveOrder, IPips
{
[Sync]
public int oreCarried = 0; /* sum of these must not exceed capacity */
[Sync]
public int gemsCarried = 0;
public bool IsFull { get { return oreCarried + gemsCarried == Rules.General.BailCount; } }

View File

@@ -4,7 +4,7 @@ using OpenRa.Game.GameRules;
namespace OpenRa.Game.Traits
{
class Helicopter : IOrder, IMovement
class Helicopter : IIssueOrder, IResolveOrder, IMovement
{
public IDisposable reservation;
public Helicopter(Actor self) {}

View File

@@ -1,15 +1,11 @@
using OpenRa.Game.Traits;
using OpenRa.Game.Orders;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Linq;
using OpenRa.Game.Effects;
using OpenRa.Game.Graphics;
namespace OpenRa.Game.Traits
{
class IronCurtainable: IOrder, IDamageModifier, ITick
class IronCurtainable : IResolveOrder, IDamageModifier, ITick
{
[Sync]
int RemainingTicks = 0;
public IronCurtainable(Actor self) { }
@@ -23,24 +19,15 @@ namespace OpenRa.Game.Traits
{
return (RemainingTicks > 0) ? 0.0f : 1.0f;
}
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{
return null; // Chronoshift order is issued through Chrome.
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "IronCurtain")
{
Game.controller.CancelInputMode();
var power = self.Owner.SupportPowers[order.TargetString].Impl;
power.OnFireNotification(self, self.Location);
Game.world.AddFrameEndTask(w => w.Add(new InvulnEffect(self)));
RemainingTicks = (int)(Rules.General.IronCurtain * 60 * 25);
Sound.Play("ironcur9.aud");
// Play active anim
var ironCurtain = Game.world.Actors.Where(a => a.Owner == order.Subject.Owner && a.traits.Contains<IronCurtain>()).FirstOrDefault();
if (ironCurtain != null)
ironCurtain.traits.Get<RenderBuilding>().PlayCustomAnim(ironCurtain, "active");
}
}
}

View File

@@ -4,6 +4,7 @@ namespace OpenRa.Game.Traits
{
class LimitedAmmo : INotifyAttack, IPips
{
[Sync]
int ammo;
Actor self;

View File

@@ -3,7 +3,7 @@ using OpenRa.Game.Traits.Activities;
namespace OpenRa.Game.Traits
{
class McvDeploy : IOrder
class McvDeploy : IIssueOrder, IResolveOrder
{
public McvDeploy(Actor self) { }

View File

@@ -5,7 +5,7 @@ using System.Text;
namespace OpenRa.Game.Traits
{
class Minelayer : IOrder
class Minelayer : IIssueOrder, IResolveOrder
{
public Minelayer(Actor self) { }

View File

@@ -5,10 +5,11 @@ using OpenRa.Game.GameRules;
namespace OpenRa.Game.Traits
{
class Mobile : IOrder, IOccupySpace, IMovement
class Mobile : IIssueOrder, IResolveOrder, IOccupySpace, IMovement
{
readonly Actor self;
[Sync]
int2 __fromCell;
public int2 fromCell
{

View File

@@ -6,7 +6,7 @@ using OpenRa.Game.Traits.Activities;
namespace OpenRa.Game.Traits
{
class Passenger : IOrder
class Passenger : IIssueOrder, IResolveOrder
{
public Passenger(Actor self) { }

View File

@@ -6,7 +6,7 @@ using OpenRa.Game.Traits.Activities;
namespace OpenRa.Game.Traits
{
class Plane : IOrder, IMovement
class Plane : IIssueOrder, IResolveOrder, IMovement
{
public IDisposable reservation;

View File

@@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace OpenRa.Game.Traits
{
class Production : IOrder, IProducer, ITags
class Production : IIssueOrder, IResolveOrder, IProducer, ITags
{
bool isPrimary = false;
public bool IsPrimary { get { return isPrimary; } }
@@ -66,9 +66,7 @@ namespace OpenRa.Game.Traits
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Deploy")
{
SetPrimaryProducer(self, !isPrimary);
}
}
public void SetPrimaryProducer(Actor self, bool state)

View File

@@ -6,7 +6,7 @@ using IjwFramework.Collections;
namespace OpenRa.Game.Traits
{
class ProductionQueue : IOrder, ITick
class ProductionQueue : IResolveOrder, ITick
{
Actor self;
@@ -22,12 +22,6 @@ namespace OpenRa.Game.Traits
(p.Value)[0].Tick( self.Owner );
}
public Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor )
{
// production isn't done by clicks in the world; the chrome handles it.
return null;
}
public void ResolveOrder( Actor self, Order order )
{
switch( order.OrderString )
@@ -80,6 +74,7 @@ namespace OpenRa.Game.Traits
}
// Key: Production category.
// TODO: sync this
readonly Cache<string, List<ProductionItem>> production
= new Cache<string, List<ProductionItem>>( _ => new List<ProductionItem>() );

View File

@@ -4,8 +4,9 @@ using OpenRa.Game.Orders;
namespace OpenRa.Game.Traits
{
class RallyPoint : IRender, IOrder, ITick
class RallyPoint : IRender, IIssueOrder, IResolveOrder, ITick
{
[Sync]
public int2 rallyPoint;
public Animation anim;

View File

@@ -7,7 +7,9 @@ namespace OpenRa.Game.Traits
class RenderWarFactory : IRender, INotifyBuildComplete, INotifyDamage, ITick, INotifyProduction
{
public Animation roof;
[Sync]
bool doneBuilding;
[Sync]
bool isOpen;
public readonly Actor self;

View File

@@ -6,7 +6,7 @@ using OpenRa.Game.Traits.Activities;
namespace OpenRa.Game.Traits
{
class Repairable : IOrder
class Repairable : IIssueOrder, IResolveOrder
{
IDisposable reservation;
public Repairable(Actor self) { }

View File

@@ -1,9 +1,12 @@
using System.Collections.Generic;
using System;
using OpenRa.Game.GameRules;
namespace OpenRa.Game.Traits
{
class StoresOre : IPips
class StoresOre : IPips, IAcceptThief
{
public const int MaxStealAmount = 100; //todo: How is cash stolen determined?
readonly Actor self;
public StoresOre(Actor self)
@@ -11,6 +14,21 @@ namespace OpenRa.Game.Traits
this.self = self;
}
public void OnSteal(Actor self, Actor thief)
{
// Steal half the ore the building holds
var toSteal = (self.Info as BuildingInfo).Storage/2;
self.Owner.TakeCash(toSteal);
thief.Owner.GiveCash(toSteal);
if (Game.LocalPlayer == thief.Owner)
Sound.Play("credit1.aud");
// the thief is sacrificed.
thief.Health = 0;
Game.world.AddFrameEndTask(w => w.Remove(thief));
}
public IEnumerable<PipType> GetPips(Actor self)
{
for (int i = 0; i < self.Info.OrePips; i++)

View File

@@ -6,6 +6,7 @@ namespace OpenRa.Game.Traits
{
class Submarine : IRenderModifier, INotifyAttack, ITick, INotifyDamage
{
[Sync]
int remainingSurfaceTime = 2; /* setup for initial dive */
public Submarine(Actor self) { }

View File

@@ -8,6 +8,7 @@ namespace OpenRa.Game.Traits
const float proneDamage = .5f;
const float proneSpeed = .5f;
[Sync]
int remainingProneTime = 0;
public bool IsProne { get { return remainingProneTime > 0; } }

View File

@@ -0,0 +1,29 @@
using OpenRa.Game.Traits.Activities;
using System.Collections.Generic;
using System.Linq;
namespace OpenRa.Game.Traits
{
class Thief : IIssueOrder, IResolveOrder
{
public Thief(Actor self) { }
public Order IssueOrder(Actor self, int2 xy, MouseInput mi, Actor underCursor)
{
if (mi.Button != MouseButton.Right) return null;
if (underCursor == null) return null;
if (!underCursor.traits.WithInterface<IAcceptThief>().Any()) return null;
return new Order("Steal", self, underCursor, int2.Zero, null);
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Steal")
{
self.CancelActivity();
self.QueueActivity(new Move(order.TargetActor, 1));
self.QueueActivity(new Steal(order.TargetActor));
}
}
}
}

View File

@@ -10,18 +10,18 @@ namespace OpenRa.Game.Traits
// depends on the order of pips in WorldRenderer.cs!
enum PipType { Transparent, Green, Yellow, Red, Gray };
enum TagType { None, Fake, Primary };
interface ITick { void Tick(Actor self); }
interface IRender { IEnumerable<Renderable> Render(Actor self); }
interface IIssueOrder { Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor ); }
interface IResolveOrder { void ResolveOrder( Actor self, Order order ); }
interface INotifySold { void Sold(Actor self); }
interface INotifyDamage { void Damaged(Actor self, AttackInfo e); }
interface INotifyBuildComplete { void BuildingComplete (Actor self); }
interface INotifyProduction { void UnitProduced(Actor self, Actor other); }
interface IOrder
{
Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor );
void ResolveOrder( Actor self, Order order );
}
interface IAcceptThief { void OnSteal(Actor self, Actor thief); }
interface IProducer
{
bool Produce( Actor self, UnitInfo producee );

View File

@@ -3,6 +3,7 @@ namespace OpenRa.Game.Traits
{
class Turreted : ITick
{
[Sync]
public int turretFacing = 0;
public int? desiredFacing;

View File

@@ -3,7 +3,9 @@ namespace OpenRa.Game.Traits
{
class Unit : INotifyDamage
{
[Sync]
public int Facing;
[Sync]
public int Altitude;
public Unit( Actor self ) { }

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using OpenRa.Game.Effects;
using OpenRa.Game.Support;
namespace OpenRa.Game
{
@@ -12,15 +13,15 @@ namespace OpenRa.Game
public void Add(Actor a)
{
a.IsInWorld = true;
actors.Add(a);
a.IsInWorld = true;
actors.Add(a);
ActorAdded(a);
}
public void Remove(Actor a)
{
a.IsInWorld = false;
actors.Remove(a);
a.IsInWorld = false;
actors.Remove(a);
ActorRemoved(a);
}
@@ -52,5 +53,17 @@ namespace OpenRa.Game
{
return nextAID++;
}
public int SyncHash()
{
using (new PerfSample("synchash"))
{
int ret = 0;
foreach (var a in Actors)
ret += (int)a.ActorID * Sync.CalculateSyncHash(a);
return ret;
}
}
}
}

View File

@@ -1,12 +1,11 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using OpenRa.FileFormats;
using System.Xml;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using OpenRa.FileFormats;
namespace SequenceEditor
{

17
ra.yaml Normal file
View File

@@ -0,0 +1,17 @@
#
# Red Alert rules
#
Vehicles:
V2RL:
Buildable: { Description="V2 Rocket", Prerequisites=[weap,dome], TechLevel=4, Cost=700,
LongDesc="Long-range rocket artillery.\n Strong vs Infantry, Buildings\n Weak vs Tanks, Aircraft" }
Unit: { HP=150, Armor=light, Crewed=yes, Voice=VehicleVoice }
Mobile: { Sight=5, ROT=5, Speed=7, UMT=Track }
AttackBase: { Primary=SCUD, Ammo=1 }
RenderUnitReload: {}
AutoTarget: {}
Repairable: {}
Chronoshiftable: {}
Passenger: {}
IronCurtainable: {}

View File

@@ -1228,7 +1228,7 @@ ROT=30
; big missile silo
[MSLO]
Prerequisite=stek
Prerequisite=stek,atek
Primary=none
Strength=400
Armor=heavy

View File

@@ -94,6 +94,7 @@
<sequence name="idle" start="0" />
<sequence name="damaged-idle" start="1" />
<sequence name="make" start="0" length="*" src="atekmake" />
<sequence name="active" start="0" length="*" src="sputdoor" />
</unit>
<!-- soviet tech center -->
<unit name="stek">
@@ -201,9 +202,9 @@
</unit>
<!-- iron curtain -->
<unit name="iron">
<sequence name="idle" start="0" length="1" />
<sequence name="active" start="0" length="11" />
<sequence name="damaged-idle" start="11" length="1" />
<sequence name="idle" start="0" length="1" />
<sequence name="active" start="0" length="11" />
<sequence name="damaged-idle" start="11" length="1" />
<sequence name="damaged-active" start="11" length="11" />
<sequence name="make" start="0" length="*" src="ironmake" />
</unit>
@@ -1030,10 +1031,30 @@
<sequence name="left-normal" start="0" length="1" />
<sequence name="left-pressed" start="1" length="1" />
</unit>
<unit name="sputnik">
<sequence name="idle" start="0" length="4" />
</unit>
<unit name="dd-crnr">
<sequence name="idle" start="0" length="4" />
<sequence name="top-left" start="0" length="1" />
<sequence name="top-right" start="1" length="1" />
<sequence name="bottom-left" start="2" length="1" />
<sequence name="bottom-right" start="3" length="1" />
</unit>
<unit name="ussrradr">
<sequence name="idle" start="0" length="1" />
<sequence name="open" start="1" length="20" />
<sequence name="jammed" start="21" length="4" />
<sequence name="close" start="25" length="16" />
<sequence name="no-power" start="41" length="1" />
<sequence name="active" start="42" length="1" />
</unit>
<unit name="natoradr">
<sequence name="idle" start="0" length="1" />
<sequence name="open" start="1" length="20" />
<sequence name="active" start="42" length="1" />
<sequence name="jammed" start="21" length="4" />
<sequence name="close" start="25" length="16" />
<sequence name="no-power" start="41" length="1" />
</unit>
</sequences>

55
thirdparty/yaml/AssemblyInfo.cs vendored Normal file
View File

@@ -0,0 +1,55 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("Yaml Parser")]
[assembly: AssemblyDescription("Yaml .NET library")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("UHasselt students")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Christophe Lambrechts and Jonathan Slenders")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]

154
thirdparty/yaml/Binary.cs vendored Normal file
View File

@@ -0,0 +1,154 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
namespace Yaml
{
/// <summary>
/// A Yaml Boolean node
/// tag:yaml.org,2002:binary
/// </summary>
public class Binary : Scalar
{
private byte [] content;
/// <summary> Binary constructor from byte array </summary>
/// <remarks> This constructor only sets the reference, no new memory is allocated </remarks>
public Binary (byte[] val) :
base ("tag:yaml.org,2002:binary", NodeType.Binary)
{
content = val;
}
/// <summary> Parse a binary node </summary>
public Binary (ParseStream stream) :
base ("tag:yaml.org,2002:binary", NodeType.Binary)
{
try
{
content = Parse (stream);
}
catch (FormatException e)
{
throw new ParseException (stream, e);
}
}
/// <summary> Binary content </summary>
/// <remarks> There is no new memory allocated in the 'set'. </remarks>
public byte [] Content
{
get { return content; }
set { content = value; }
}
/// <summary> Parses a binairy node. </summary>
/// <remarks>
/// This is not an efficient method. First the stream is placed
/// in a string. And after that the string is converted in a byte[].
/// If there is a fault in the binairy string then that will only be detected
/// after reading the whole stream and after coneverting.
/// </remarks>
public static new byte [] Parse (ParseStream stream)
{
bool quoted = false;
bool block = false;
System.Text.StringBuilder input = new System.Text.StringBuilder();
if (stream.EOF)
throw new ParseException (stream, "Empty node");
// Detect block scalar
stream.SkipSpaces ();
if (stream.Char == '|')
{
block = true;
stream.Next ();
stream.SkipSpaces ();
}
while ( ! stream.EOF)
{
// Detect quotes
if (stream.Char == '\"')
if (quoted)
break; //End of stream
else
quoted = true; //Start of quoted stream
// Detect and ignore newline char's
else if (!(stream.Char == '\n' && block))
input.Append( stream.Char );
stream.Next ();
}
//Console.WriteLine("convert [" + input.ToString() + "]");
return System.Convert.FromBase64String (input.ToString ());
}
/// <summary> To String </summary>
/// <remarks> The hexadecimal notation, 20 bytes for each line </remarks>
public override string ToString ()
{
System.Text.StringBuilder output = new System.Text.StringBuilder ();
output.Append ("[BINARY]\n\t");
for (uint i = 0; i < content.Length; i++)
{
if ((i%16) == 0)
output.Append( "\n\t" );
output.AppendFormat ("{0:X2} ", content[i]);
}
output.Append ("\n[/BINARY]");
return output.ToString ();
}
/// <summary>
/// Write the base64 content to YAML
/// </summary>
/// <remarks> The lines are splitted in blocks of 20 bytes </remarks>
protected internal override void Write (WriteStream stream)
{
stream.Append("!!binary |" + "\n" );
string bin = System.Convert.ToBase64String(content);
while (bin.Length > 75)
{
stream.Append(" " + bin.Substring(0, 75) + "\n");
bin = bin.Substring(75);
}
stream.Append(" " + bin );
// Old coden, everything on one line
// stream.Append ("!!binary \"" + System.Convert.ToBase64String (content) + "\"");
}
}
}

132
thirdparty/yaml/Boolean.cs vendored Normal file
View File

@@ -0,0 +1,132 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
namespace Yaml
{
/// <summary>
/// Class for storing a Yaml Boolean node
/// tag:yaml.org,2002:bool
/// </summary>
public class Boolean : Scalar
{
private bool content;
/// <summary> New boolean </summary>
public Boolean (bool val) :
base ("tag:yaml.org,2002:bool", NodeType.Boolean)
{
content = val;
}
/// <summary> Parse boolean </summary>
public Boolean (ParseStream stream) :
base ("tag:yaml.org,2002:bool", NodeType.Boolean)
{
// Read the first 8 chars
char [] chars = new char [8];
int length = 0;
for (int i = 0; i < chars.Length && ! stream.EOF; i ++)
{
chars [i] = stream.Char;
length ++;
stream.Next (true);
}
// Compare
if (length == 1)
{
if (chars[0] == 'Y' || chars[0] == 'y')
{ content = true; return; }
if (chars[0] == 'N' || chars[0] == 'n')
{ content = false; return; }
}
if (length == 2)
{
string s = "" + chars [0] + chars [1];
if (s == "ON" || s == "On" || s == "on")
{ content = true; return; }
if (s == "NO" || s == "No" || s == "no")
{ content = false; return; }
}
if (length == 3)
{
string s = "" + chars [0] + chars [1] + chars [2];
if (s == "YES" || s == "Yes" || s == "yes")
{ content = true; return; }
if (s == "OFF" || s == "Off" || s == "off")
{ content = false; return; }
}
if (length == 4)
{
string s = "" + chars [0] + chars [1] + chars [2] + chars [3];
if (s == "TRUE" || s == "True" || s == "true")
{ content = true; return; }
}
if (length == 5)
{
string s = "" + chars [0] + chars [1] + chars [2] + chars [3] + chars[4];
if (s == "FALSE" || s == "False" || s == "false")
{ content = false; return; }
}
// No boolean
throw new Exception ("No valid boolean");
}
/// <summary> Node content </summary>
public bool Content
{
get { return content; }
set { content = value; }
}
/// <summary> To String </summary>
public override string ToString ()
{
return "[BOOLEAN]" + content.ToString () + "[/BOOLEAN]";
}
/// <summary> Write to YAML </summary>
protected internal override void Write (WriteStream stream)
{
if (Content)
stream.Append ("y");
else
stream.Append ("n");
}
}
}

504
thirdparty/yaml/COPYING vendored Normal file
View File

@@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

295
thirdparty/yaml/Float.cs vendored Normal file
View File

@@ -0,0 +1,295 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
namespace Yaml
{
/// <summary>
/// Class for storing a Yaml Float node
/// tag:yaml.org,2002:float
/// </summary>
public class Float : Scalar
{
private double content;
/// <summary> New float </summary>
public Float (float val) : base ("tag:yaml.org,2002:float", NodeType.Float)
{
content = val;
}
/// <summary> Parse float </summary>
public Float (ParseStream stream) :
base ("tag:yaml.org,2002:float", NodeType.Float)
{
// NaN
if (stream.Char == '.')
{
stream.Next (true);
ParseNaN (stream);
}
else
{
// By default positief
int sign = 1;
// Negative sign
if (stream.Char == '-')
{
sign = -1;
stream.Next (true);
}
// Positive sign
else if (stream.Char == '+')
stream.Next (true);
// Test for inf, Inf and INF
if ( ! stream.EOF && stream.Char == '.')
{
stream.Next (true);
ParseInf (stream, sign);
}
// Parse the numbers
else if (!stream.EOF)
ParseNumber (stream, sign);
else
throw new ParseException (stream,
"No valid float, no data behind the sign");
}
}
#region Parse special formats (NaN and Inf)
/// <summary>
/// Test for the value's nan, NaN and NAN in the stream. If
/// found then it is placed inside the content.
/// There is no more data excepted behind it
/// </summary>
private void ParseNaN (ParseStream stream)
{
// Read the first 8 chars
char [] chars = new char [8];
int length = 0;
for (int i = 0; i < chars.Length && ! stream.EOF; i ++)
{
chars [i] = stream.Char;
length ++;
stream.Next (true);
}
// Compare
if (length == 3)
{
string s = "" + chars [0] + chars [1] + chars [2];
if (s == "NAN" || s == "NaN" || s == "nan")
{
content = double.NaN;
return;
}
}
throw new ParseException (stream, "No valid NaN");
}
/// <summary>
/// Test for the value's inf, Inf and INF in the stream. If
/// found then it 'merged' with the sign and placed in the content.
/// There is no more data excepted behind it.
/// </summary>
private void ParseInf (ParseStream stream, int sign)
{
// Read the first 8 chars
char [] chars = new char [8];
int length = 0;
for (int i = 0; i < chars.Length && ! stream.EOF; i ++)
{
chars [i] = stream.Char;
length ++;
stream.Next (true);
}
// Compare
if (length == 3)
{
string s = "" + chars [0] + chars [1] + chars [2];
if (s == "INF" || s == "Inf" || s == "inf")
{
if (sign < 0)
content = double.NegativeInfinity;
else
content = double.PositiveInfinity;
return;
}
}
throw new ParseException (stream, "No valid infinity");
}
#endregion
/// <summary>
/// If it is not Infinity or NaN, then parse as a number
/// </summary>
private void ParseNumber (ParseStream stream, int sign)
{
bool base60 = false; // Base 60 with ':'
bool afterDecimal = false; // Before or after the decimal point
double factor = 0.1;
double part; // If base60 different parts, else output value
// Set sign
content = sign >= 0 ? 1 : -1;
// First char must 0-9
if (stream.Char >= '0' && stream.Char <= '9')
{
part = (uint) (stream.Char - '0');
stream.Next (true);
}
else
throw new ParseException (stream,
"No valid float: Invalid first character of float: " + stream.Char);
while (! stream.EOF)
{
// Decimal
if (stream.Char >= '0' && stream.Char <= '9')
if (afterDecimal)
{
part += (uint) (stream.Char - '0') * factor;
factor *= 0.1;
}
else
part = (part * 10) + (uint) (stream.Char - '0');
// Base60 detected
else if (stream.Char == ':')
{
if ( ! base60) // First time
{
content *= part; // Multiply to get sign
part = 0;
base60 = true; // We are now sure base 60
}
else
{
if (part > 59)
throw new ParseException (stream,
"Part of base 60 can't be larger then 59");
content = (60 * content) + part;
part = 0;
}
}
// If first '.', then after decimal, else it is ignored if not in Base60
else if ( (!base60 || (base60 && !afterDecimal)) && stream.Char == '.' )
afterDecimal = true;
// Determine scientific notation
else if ( (stream.Char == 'E' || stream.Char == 'e') && ! base60 )
{
stream.Next (true);
content *= Math.Pow (10, ParseScient (stream));
}
// Ignore underscores if before the decimal point, special case if base 60
else if ((!afterDecimal || (afterDecimal && base60)) && stream.Char != '_')
throw new ParseException (stream, "Unknown char");
stream.Next (true);
}
// Add last part of base to content
if (base60)
content = (60 * content) + part;
else
content *= part; // Multiply to get sign
}
/// <summary> Parses the exponential part of the float </summary>
private static long ParseScient (ParseStream stream)
{
ulong output = 0;
short sign;
if (stream.Char == '-')
sign = -1;
else if (stream.Char == '+')
sign = 1;
else
throw new ParseException (stream,
"Excepted + or - for the exponential part");
stream.Next (true);
while (! stream.EOF)
{
if (stream.Char >= '0' && stream.Char <= '9')
output = (10 * output) + (uint) stream.Char - '0';
else
throw new ParseException (stream,
"Unexepted char in exponential part: >" +
stream.Char + "<");
stream.Next (true);
}
return sign * (long) output;
}
/// <summary> Content </summary>
public double Content
{
get { return content; }
set { content = value; }
}
/// <summary> To string </summary>
public override string ToString()
{
return "[FLOAT]" + content + "[/FLOAT]";
}
/// <summary> Write to a YAML node </summary>
protected internal override void Write (WriteStream stream)
{
if (content.Equals( double.NaN ))
stream.Append ("!!float .NaN");
else if (content.Equals( double.NegativeInfinity ))
stream.Append ("!!float -.Inf");
else if (content.Equals( double.PositiveInfinity ))
stream.Append ("!!float +.Inf");
else stream.Append ("!!float " + content);
}
}
}

266
thirdparty/yaml/Integer.cs vendored Normal file
View File

@@ -0,0 +1,266 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
namespace Yaml
{
/// <summary>
/// Class for storing a Yaml Integer node
/// uri: tag:yaml.org,2002:int
/// </summary>
public class Integer : Scalar
{
private long content;
/// <summary> New Integer </summary>
public Integer (long val) :
base ("tag:yaml.org,2002:int", NodeType.Integer)
{
content = val;
}
/// <summary> Content </summary>
public long Content
{
get { return content; }
set { content = value; }
}
/// <summary> Parse an integer </summary>
public Integer (ParseStream stream) :
base ("tag:yaml.org,2002:int", NodeType.Integer)
{
short sign = 1; // Positive sign by default
// Negative sign
if (stream.Char == '-')
{
sign = -1;
stream.Next ();
}
// Positive sign
else if (stream.Char == '+')
stream.Next ();
try
{
// Determine base
if (stream.Char == '0')
{
stream.Next ();
// Base 2
if (stream.Char == 'b')
{
stream.Next ();
content = ParseBase (stream, 2, sign);
return;
}
// Base 16
else if (stream.Char == 'x')
{
stream.Next ();
content = Parse16 (stream, sign);
return;
}
// Base 8
else
{
content = ParseBase (stream, 8, sign);
return;
}
}
// Other base
stream.BuildLookaheadBuffer ();
// First, try to parse with base 10
try
{
content = ParseBase (stream, 10, sign);
stream.DestroyLookaheadBuffer ();
return;
}
catch { }
// If not parseable with base 10, then try base 60
stream.RewindLookaheadBuffer ();
stream.DestroyLookaheadBuffer ();
content = Parse60 (stream, sign);
}
catch (Exception ex)
{
throw new ParseException (stream, ex.ToString ());
}
}
/// <summary> Hexadecimal string </summary>
private static long Parse16 (ParseStream stream, short sign)
{
uint output = 0;
while (! stream.EOF)
{
// 0 .. 9
if (stream.Char >= '0' && stream.Char <= '9')
{
output = (output * 16) + (uint) (stream.Char - '0');
OverflowTest (output, sign);
}
// a .. f
else if (stream.Char >= 'a' && stream.Char <= 'f')
{
output = (output * 16) + (uint) (stream.Char - 'a') + 10;
OverflowTest (output, sign);
}
// A .. F
else if (stream.Char >= 'A' && stream.Char <= 'F')
{
output = (output * 16) + (uint) (stream.Char - 'A') + 10;
OverflowTest(output, sign);
}
// Ignore underscores, other chars are not allowed
else if (stream.Char != '_')
throw new Exception ("Unknown char in base 16");
stream.Next ();
}
return (long) (sign * output);
}
/// <summary> Parses a string with a given base (maximum 10) </summary>
/// <remarks>
/// This is not completly correct. For base10 the first char may not be a '_'
/// The other bases allow this...
/// </remarks>
private static long ParseBase (ParseStream stream, uint basis, short sign)
{
// Base must be <= 10
if (basis > 10)
throw new Exception ("Base to large. Maximum 10");
ulong output = 0;
char max = (char) ((basis - 1) + (int) '0');
// Parse
while (! stream.EOF)
{
// Decimal
if (stream.Char >= '0' && stream.Char <= max)
{
output = (output * basis) + (uint) (stream.Char - '0');
OverflowTest (output, sign);
}
// Ignore underscores, but other chars are not allowed
// see remarks
else if (stream.Char != '_')
throw new Exception ("Unknown char in base " + basis);
stream.Next ();
}
return sign * (long) output;
}
/// <summary> Parses a string with base 60, without sign </summary>
private static long Parse60 (ParseStream stream, short sign)
{
ulong output = 0;
// Parse
ulong part = 0;
bool firstPart = true; // Only the first part can be larger then 59
while (! stream.EOF)
{
// Decimal
if (stream.Char >= '0' && stream.Char <= '9')
part = (part * 10) + (uint) (stream.Char - '0');
// New part
else if (stream.Char == ':')
{
// Only the first part can be largen then 60
if ( ! firstPart)
if (part >= 60)
throw new
Exception ("Part of base 60 scalar is too large (max. 59)");
else
firstPart = false;
output = (output * 60) + part;
OverflowTest(output, sign);
part = 0;
}
// Ignore underscores, other chars are not allowed
else if (stream.Char != '_')
throw new Exception ("Unknown char in base 16");
stream.Next ();
}
// Add last part to the output
if (!firstPart)
if (part >= 60)
throw new Exception (
"Part of base 60 scalar is too large (max. 59)");
else
firstPart = false;
output = (output * 60) + part;
OverflowTest (output, sign);
return sign * (long) output;
}
/// <summary> Test that the unsigned int fits in a signed int </summary>
/// <param name="number"> Value to test </param>
/// <param name="sign"> Sign of the int where it must fit in </param>
private static void OverflowTest (ulong number, short sign)
{
// NOTE: Negatif numbers can be one larger
if ((sign >= 0 && number > System.Int64.MaxValue) ||
(sign < 0 && number > (ulong) System.Int64.MaxValue + 1) )
throw new Exception ("YAML overflow exception");
}
/// <summary> To String </summary>
public override string ToString ()
{
return "[INTEGER]" + content.ToString () + "[/INTEGER]";
}
/// <summary> Write to YAML </summary>
protected internal override void Write (WriteStream stream)
{
stream.Append (content.ToString ());
}
}
}

292
thirdparty/yaml/Mapping.cs vendored Normal file
View File

@@ -0,0 +1,292 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
using System.Collections;
// TODO Access to nodes via the [] overload
namespace Yaml
{
/// <summary>
/// Yaml Mapping
/// </summary>
public class Mapping : Node
{
private ArrayList childNodes = new ArrayList ();
/// <summary> New empty mapping </summary>
public Mapping () : base ("tag:yaml.org,2002:map", NodeType.Mapping) { }
/// <summary> New mapping from a mappingnode array </summary>
public Mapping (MappingNode [] nodes) :
base ("tag:yaml.org,2002:map", NodeType.Mapping)
{
foreach (MappingNode node in nodes)
childNodes.Add (node);
}
/// <summary> Parse a mapping </summary>
public Mapping (ParseStream stream) :
base ("tag:yaml.org,2002:map", NodeType.Mapping)
{
// Mapping with eplicit key, (implicit mappings are threaded
// in Node.cs)
if (stream.Char == '?')
{
// Parse recursively
do {
Node key, val;
// Skip over '?'
stream.Next ();
stream.SkipSpaces ();
// Parse recursively. The false param avoids
// looking recursively for implicit mappings.
stream.StopAt (new char [] {':'});
stream.Indent ();
key = Parse (stream, false);
stream.UnIndent ();
stream.DontStop ();
// Parse recursively. The false param avoids
// looking for implit nodes
if (stream.Char == ':')
{
// Skip over ':'
stream.Next ();
stream.SkipSpaces ();
// Parse recursively
stream.Indent ();
val = Parse (stream);
stream.UnIndent ();
}
else
val = new Null ();
AddMappingNode (key, val);
// Skip possible newline
// NOTE: this can't be done by the drop-newline
// method since this is not the end of a block
if (stream.Char == '\n')
stream.Next ();
}
while ( ! stream.EOF && stream.Char == '?');
}
// Inline mapping
else if (stream.Char == '{')
{
// Override the parent's stop chars, never stop
stream.StopAt (new char [] { });
// Skip '{'
stream.Next ();
do {
Node key, val;
// Skip '?'
// (NOTE: it's not obligated to use this '?',
// especially because this is an inline mapping)
if (stream.Char == '?')
{
stream.Next ();
stream.SkipSpaces ();
}
// Parse recursively the key
stream.StopAt (new char [] {':', ',', '}'});
stream.Indent ();
key = Parse (stream, false);
stream.UnIndent ();
stream.DontStop ();
// Value
if (stream.Char == ':')
{
// Skip colon
stream.Next ();
stream.SkipSpaces ();
// Parse recursively the value
stream.StopAt (new char [] {'}', ','});
stream.Indent ();
val = Parse (stream, false);
stream.UnIndent ();
stream.DontStop ();
}
else
val = new Null ();
AddMappingNode (key, val);
// Skip comma (key sepatator)
if (stream.Char != '}' && stream.Char != ',')
{
stream.DontStop ();
throw new ParseException (stream, "Comma expected in inline sequence");
}
if (stream.Char == ',')
{
stream.Next ();
stream.SkipSpaces ();
}
}
while ( ! stream.EOF && stream.Char != '}' );
// Re-accept the parent's stop chars
stream.DontStop ();
// Skip '}'
if (stream.Char == '}')
stream.Next ();
else
throw new ParseException (stream, "Inline mapping not closed");
}
}
/// <summary> Add a node to this mapping </summary>
public void AddMappingNode (Node key, Node val)
{
childNodes.Add (new MappingNode (key, val));
}
/// <summary> Add a node to this mapping </summary>
public void AddMappingNode (MappingNode node)
{
if (node != null)
childNodes.Add (node);
else
childNodes.Add (new MappingNode (null, null));
}
/// <summary> Number of mappings </summary>
public int Count
{
get { return childNodes.Count; }
}
/// <summary> To String </summary>
public override string ToString ()
{
string result = "";
foreach (MappingNode node in childNodes)
result += node.ToString ();
return "[MAPPING]" + result + "[/MAPPING]";
}
/// <summary> Node info </summary>
public override Node Info ()
{
Mapping mapping = new Mapping ();
mapping.AddMappingNode (new String ("kind"), new String ("mapping"));
mapping.AddMappingNode (new String ("type_id"), new String (URI));
Mapping childs = new Mapping ();
int i = 0;
foreach (MappingNode child in childNodes)
{
Sequence keyvaluepair = new Sequence ();
keyvaluepair.AddNode (child.Key.Info () );
keyvaluepair.AddNode (child.Value.Info ());
childs.AddMappingNode (new String ("key_" + i), keyvaluepair);
i ++;
}
mapping.AddMappingNode (new String ("value"), childs);
return mapping;
}
/// <summary> Write to YAML </summary>
protected internal override void Write (WriteStream stream)
{
foreach (MappingNode node in childNodes)
{
stream.Append ("? ");
stream.Indent ();
Yaml.Node key = node.Key;
key.Write (stream);
stream.UnIndent ();
stream.Append (": ");
stream.Indent ();
node.Value.Write (stream);
stream.UnIndent ();
}
}
}
/// <summary>
/// Node pair (key, value) of a mapping
/// </summary>
public class MappingNode
{
private Node key;
private Node val;
/// <summary> Create a new mappingnode </summary>
public MappingNode (Node key, Node val)
{
if (key == null) key = new Null ();
if (val == null) val = new Null ();
this.key = key;
this.val = val;
}
/// <summary> Key property </summary>
public Node Key
{
get { return key; }
set { key = (value == null ? new Null () : value); }
}
/// <summary> Value property </summary>
public Node Value
{
get { return val; }
set { val = (value == null ? new Null () : value); }
}
/// <summary> To String </summary>
public override string ToString ()
{
return
"[KEY]" + key.ToString () + "[/KEY]" +
"[VAL]" + val.ToString () + "[/VAL]";
}
}
}

469
thirdparty/yaml/Node.cs vendored Normal file
View File

@@ -0,0 +1,469 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
#define UNSTABLE
#define SUPPORT_EXPLICIT_TYPES
#define SUPPORT_IMPLICIT_MAPPINGS
using System;
using System.Text;
using System.Collections;
using System.IO;
namespace Yaml
{
/// <summary>
/// Kind of node, used to determine the type of node.
/// </summary>
public enum NodeType
{
/// <summary>A Yaml mapping - collection type</summary>
Mapping,
/// <summary>A Yaml sequence - collection type</summary>
Sequence,
/// <summary>A Yaml binary scalar </summary>
Binary,
/// <summary>A Yaml boolean scalar </summary>
Boolean,
/// <summary>A Yaml float scalar </summary>
Float,
/// <summary>A Yaml integer scalar </summary>
Integer,
/// <summary>A Yaml null scalar </summary>
Null,
/// <summary>A Yaml string scalar </summary>
String,
/// <summary>A Yaml timestamp scalar </summary>
Timestamp
};
/// <summary>
/// Node in the Yaml tree
/// </summary>
public abstract class Node
{
/// <summary> The uri given by http://yaml.org/type/ </summary>
protected readonly string uri;
/// <summary> Determines wich node we are talking about </summary>
protected NodeType nodetype;
/// <summary> Node Constructor </summary>
/// <param name="uri"> URI of the node </param>
/// <param name="nodetype"> The type of node that we want to store </param>
public Node (string uri, NodeType nodetype)
{
this.uri = uri;
this.nodetype = nodetype;
}
/// <summary> Parse a Yaml string and return a Yaml tree </summary>
public static Node Parse (string lines)
{
StringReader reader = new StringReader (lines);
Node node = Parse (new ParseStream (reader));
reader.Close ();
return node;
}
/// <summary> Parse a Yaml string from a textreader and return a Yaml tree </summary>
public static Node Parse (TextReader textreader)
{
return Parse (new ParseStream (textreader));
}
/// <summary> Return a Yaml string </summary>
public string Write ()
{
StringWriter stringWriter = new StringWriter ();
WriteStream writeStream = new WriteStream (stringWriter);
Write (writeStream);
stringWriter.Close ();
return stringWriter.ToString ();
}
/// <summary>
/// Parse a Yaml string from a textfile and return a Yaml tree
/// </summary>
public static Node FromFile (string filename)
{
// Open YAML file
StreamReader reader = File.OpenText (filename);
ParseStream parsestream = new ParseStream (reader);
// Parse
Node node = Parse (parsestream);
// Close YAML file
reader.Close ();
return node;
}
/// <summary>
/// Write a YAML tree to a file using UTF-8 encoding
/// </summary>
public void ToFile (string filename)
{
ToFile (filename, Encoding.UTF8);
}
/// <summary>
/// Write a YAML tree to a file
/// </summary>
public void ToFile (string filename, Encoding enc)
{
// Open YAML file
StreamWriter writer = new StreamWriter (filename, false, enc);
WriteStream writestream = new WriteStream (writer);
// Write
Write (writestream);
// Close YAML file
writer.Close ();
}
/// <summary> Parse function </summary>
protected static Node Parse (ParseStream stream) { return Parse (stream, true); }
/// <summary> Internal parse method </summary>
/// <param name="parseImplicitMappings">
/// Avoids ethernal loops while parsing implicit mappings. Implicit mappings are
/// not rocognized by a leading character. So while trying to parse the key of
/// something we think that could be a mapping, we're sure that if it is a mapping,
/// the key of this implicit mapping is not a mapping itself.
///
/// NOTE: Implicit mapping still belong to unstable code and require the UNSTABLE and
/// IMPLICIT_MAPPINGS preprocessor flags.
/// </param>
/// <param name="stream"></param>
protected static Node Parse (ParseStream stream, bool parseImplicitMappings)
{
// ----------------
// Skip Whitespace
// ----------------
if (! stream.EOF)
{
// Move the firstindentation pointer after the whitespaces of this line
stream.SkipSpaces ();
while (stream.Char == '\n' && ! stream.EOF)
{
// Skip newline and next whitespaces
stream.Next ();
stream.SkipSpaces ();
}
}
// -----------------
// No remaining chars (Null/empty stream)
// -----------------
if (stream.EOF)
return new Null ();
// -----------------
// Explicit type
// -----------------
#if SUPPORT_EXPLICIT_TYPES
stream.BuildLookaheadBuffer ();
char a = '\0', b = '\0';
a = stream.Char; stream.Next ();
b = stream.Char; stream.Next ();
// Starting with !!
if (a == '!' && b == '!' && ! stream.EOF)
{
stream.DestroyLookaheadBuffer ();
// Read the tagname
string tag = "";
while (stream.Char != ' ' && stream.Char != '\n' && ! stream.EOF)
{
tag += stream.Char;
stream.Next ();
}
// Skip Whitespace
if (! stream.EOF)
{
stream.SkipSpaces ();
while (stream.Char == '\n' && ! stream.EOF)
{
stream.Next ();
stream.SkipSpaces ();
}
}
// Parse
Node n;
switch (tag)
{
// Mappings and sequences
// NOTE:
// - sets are mappings without values
// - Ordered maps are ordered sequence of key: value
// pairs without duplicates.
// - Pairs are ordered sequence of key: value pairs
// allowing duplicates.
// TODO: Create new datatypes for omap and pairs
// derived from sequence with a extra duplicate
// checking.
case "seq": n = new Sequence (stream); break;
case "map": n = new Mapping (stream); break;
case "set": n = new Mapping (stream); break;
case "omap": n = new Sequence (stream); break;
case "pairs": n = new Sequence (stream); break;
// Scalars
//
// TODO: do we have to move this to Scalar.cs
// in order to get the following working:
//
// !!str "...": "..."
// !!str "...": "..."
case "timestamp": n = new Timestamp (stream); break;
case "binary": n = new Binary (stream); break;
case "null": n = new Null (stream); break;
case "float": n = new Float (stream); break;
case "int": n = new Integer (stream); break;
case "bool": n = new Boolean (stream); break;
case "str": n = new String (stream); break;
// Unknown data type
default:
throw new Exception ("Incorrect tag '!!" + tag + "'");
}
return n;
}
else
{
stream.RewindLookaheadBuffer ();
stream.DestroyLookaheadBuffer ();
}
#endif
// -----------------
// Sequence
// -----------------
if (stream.Char == '-' || stream.Char == '[')
return new Sequence (stream);
// -----------------
// Mapping
// -----------------
if (stream.Char == '?' || stream.Char == '{')
return new Mapping (stream);
// -----------------
// Try implicit mapping
// -----------------
// This are mappings which are not preceded by a question
// mark. The keys have to be scalars.
#if (UNSTABLE && SUPPORT_IMPLICIT_MAPPINGS)
// NOTE: This code can't be included in Mapping.cs
// because of the way we are using to rewind the buffer.
Node key, val;
if (parseImplicitMappings)
{
// First Key/value pair
stream.BuildLookaheadBuffer ();
stream.StopAt (new char [] {':'});
// Keys of implicit mappings can't be sequences, or other mappings
// just look for scalars
key = Scalar.Parse (stream, false);
stream.DontStop ();
Console.WriteLine ("key: " + key);
// Followed by a colon, so this is a real mapping
if (stream.Char == ':')
{
stream.DestroyLookaheadBuffer ();
Mapping mapping = new Mapping ();
// Skip colon and spaces
stream.Next ();
stream.SkipSpaces ();
// Parse the value
Console.Write ("using buffer: " + stream.UsingBuffer ());
stream.Indent ();
Console.Write ("using buffer: " + stream.UsingBuffer ());
// val = Parse (stream, false);
Console.Write ("<<");
while (!stream.EOF) {Console.Write (stream.Char);stream.Next (true);}
Console.Write (">>");
val = new String (stream);
Console.Write ("using buffer: " + stream.UsingBuffer ());
stream.UnIndent ();
Console.Write ("using buffer: " + stream.UsingBuffer ());
Console.Write ("<<");
while (!stream.EOF) {Console.Write (stream.Char);stream.Next (true);}
Console.Write (">>");
Console.WriteLine ("val: " + val);
mapping.AddMappingNode (key, val);
// Skip possible newline
// NOTE: this can't be done by the drop-newline
// method since this is not the end of a block
while (stream.Char == '\n')
stream.Next (true);
// Other key/value pairs
while (! stream.EOF)
{
stream.StopAt (new char [] {':'} );
stream.Indent ();
key = Scalar.Parse (stream);
stream.UnIndent ();
stream.DontStop ();
Console.WriteLine ("key 2: " + key);
if (stream.Char == ':')
{
// Skip colon and spaces
stream.Next ();
stream.SkipSpaces ();
// Parse the value
stream.Indent ();
val = Parse (stream);
stream.UnIndent ();
Console.WriteLine ("val 2: " + val);
mapping.AddMappingNode (key, val);
}
else // TODO: Is this an error?
{
// NOTE: We can't recover from this error,
// the last buffer has been destroyed, so
// rewinding is impossible.
throw new ParseException (stream,
"Implicit mapping without value node");
}
// Skip possible newline
while (stream.Char == '\n')
stream.Next ();
}
return mapping;
}
stream.RewindLookaheadBuffer ();
stream.DestroyLookaheadBuffer ();
}
#endif
// -----------------
// No known data structure, assume this is a scalar
// -----------------
Scalar scalar = Scalar.Parse (stream);
// Skip trash
while (! stream.EOF)
stream.Next ();
return scalar;
}
/// <summary>
/// URI of this node, according to the YAML documentation.
/// </summary>
public string URI
{
get { return uri; }
}
/// <summary>
/// Kind of node: mapping, sequence, string, ...
/// </summary>
public NodeType Type
{
get { return nodetype; }
}
/// <summary>
/// Writes a Yaml tree back to a file or stream
/// </summary>
/// <remarks>
/// should not be called from outside the parser. This method
/// is only public from inside the Sequence and Mapping Write
/// methods.
/// </remarks>
/// <param name="stream">Were the output data go's</param>
protected internal virtual void Write (WriteStream stream) {}
/// <summary>
/// The ToString method here, and in all the classses
/// derived from this class, is used mainly for debugging
/// purpose. ToString returns a xml-like textual representation
/// of the objects. It's very useful to see how a Yaml document
/// has been parsed because of the disambiguous representation
/// of this notation.
/// </summary>
public override abstract string ToString ();
/// <summary>
/// Node info returns a YAML node and is also mostly used
/// for debugging the parser. This could be used for
/// traversing the meta-info of another YAML tree
/// </summary>
public abstract Node Info ();
}
}

100
thirdparty/yaml/Null.cs vendored Normal file
View File

@@ -0,0 +1,100 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
namespace Yaml
{
/// <summary>
/// Class for storing a Yaml Null node
/// tag:yaml.org,2002:null
/// </summary>
public class Null : Scalar
{
/// <summary> Null Constructor </summary>
public Null () : base ("tag:yaml.org,2002:null", NodeType.Null) { }
/// <summary> Parse a null node </summary>
public Null (ParseStream stream) :
base ("tag:yaml.org,2002:null", NodeType.Null)
{
// An empty string is a valid null node
if (stream.EOF)
return;
else
{
// Read the first 4 chars
char [] chars = new char [8];
int length = 0;
for (int i = 0; i < chars.Length && ! stream.EOF; i ++)
{
chars [i] = stream.Char;
length ++;
stream.Next ();
}
// Compare
if (length == 1)
{
string s = "" + chars [0];
// Canonical notation
if (s == "~")
return;
}
if (length == 4)
{
string s = "" + chars [0] + chars [1] + chars [2] + chars [3];
// null, Null, NULL
if (s == "NULL" || s == "Null" || s == "null")
return;
}
throw new ParseException (stream, "Not NULL");
}
}
/// <summary> Content property </summary>
public object Content
{
get { return null; }
}
/// <summary> To String </summary>
public override string ToString ()
{
return "[NULL]~[/NULL]";
}
/// <summary> Write to YAML </summary>
protected internal override void Write (WriteStream stream)
{
stream.Append ("~");
}
}
}

63
thirdparty/yaml/ParseException.cs vendored Normal file
View File

@@ -0,0 +1,63 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
namespace Yaml
{
/// <summary>
/// ParseException, could be thrown while parsing a YAML stream
/// </summary>
public class ParseException : Exception
{
// Line of the Yaml stream/file where the fault occures
private readonly int linenr;
/// <summary> Constructor </summary>
/// <param name="stream"> The parse stream (contains the line number where it went wrong) </param>
/// <param name="message"> Info about the exception </param>
public ParseException (ParseStream stream, string message) :
base ("Parse error near line " + stream.CurrentLine + ": " + message)
{
this.linenr = stream.CurrentLine;
}
/// <summary> Constructor </summary>
/// <param name="stream"> The parse stream (contains the line number where it went wrong) </param>
/// <param name="child"> The exception that is for example throwed again </param>
public ParseException (ParseStream stream, Exception child) :
base ( "Parse error near line " + stream.CurrentLine, child )
{
this.linenr = stream.CurrentLine;
}
/// <summary> The line where the error occured </summary>
public int LineNumber
{
get { return linenr; }
}
}
}

899
thirdparty/yaml/ParseStream.cs vendored Normal file
View File

@@ -0,0 +1,899 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
using System.Collections;
using System.IO;
namespace Yaml
{
/// <summary>
/// The Preprocessor class
/// Given a character stream, this class will
/// walk through that stream.
/// NOTE: Comments are not longer skipped at this level,
/// but now in the last level instead. (because of
/// problems with comments within the buffer)
/// NOTE: Null characters are skipped, read nulls should
/// be escaped. \0
/// </summary>
public class Preprocessor
{
private TextReader stream;
private int currentline = 1; // Line numbers start with one
private bool literal = false; // Parse literal/verbatim
/// <summary> Constuctor </summary>
public Preprocessor (TextReader stream)
{
this.stream = stream;
}
/// <summary> Jump to the next character </summary>
public void Next ()
{
// Transition to the next line?
if (Char == '\n')
currentline ++;
// Not yet passed the end of file
if (! EOF)
{
// Next
stream.Read ();
// Skip null chars
while (stream.Peek () == '\0')
stream.Read ();
}
}
/// <summary> Start parsing literal </summary>
public void StartLiteral ()
{
literal = true;
}
/// <summary> Stop parsing literal </summary>
public void StopLiteral ()
{
if (literal)
literal = false;
else
throw new Exception ("Called StopLiteral without " +
"calling StartLiteral before");
}
/// <summary> Literal parsing </summary>
public bool Literal
{
get { return literal; }
// No set method, setting must by using the {Start,Stop}Literal
// methods. They provide mory symmetry in the parser.
}
/// <summary> The current character </summary>
public char Char
{
get
{
if (EOF)
return '\0';
else
return (char) stream.Peek ();
}
}
/// <summary> End of file/stream </summary>
public bool EOF
{
get { return stream.Peek () == -1; }
}
/// <summary> Returns the current line number </summary>
public int CurrentLine
{
get { return currentline; }
}
}
/// <summary>
/// The indentation processor,
/// This class divides the stream from the preprocessor
/// in substreams, according to the current level
/// of indentation.
/// </summary>
public class IndentationProcessor : Preprocessor
{
// While trying to readahead over whitespaces,
// This is how many whitespaces were skipped that weren't yet read
private int whitespaces = 0;
private int whitespacesSkipped = 0;
// Reached the end
private bool endofstream = false;
// Current level of indentation
private int indentationLevel = 0;
private bool indentationRequest = false;
private Stack indentationStack = new Stack ();
/// <summary> Constructor </summary>
public IndentationProcessor (TextReader stream) : base (stream) { }
/// <summary>
/// Request an indentation. When we meet a \n and the following
/// line is more indented then the current indentationlever, then
/// save this request
/// </summary>
public void Indent ()
{
if (Literal)
throw new Exception ("Cannot (un)indent while literal parsing " +
"has been enabled");
else
{
// Handle double requests
if (indentationRequest)
indentationStack.Push ((object) indentationLevel);
// Remember
indentationRequest = true;
}
}
/// <summary> Cancel the last indentation </summary>
public void UnIndent ()
{
if (Literal)
throw new Exception ("Cannot (un)indent while literal parsing " +
"has been enabled");
else
{
// Cancel the indentation request
if (indentationRequest)
{
indentationRequest = false;
return;
}
// Unpop the last indentation
if (indentationStack.Count > 0)
indentationLevel = (int) indentationStack.Pop ();
// When not indented
else
throw new Exception ("Unable to unindent a not indented parse stream");
// Parent stream not yet finished
// Skipped whitespaces in the childstream (at that time assumed to be
// indentation) can become content.
if (endofstream && indentationLevel <= whitespaces)
{
endofstream = false;
if (whitespaces == this.indentationLevel)
whitespaces = 0;
}
}
}
/// <summary> Go to the next parsable char in the stream </summary>
public new void Next ()
{
if (endofstream)
return;
// Are there still whitespaces to skip
if (whitespaces > 0)
{
// All whitespaces were skipped
if (whitespaces == whitespacesSkipped + this.indentationLevel)
whitespaces = 0;
// Else, skip one
else
{
whitespacesSkipped ++;
return;
}
}
// All whitespaces have been skipped
if (whitespaces == 0 && ! base.EOF)
{
// When a char is positioned at a newline '\n',
// then skip 'indentation' chars and continue.
// When there are less spaces available, then we are
// at the end of the (sub)stream
if (! base.EOF && base.Char == '\n' && ! Literal)
{
// Skip over newline
base.Next ();
// Skip indentation (and count the spaces)
int i = 0;
while (! base.EOF && base.Char == ' ' && i < this.indentationLevel)
{
i ++;
base.Next ();
}
// Not enough indented?
if (i < this.indentationLevel)
{
// Remember the number of whitespaces, and
// continue at the moment that the indentationlevel
// drops below this number of whitespaces
whitespaces = i;
whitespacesSkipped = 0;
endofstream = true;
return;
}
// Indentation request
else if (indentationRequest)
{
while (! base.EOF && base.Char == ' ')
{
i ++;
base.Next ();
}
// Remember current indentation
indentationStack.Push ((object) indentationLevel);
indentationRequest = false;
// Number of spaces before this line is equal to the
// current level of indentation, so the
// indentation request cannot be fulfilled
if (indentationLevel == i)
{
whitespaces = i;
whitespacesSkipped = 0;
endofstream = true;
return;
}
else // i > indentationLevel
indentationLevel = i;
}
}
else
// Next char
base.Next ();
}
else
endofstream = true;
}
/// <summary> Reads the current char from the stream </summary>
public new char Char
{
get
{
// In case of spaces
if (whitespaces > 0)
return ' ';
// \0 at the end of the stream
else if (base.EOF || endofstream)
return '\0';
// Return the char
else
return base.Char;
}
}
/// <summary> End of File/Stream </summary>
public new bool EOF
{
get { return endofstream || base.EOF; }
}
}
/// <summary>
/// Third stream processor, this class adds a buffer with a maximum
/// size of 1024 chars. The buffer cannot encapsulate multiple lines
/// because that could do strange things while rewinding/indenting
/// </summary>
public class BufferStream : IndentationProcessor
{
LookaheadBuffer buffer = new LookaheadBuffer ();
// When the buffer is used, this is true
private bool useLookaheadBuffer = false;
// In use, but requested to destroy. The buffer will keep to exists
// (only in this layer) and shall be destroyed when we move out of
// the buffer
private bool destroyRequest = false;
/// <summary> Constructor </summary>
public BufferStream (TextReader stream) : base (stream) { }
/// <summary> Build lookahead buffer </summary>
public void BuildLookaheadBuffer ()
{
if (Literal)
throw new Exception ("Cannot build a buffer while " +
"literal parsing is enabled");
else
{
// When the buffer is already in use
if (useLookaheadBuffer && ! destroyRequest)
throw new Exception ("Buffer already exist, cannot rebuild " +
"the buffer at this level");
// Cancel the destroy request
if (destroyRequest)
destroyRequest = false;
// Or start a new buffer
else
{
buffer.Clear ();
buffer.Append (Char);
}
useLookaheadBuffer = true;
}
}
/// <summary> Move to the next character in the parse stream. </summary>
public new void Next ()
{
// End of file (This check is not really necessary because base.next
// would skip this anyway)
if (EOF) return;
// When it's not allowed to leave the buffer
if (useLookaheadBuffer && ! destroyRequest && ! NextInBuffer () )
return;
// When using the lookahead buffer
if (useLookaheadBuffer)
{
// Requested to destroy
if (destroyRequest)
{
// But not yet reached the end of the buffer
if (buffer.Position < buffer.LastPosition)
{
buffer.Position ++;
buffer.ForgetThePast ();
}
// Reached the end
else
{
buffer.Clear ();
useLookaheadBuffer = false;
destroyRequest = false;
base.Next ();
}
}
// Continue in the buffer
else
{
// We've been here before
if (buffer.Position < buffer.LastPosition)
buffer.Position ++;
// This is new to the buffer, but there is place
// to remember new chars
else if (
buffer.Position == buffer.LastPosition &&
! buffer.Full)
{
// Save the next char in the buffer
base.Next();
buffer.Append (base.Char);
}
// Otherwise, the buffer is full
else
throw new Exception ("buffer overflow");
}
}
// Not using the buffer
else
base.Next();
}
/// <summary> Returns true when using a buffer </summary>
public bool UsingBuffer ()
{
return useLookaheadBuffer && ! destroyRequest;
}
/// <summary>
/// Returns true when the next char will still be in the buffer
/// (after calling next)
/// </summary>
private bool NextInBuffer ()
{
return
// Using the buffer
useLookaheadBuffer &&
// Next char has been read before
(buffer.Position < buffer.LastPosition ||
// Or the next char will also be in the buffer
(Char != '\n' && ! base.EOF &&
// There is still unused space
! buffer.Full));
}
/// <summary> Destroys the current lookaheadbuffer, if there is one </summary>
public void DestroyLookaheadBuffer ()
{
if (useLookaheadBuffer && ! destroyRequest)
{
buffer.ForgetThePast ();
destroyRequest = true;
}
else
throw new Exception ("Called destroy buffer before building the buffer");
}
/// <summary> Rewind the buffer </summary>
public void RewindLookaheadBuffer ()
{
if (! useLookaheadBuffer || destroyRequest)
throw new Exception ("Cannot rewind the buffer. No buffer in use");
else
buffer.Rewind ();
}
/// <summary> The current character </summary>
public new char Char
{
get
{
// When using a buffer
if (useLookaheadBuffer)
return buffer.Char;
else
return base.Char;
}
}
/// <summary> End of stream/file </summary>
public new bool EOF
{
get
{
return
// When it's not allowed to run out of the buffer
(useLookaheadBuffer && ! destroyRequest && ! NextInBuffer () ) ||
// Not using the buffer, but the end of stream has been reached
(! useLookaheadBuffer && base.EOF);
}
}
/// <summary> Current position in the lookahead buffer </summary>
protected int LookaheadPosition
{
get
{
if (useLookaheadBuffer)
return buffer.Position;
else
throw new Exception ("Not using a lookahead buffer");
}
set
{
if (useLookaheadBuffer)
{
if (value >= 0 && value <= buffer.LastPosition)
buffer.Position = value;
else
throw new Exception ("Lookahead position not between 0 " +
"and the buffer size");
}
else
throw new Exception ("Not using a lookahead buffer");
}
}
}
/// <summary> Parsestream with multilever buffer </summary>
public class MultiBufferStream : BufferStream
{
private Stack bufferStack = new Stack (); // Top is current buffer start
/// <summary> Constructor </summary>
public MultiBufferStream (TextReader stream) : base (stream) { }
/// <summary> Destroy the current buffer </summary>
public new void BuildLookaheadBuffer ()
{
if (Literal)
throw new Exception ("Cannot build a buffer while " +
"literal parsing is enabled");
else
{
// Already using a buffer
if (base.UsingBuffer ())
// Remember the current position
bufferStack.Push ((object) base.LookaheadPosition);
// Otherwise, create a new buffer
else
{
// Remember the current position (= 0)
bufferStack .Push ((object) 0);
base.BuildLookaheadBuffer ();
}
}
}
/// <summary> Destroy the current buffer </summary>
public new void DestroyLookaheadBuffer ()
{
// Clear the buffer info when we runned out of the buffer,
if ( ! base.UsingBuffer () )
bufferStack.Clear ();
else
{
// Unpop the buffers start index
bufferStack.Pop ();
// Destroy it when the last buffer is gone
if (bufferStack.Count == 0)
base.DestroyLookaheadBuffer ();
}
}
/// <summary> Rewind the current buffer </summary>
public new void RewindLookaheadBuffer ()
{
if (base.UsingBuffer () )
base.LookaheadPosition = (int) bufferStack.Peek ();
else
throw new Exception ("Rewinding not possible. Not using a " +
"lookahead buffer.");
}
}
/// <summary>
/// Drop the comments
/// (This is disabled when literal parsing is enabled)
/// </summary>
public class DropComments : MultiBufferStream
{
/// <summary> Constructor </summary>
public DropComments (TextReader stream) : base (stream) { }
/// <summary> Move to the next character in the parse stream. </summary>
public new void Next ()
{
base.Next ();
// Skip comments
if (base.Char == '#' && ! Literal)
while (! base.EOF && base.Char != '\n')
base.Next ();
}
}
/// <summary>
/// This layer removes the trailing newline at the end of each (sub)stream
/// </summary>
public class DropTrailingNewline : DropComments
{
// One char buffer
private bool newline = false;
/// <summary> Constructor </summary>
public DropTrailingNewline (TextReader stream) : base (stream) { }
/// <summary> The current character </summary>
public new char Char
{
get
{
if (EOF)
return '\0';
else if (newline)
return '\n';
else
return base.Char;
}
}
/// <summary> End of File/Stream </summary>
public new bool EOF
{
get { return ! newline && base.EOF; }
}
/// <summary> Skip space characters </summary>
public int SkipSpaces ()
{
int count = 0;
while (Char == ' ')
{
Next ();
count ++;
}
return count;
}
/// <summary> Move to the next character in the parse stream. </summary>
public new void Next ()
{
Next (false);
}
/// <summary> Move to the next character in the parse stream. </summary>
/// <param name="dropLastNewLine"> Forget the last newline </param>
public void Next (bool dropLastNewLine)
{
if (newline)
newline = false;
else
{
base.Next ();
if (dropLastNewLine && ! base.EOF && Char == '\n')
{
base.Next ();
if (base.EOF)
newline = false;
else
newline = true;
}
}
}
}
/// <summary>
/// Stops parsing at specific characters, useful for parsing inline
/// structures like (for instance):
///
/// [aaa, bbb, ccc, {ddd: eee, "fff": ggg}]
/// </summary>
public class ParseStream : DropTrailingNewline
{
private Stack stopstack = new Stack ();
/// <summary> Constructor </summary>
public ParseStream (TextReader stream) : base (stream) { }
/// <summary> Set the characters where we should stop. </summary>
public void StopAt (char [] characters)
{
stopstack.Push (characters);
}
/// <summary> Unset the characters where we should stop. </summary>
public void DontStop ()
{
if (stopstack.Count > 0)
stopstack.Pop ();
else
throw new Exception ("Called DontStop without " +
"calling StopAt before");
}
/// <summary> True when we have to stop here </summary>
private bool StopNow
{
get {
if (stopstack.Count > 0)
foreach (char c in (char []) stopstack.Peek ())
if (c == base.Char)
return true;
return false;
}
}
/// <summary> Start parsing literal </summary>
public new void StartLiteral ()
{
base.StartLiteral ();
// Parsing literal disables stopping
StopAt (new Char [] { });
}
/// <summary> Stop parsing literal </summary>
public new void StopLiteral ()
{
base.StopLiteral ();
DontStop ();
}
/// <summary> Move to the next character in the parse stream. </summary>
public new void Next ()
{
Next (false);
}
/// <summary> Move to the next character in the parse stream. </summary>
public new void Next (bool dropLastNewLine)
{
if ( ! StopNow )
base.Next (dropLastNewLine);
}
/// <summary> The current character </summary>
public new char Char
{
get
{
if (StopNow)
return '\0';
else
return base.Char;
}
}
/// <summary> End of stream/file </summary>
public new bool EOF
{
get { return StopNow || base.EOF; }
}
}
/// <summary>
/// The lookahead buffer, used by the buffer layer in the parser
/// </summary>
class LookaheadBuffer
{
// The buffer array
private char [] buffer = new char [1024];
private int size = 0; // 0 = Nothing in the buffer
private int position = -1; // Current position
private int rotation = 0; // Start of circular buffer
/// <summary> Character at the current position </summary>
public char Char
{
get
{
if (size > 0)
return buffer [(position + rotation) % buffer.Length];
else
throw new Exception ("Trying to read from an emty buffer");
}
}
/// <summary> The current position </summary>
public int Position
{
get { return position; }
set
{
if (value >= 0 && value < size)
position = value;
else
throw new Exception ("Buffer position should be " +
"between zero and 'size' ");
}
}
/// <summary> The last possible postition which could be set </summary>
public int LastPosition
{
get { return size - 1; }
}
/// <summary>
/// The last possible position which could be set if
/// the buffer where full
/// </summary>
public int MaxPosition
{
get { return buffer.Length - 1; }
}
/// <summary> True when the buffer is full </summary>
public bool Full
{
get { return size == buffer.Length; }
}
/// <summary> Current buffer size </summary>
public int Size
{
get { return size; }
}
/// <summary> Append a character to the buffer </summary>
public void Append (char c)
{
// Appending is only possible when the current position is the
// last in the buffer
if (position < LastPosition)
throw new Exception ("Appending to buffer only possible " +
"when the position is the last");
// Buffer overflow
if (size == buffer.Length)
throw new Exception ("Buffer full");
// Append
position ++;
size ++;
buffer [(position + rotation) % buffer.Length] = c;
}
/// <summary> Rewind the buffer </summary>
public void Rewind ()
{
position = 0;
}
/// <summary> Reset (clear) the buffer </summary>
public void Clear ()
{
position = -1;
size = 0;
}
/// <summary> Move to the next character </summary>
public void Next ()
{
if (Position < Size)
Position ++;
else throw new Exception ("Cannot move past the buffer");
}
/// <summary>
/// Remove characters from the buffer before the current character
/// </summary>
public void ForgetThePast ()
{
// Size becomes smaller, characters before the position should be dropped
size -= position;
// The current position becomes the new startposition
rotation = (rotation + position + buffer.Length) % buffer.Length;
// The current position in the new buffer becomes zero
position = 0;
}
}
}

137
thirdparty/yaml/Scalar.cs vendored Normal file
View File

@@ -0,0 +1,137 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
#define SUPPORT_NULL_NODES
#define SUPPORT_INTEGER_NODES
#define SUPPORT_FLOAT_NODES
#define SUPPORT_BOOLEAN_NODES
#define SUPPORT_TIMESTAMP_NODES
using System;
namespace Yaml
{
/// <summary>
/// All Yaml scalars are derived from this class
/// </summary>
public abstract class Scalar : Node
{
/// <summary> Constructor </summary>
public Scalar (string uri, NodeType nodetype) : base (uri, nodetype) { }
/// <summary>
/// Parses a scalar
/// <list type="bullet">
/// <item>Integer</item>
/// <item>String</item>
/// <item>Boolean</item>
/// <item>Null</item>
/// <item>Timestamp</item>
/// <item>Float</item>
/// <item>Binary</item>
/// </list>
/// </summary>
/// <remarks>
/// Binary is only parsed behind an explicit !!binary tag (in Node.cs)
/// </remarks>
public static new Scalar Parse (ParseStream stream)
{
// -----------------
// Parse scalars
// -----------------
stream.BuildLookaheadBuffer ();
// Try Null
#if SUPPORT_NULL_NODES
try
{
Scalar s = new Null (stream);
stream.DestroyLookaheadBuffer ();
return s;
} catch { }
#endif
// Try boolean
#if SUPPORT_BOOLEAN_NODES
stream.RewindLookaheadBuffer ();
try
{
Scalar scalar = new Boolean (stream);
stream.DestroyLookaheadBuffer ();
return scalar;
}
catch { }
#endif
// Try integer
#if SUPPORT_INTEGER_NODES
stream.RewindLookaheadBuffer ();
try
{
Scalar scalar = new Integer (stream);
stream.DestroyLookaheadBuffer ();
return scalar;
} catch { }
#endif
// Try Float
#if SUPPORT_FLOAT_NODES
stream.RewindLookaheadBuffer ();
try
{
Scalar scalar = new Float (stream);
stream.DestroyLookaheadBuffer ();
return scalar;
}
catch { }
#endif
// Try timestamp
#if SUPPORT_TIMESTAMP_NODES
stream.RewindLookaheadBuffer ();
try {
Scalar scalar = new Timestamp (stream);
stream.DestroyLookaheadBuffer ();
return scalar;
} catch { }
#endif
// Other scalars are strings
stream.RewindLookaheadBuffer ();
stream.DestroyLookaheadBuffer ();
return new String (stream);
}
/// <summary> Node info </summary>
// TODO, move to each induvidual child
public override Node Info ()
{
Mapping mapping = new Mapping ();
mapping.AddMappingNode (new String ("kind"), new String ("scalar"));
mapping.AddMappingNode (new String ("type_id"), new String (URI));
mapping.AddMappingNode (new String ("value"), this);
return mapping;
}
}
}

197
thirdparty/yaml/Sequence.cs vendored Normal file
View File

@@ -0,0 +1,197 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
using System.Collections;
namespace Yaml
{
/// <summary>
/// Represents a Yaml Sequence
/// </summary>
public class Sequence : Node
{
private ArrayList childNodes = new ArrayList ();
/// <summary> New, empty sequence </summary>
public Sequence ( ) : base ("tag:yaml.org,2002:seq", NodeType.Sequence) { }
/// <summary> New sequence from a node array </summary>
public Sequence (Node [] nodes) :
base ("tag:yaml.org,2002:seq", NodeType.Sequence)
{
foreach (Node node in nodes)
childNodes.Add (node);
}
/// <summary> Parse a sequence </summary>
public Sequence (ParseStream stream) :
base ("tag:yaml.org,2002:seq", NodeType.Sequence)
{
// Is this really a sequence?
if (stream.Char == '-')
{
// Parse recursively
do {
// Override the parent's stop chars, never stop
stream.StopAt (new char [] { } );
// Skip over '-'
stream.Next ();
// Parse recursively
stream.Indent ();
AddNode (Parse (stream));
stream.UnIndent ();
// Re-accept the parent's stop chars
stream.DontStop ();
}
while ( ! stream.EOF && stream.Char == '-' );
}
// Or inline Sequence
else if (stream.Char == '[')
{
// Override the parent's stop chars, never stop
stream.StopAt (new char [] { });
// Skip '['
stream.Next ();
do {
stream.StopAt (new char [] {']', ','});
stream.Indent ();
AddNode (Parse (stream, false));
stream.UnIndent ();
stream.DontStop ();
// Skip ','
if (stream.Char != ']' && stream.Char != ',')
{
stream.DontStop ();
throw new ParseException (stream, "Comma expected in inline sequence");
}
if (stream.Char == ',')
{
stream.Next ();
stream.SkipSpaces ();
}
}
while ( ! stream.EOF && stream.Char != ']');
// Re-accept the parent's stop chars
stream.DontStop ();
// Skip ']'
if (stream.Char == ']')
stream.Next (true);
else
throw new ParseException (stream, "Inline sequence not closed");
}
// Throw an exception when not
else
throw new Exception ("This is not a sequence");
}
/// <summary> Add a node to this sequence </summary>
public void AddNode (Node node)
{
if (node != null)
childNodes.Add (node);
else
childNodes.Add (new Null ());
}
/// <summary> Get a node </summary>
public Node this [int index]
{
get
{
if (index > 0 && index < childNodes.Count)
return (Node) childNodes [index];
else
throw new IndexOutOfRangeException ();
}
}
/// <summary> The node array </summary>
public Node [] Nodes
{
get
{
Node [] nodes = new Node [childNodes.Count];
for (int i = 0; i < childNodes.Count; i ++)
nodes [i] = (Node) childNodes [i];
return nodes;
}
}
/// <summary> Textual destription of this node </summary>
public override string ToString ()
{
string result = "";
foreach (Node node in childNodes)
result += node.ToString ();
return "[SEQUENCE]" + result + "[/SEQUENCE]";
}
/// <summary> Node info </summary>
public override Node Info ()
{
Mapping mapping = new Mapping ();
mapping.AddMappingNode (new String ("kind"), new String ("sequence"));
mapping.AddMappingNode (new String ("type_id"), new String (URI));
Sequence childs = new Sequence ();
foreach (Node child in childNodes)
childs.AddNode (child.Info ());
mapping.AddMappingNode (new String ("value"), childs);
return mapping;
}
/// <summary> Write back to a stream </summary>
protected internal override void Write (WriteStream stream)
{
foreach (Node node in childNodes)
{
stream.Append ("- ");
stream.Indent ();
node.Write (stream);
stream.UnIndent ();
}
}
}
}

449
thirdparty/yaml/String.cs vendored Normal file
View File

@@ -0,0 +1,449 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
// Unicode support:
// http://www.yoda.arachsys.com/csharp/unicode.html
namespace Yaml
{
/// <summary>
/// Yaml String node
/// </summary>
public class String : Scalar
{
private string content;
private bool block = false;
private bool folded = false;
/// <summary> New string constructor </summary>
public String (string val) :
base ("tag:yaml.org,2002:str", NodeType.String)
{
content = val;
}
/// <summary> Parse a string </summary>
public String (ParseStream stream) :
base ("tag:yaml.org,2002:str", NodeType.String)
{
// set flags for folded or block scalar
if (stream.Char == '>') // TODO: '+' and '-' chomp chars
folded = true;
else if (stream.Char == '|')
block = true;
if (block || folded)
{
stream.Next ();
stream.SkipSpaces ();
}
// -----------------
// Folded Scalar
// -----------------
if (folded)
{
System.Text.StringBuilder builder = new System.Text.StringBuilder ();
// First line (the \n after the first line is always ignored,
// not replaced with a whitespace)
while (! stream.EOF && stream.Char != '\n')
{
builder.Append (stream.Char);
stream.Next ();
}
// Skip the first newline
stream.Next ();
// Next lines (newlines will be replaced by spaces in folded scalars)
while (! stream.EOF)
{
if (stream.Char == '\n')
builder.Append (' ');
else
builder.Append (stream.Char);
stream.Next (true);
}
content = builder.ToString ();
}
// -----------------
// Block Scalar (verbatim block without folding)
// -----------------
else if (block)
{
/*
Console.Write(">>");
while (! stream.EOF)
{
Console.Write (stream.Char);
stream.Next();
}
Console.Write("<<");
// */
System.Text.StringBuilder builder = new System.Text.StringBuilder ();
while (! stream.EOF)
{
builder.Append (stream.Char);
stream.Next (true);
}
content = builder.ToString ();
}
// String between double quotes
if (stream.Char == '\"')
content = ParseDoubleQuoted (stream);
// Single quoted string
else if (stream.Char == '\'')
content = ParseSingleQuoted (stream);
// String without quotes
else
content = ParseUnQuoted (stream);
}
/// <summary>
/// Parses a String surrounded with single quotes
/// </summary>
private string ParseSingleQuoted (ParseStream stream)
{
System.Text.StringBuilder builder = new System.Text.StringBuilder ();
// Start literal parsing
stream.StartLiteral ();
// Skip '''
stream.Next (true);
while (! stream.EOF)
{
if (stream.Char == '\'')
{
stream.Next ();
// Escaped single quote
if (stream.Char == '\'')
builder.Append (stream.Char);
// End of string
else
break;
}
else
builder.Append (stream.Char);
stream.Next ();
// Skip \'
if (stream.EOF)
{
stream.StopLiteral ();
throw new ParseException (stream,
"Single quoted string not closed");
}
}
// Stop literal parsing
stream.StopLiteral ();
return builder.ToString();
}
/// <summary>
/// Parses a String surrounded with double quotes
/// </summary>
private string ParseDoubleQuoted(ParseStream stream)
{
System.Text.StringBuilder builder = new System.Text.StringBuilder ();
// Skip '"'
stream.Next ();
// Stop at "
stream.StopAt (new char [] {'\"'} );
while (! stream.EOF)
{
if (stream.Char == '\n')
{
builder.Append (' ');
stream.Next ();
}
else
builder.Append (NextUnescapedChar (stream));
}
// Don't stop at "
stream.DontStop ();
// Skip '"'
if (stream.Char != '\"')
throw new ParseException (stream,
"Double quoted string not closed");
else
stream.Next (true);
return builder.ToString();
}
/// <summary>
/// Parses a String surrounded without nothing
/// </summary>
private string ParseUnQuoted(ParseStream stream)
{
System.Text.StringBuilder builder = new System.Text.StringBuilder ();
while (! stream.EOF)
builder.Append (NextUnescapedChar (stream));
// Trimming left
int count = 0;
while (count < builder.Length &&
(builder [count] == ' ' || builder [count] == '\t'))
count ++;
if (count >= 0)
builder.Remove (0, count);
// Trimming right
count = 0;
while (count < builder.Length &&
(builder [builder.Length - count - 1] == ' ' ||
builder [builder.Length - count - 1] == '\t'))
count ++;
if (count >= 0)
builder.Remove (builder.Length - count, count);
return builder.ToString();
}
/// <summary>
/// Reads a character from the stream, unescapes it,
/// and moves to the next character.
/// </summary>
private char NextUnescapedChar (ParseStream stream)
{
char c = stream.Char;
// If escaped
if (c == '\\')
{
// Never stop, every special character
// looses its meaning behind a backslash.
stream.StopAt (new Char [] { });
stream.Next (true);
c = stream.Char;
// ASCII null
if (c == '0') c = '\0';
// ASCII bell
else if (c == 'a') c = (char) 0x7;
// ASCII backspace
else if (c == 'b') c = (char) 0x8;
// ASCII horizontal tab
else if (c == 't') c = (char) 0x9;
// ASCII newline
else if (c == 'n') c = (char) 0xA;
// ASCII vertical tab
else if (c == 'v') c = (char) 0xB;
// ASCII form feed
else if (c == 'f') c = (char) 0xC;
// ASCII carriage return
else if (c == 'r') c = (char) 0xD;
// ASCII escape
else if (c == 'e') c = (char) 0x1D;
// Unicode next line
else if (c == 'N') c = (char) 0x85;
// Unicode non breaking space
else if (c == '_') c = (char) 0xA0;
// TODO larger unicode characters
// Unicode line separator
// else if (c == 'L') c = (char) 0x20282028;
// 8 bit hexadecimal
else if (c == 'x')
{
int c_int = (char) 0;
for (int i = 0; i < 2; i ++)
{
c_int *= 16;
stream.Next ();
char d = stream.Char;
if (d >= '0' && d <= '9')
c_int += d - '0';
else if (d >= 'a' && d <= 'f')
c_int += d - 'a';
else if (d >= 'A' && d <= 'F')
c_int += d - 'A';
else
{
stream.DontStop ();
throw new ParseException (stream,
"Invalid escape sequence");
}
}
c = (char) c_int;
}
stream.Next (true);
// Restore last stop settings
stream.DontStop ();
}
else
stream.Next (true);
return c;
}
/// <summary> Content property </summary>
public string Content
{
get { return content; }
set { content = value; }
}
/// <summary> To String </summary>
public override string ToString ()
{
return "[STRING]" + content + "[/STRING]";
}
/// <summary> Write </summary>
protected internal override void Write (WriteStream stream)
{
// TODO, not required, but writing to block or folded scalars
// generates a little more neat code.
// Analyze string
bool multiline = false;
bool mustbequoted = false;
for (int i = 0; i < content.Length; i ++)
{
char c = content [i];
if (c == '\n')
multiline = true;
// We quote everything except strings like /[a-zA-Z]*/
// However there are more strings which don't require
// quotes.
if ( ! ( c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'))
mustbequoted = true;
}
// Double quoted strings
if (mustbequoted)
{
stream.Append ("\"");
for (int i = 0; i < content.Length; i ++)
{
char c = content [i];
// Backslash
if (c == '\\') stream.Append ("\\" + "\\");
// Double quote
else if (c == '\"') stream.Append ("\\" + "\"");
// Single quote
else if (c == '\'') stream.Append ("\\" + "\'");
// ASCII null
else if (c == '\0') stream.Append ("\\0");
// ASCII bell
else if (c == (char) 0x7) stream.Append ("\\a");
// ASCII backspace
else if (c == (char) 0x8) stream.Append ("\\b");
// ASCII horizontal tab
else if (c == (char) 0x9) stream.Append ("\\t");
// ASCII newline
else if (c == (char) 0xA) stream.Append ("\\n");
// ASCII vertical tab
else if (c == (char) 0xB) stream.Append ("\\v");
// ASCII form feed
else if (c == (char) 0xC) stream.Append ("\\f");
// ASCII carriage return
else if (c == (char) 0xD) stream.Append ("\\r");
// ASCII escape
else if (c == (char) 0x1D) stream.Append ("\\e");
// Unicode next line
else if (c == (char) 0x85) stream.Append ("\\N");
// Unicode non breaking space
else if (c == (char) 0xA0) stream.Append ("\\_");
// TODO larger unicode characters
else
stream.Append ("" + c);
}
stream.Append ("\"");
}
// Simple non-quoted strings
else
stream.Append (content);
}
}
}

356
thirdparty/yaml/Timestamp.cs vendored Normal file
View File

@@ -0,0 +1,356 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
using System;
namespace Yaml
{
/// <summary>
/// Yaml Timestamp node
/// uri: tag:yaml.org,2002:timestamp
/// </summary>
public class Timestamp : Scalar
{
private System.DateTime content;
/// <summary>
/// Represents the offset from the UTC time in hours
/// </summary>
/// <remarks>
/// We use this extra variable for compatibility with Mono
/// and .NET 1.0. .NET 2.0 has an extra property for
/// System.Datetime for the timezone.
/// </remarks>
private double timezone = 0;
/// <summary>
/// Basic constructor that takes a given datetime
/// </summary>
/// <param name="datetime">A .NET 1.0 datetime</param>
public Timestamp (DateTime datetime) :
base ("tag:yaml.org,2002:timestamp", NodeType.Timestamp)
{
this.content = datetime;
this.timezone = 0;
}
/// <summary>
/// Basic constructor, that also gives the posibility to set a timezone
/// </summary>
/// <param name="datetime">A .NET 1.0 datetime</param>
/// <param name="timezone">The offset, in hours,r to UTC that determine the timezone </param>
public Timestamp (DateTime datetime, double timezone) :
base ("tag:yaml.org,2002:timestamp", NodeType.Timestamp)
{
this.content = datetime;
this.timezone = timezone;
}
/// <summary> Content property </summary>
public System.DateTime Content
{
get { return content; }
set { content = value; }
}
/// <summary> Timezone, an offset in hours </summary>
public double Timezone
{
get { return timezone; }
set { timezone = value; }
}
/// <summary> To String </summary>
public override string ToString ()
{
return "[TIMESTAMP]" + YamlString () + "[/TIMESTAMP]";
}
/// <summary> Parse a DateTime </summary>
public Timestamp (ParseStream stream) :
base ("tag:yaml.org,2002:timestamp", NodeType.Timestamp)
{
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minutes = 0;
int seconds = 0;
int ms = 0;
try
{
// Parse year
year = ParseNumber (stream, 4);
SkipChar (stream, '-');
// Parse month
month = ParseNumber (stream, 2);
SkipChar (stream, '-');
// Parse day
day = ParseNumber (stream, 2);
// Additional, the time
if ( ! stream.EOF)
ParseTime (stream, out hour, out minutes, out seconds);
// Additional, milliseconds
if ( ! stream.EOF)
ms = ParseMilliSeconds (stream);
// Additional, the timezone
if ( ! stream.EOF)
timezone = ParseTimezone (stream);
// If there is more, then a format exception
if ( ! stream.EOF)
throw new Exception ("More data then excepted");
content = new DateTime (year, month, day, hour, minutes, seconds, ms);
}
catch (Exception ex)
{
throw new ParseException (stream, ex.ToString ());
}
}
/// <summary>
/// Parse the time (hours, minutes, seconds)
/// </summary>
private void ParseTime (ParseStream stream,
out int hour, out int minutes, out int seconds)
{
if (stream.Char == 't' || stream.Char == 'T')
stream.Next (true);
else
SkipWhitespace (stream);
// Parse hour
// Note: A hour can be represented by one or two digits.
string hulp = "";
while (stream.Char >= '0' && stream.Char <= '9' &&
! stream.EOF && hulp.Length <= 2)
{
hulp += stream.Char;
stream.Next (true);
}
hour = Int32.Parse (hulp);
SkipChar (stream, ':');
// Parse minutes
minutes = ParseNumber (stream, 2);
SkipChar (stream, ':');
// Parse seconds
seconds = ParseNumber (stream, 2);
}
/// <summary>
/// Parse the milliseconds
/// </summary>
private int ParseMilliSeconds (ParseStream stream)
{
int ms = 0;
// Look for fraction
if (stream.Char == '.')
{
stream.Next (true);
// Parse fraction, can consists of an
// unlimited sequence of numbers, we only
// look to the first three (max 1000)
int count = 0;
while (stream.Char >= '0' && stream.Char <= '9' &&
count < 3 && ! stream.EOF)
{
ms *= 10;
ms += stream.Char - '0';
stream.Next (true);
count ++;
}
if (count == 1) ms *= 100;
if (count == 2) ms *= 10;
if (count == 3) ms *= 1;
// Ignore the rest
while (stream.Char >= '0' && stream.Char <= '9' &&
! stream.EOF)
stream.Next (true);
}
return ms;
}
/// <summary>
/// Parse the time zone
/// </summary>
private double ParseTimezone (ParseStream stream)
{
double timezone = 0;
SkipWhitespace (stream);
// Timezone = UTC, use by default 0
if (stream.Char == 'Z')
stream.Next (true);
else
{
// Find the sign of the offset
int sign = 0;
if (stream.Char == '-')
sign = -1;
else if (stream.Char == '+')
sign = +1;
else
throw new Exception ("Invalid time zone: " +
"unexpected character");
// Read next char and test for more chars
stream.Next (true);
if (stream.EOF)
throw new Exception ("Invalid time zone");
// Parse hour offset
// Note: A hour can be represented by one or two digits.
string hulp = "";
while (stream.Char >= '0' &&
stream.Char <= '9' &&
!stream.EOF && hulp.Length <= 2)
{
hulp += (stream.Char);
stream.Next (true);
}
timezone = sign * Double.Parse (hulp);
// Parse the minutes of the timezone
// when there is still more to parse
if ( ! stream.EOF)
{
SkipChar (stream, ':');
int temp = ParseNumber (stream, 2);
timezone += (temp / 60.0);
}
}
return timezone;
}
/// <summary>
/// Parse an integer
/// </summary>
/// <param name="length">
/// The number of characters that the integer is expected to be.
/// </param>
/// <param name="stream"> The stream that will be parsed </param>
private int ParseNumber (ParseStream stream, int length)
{
System.Text.StringBuilder hulp = new System.Text.StringBuilder ();
int i;
for (i = 0; i < length && !stream.EOF; i++)
{
hulp.Append (stream.Char);
stream.Next (true);
}
if (i == length)
return Int32.Parse (hulp.ToString ());
else
throw new Exception ("Can't parse number");
}
/// <summary>
/// Skips a specified char, and throws an exception when
/// another char was found.
/// </summary>
private void SkipChar (ParseStream stream, char toSkip)
{
if (stream.Char == toSkip)
stream.Next (true);
else
throw new Exception ("Unexpected character");
}
/// <summary>
/// Skips the spaces * and tabs * in the current stream
/// </summary>
private void SkipWhitespace (ParseStream stream)
{
while ((stream.Char == ' ' || stream.Char == '\t') && ! stream.EOF)
stream.Next (true);
}
/// <summary> Yaml notation for this datetime </summary>
private string YamlString ()
{
string date = content.ToString ("yyyy-MM-ddTHH:mm:ss");
int ms = content.Millisecond;
if (ms != 0)
{
string hulp = "" + (ms / 1000.0);
hulp = hulp.Substring(2); // Cut of the '0,', first 2 digits
date += "." + hulp;
}
string zone = "";
if (timezone != 0)
{
int timezoneHour = (int) Math.Floor (timezone);
int timezoneMinutes = (int) (60 * (timezone - timezoneHour));
// if positif offset add '+', a '-' is default added
if (timezone > 0)
zone = "+";
zone += timezoneHour.ToString ();
if (timezoneMinutes != 0)
zone += ":" + timezoneMinutes;
}
else
zone = "Z"; // UTC timezone as default and if offset == 0
return date + zone;
}
/// <summary> Write to YAML </summary>
protected internal override void Write (WriteStream stream)
{
stream.Append (YamlString ());
}
}
}

121
thirdparty/yaml/WriteStream.cs vendored Normal file
View File

@@ -0,0 +1,121 @@
// ====================================================================================================
// YAML Parser for the .NET Framework
// ====================================================================================================
//
// Copyright (c) 2006
// Christophe Lambrechts
// Jonathan Slenders
//
// ====================================================================================================
// This file is part of the .NET YAML Parser.
//
// This .NET YAML parser is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// The .NET YAML parser is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Foobar; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAusing System.Reflection;
// ====================================================================================================
#define ENABLE_COMPRESSION
using System;
using System.Collections;
using System.IO;
namespace Yaml
{
/// <summary>
/// Help class for writing a Yaml tree to a string
/// </summary>
public class WriteStream
{
private TextWriter stream;
private int indentation = 0;
private bool lastcharisnewline = false;
private static string indentationChars = " ";
/// <summary> Constructor </summary>
public WriteStream (TextWriter stream)
{
this.stream = stream;
}
/// <summary> Append a string </summary>
public void Append (string s)
{
// Just add the text to the output stream when
// there is no indentation
if (indentation == 0)
stream.Write (s);
// Otherwise process each individual char
else
for (int i = 0; i < s.Length; i ++)
{
// Indent after a newline
if (lastcharisnewline)
{
WriteIndentation ();
lastcharisnewline = false;
}
// Add char
stream.Write (s [i]);
// Remember newlines
if (s [i] == '\n')
lastcharisnewline = true;
}
}
/// <summary> Indentation </summary>
public void Indent ()
{
// Increase indentation level
indentation ++;
// Add a newline
#if ENABLE_COMPRESSION
lastcharisnewline = false;
#else
stream.Write ("\n");
lastcharisnewline = true;
#endif
}
/// <summary> Write the indentation to the output stream </summary>
private void WriteIndentation ()
{
for (int i = 0; i < indentation; i ++)
stream.Write (indentationChars);
}
/// <summary> Unindent </summary>
public void UnIndent ()
{
if (indentation > 0)
{
// Decrease indentation level
indentation --;
// Add a newline
if (! lastcharisnewline)
stream.Write ("\n");
lastcharisnewline = true;
}
else
throw new Exception ("Cannot unindent a not indented writestream.");
}
}
}

188
thirdparty/yaml/Yaml.csproj vendored Normal file
View File

@@ -0,0 +1,188 @@
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{D4424F4D-7939-4247-98F5-6A7F6DEBA7C9}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ApplicationIcon>
</ApplicationIcon>
<AssemblyKeyContainerName>
</AssemblyKeyContainerName>
<AssemblyName>Yaml</AssemblyName>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
<DefaultClientScript>JScript</DefaultClientScript>
<DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
<DefaultTargetSchema>IE50</DefaultTargetSchema>
<DelaySign>false</DelaySign>
<OutputType>Library</OutputType>
<RootNamespace>Yaml</RootNamespace>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<StartupObject>
</StartupObject>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>0.0</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>bin\Debug\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>true</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>false</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>full</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<OutputPath>.\</OutputPath>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<BaseAddress>285212672</BaseAddress>
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
<ConfigurationOverrideFile>
</ConfigurationOverrideFile>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<DebugSymbols>false</DebugSymbols>
<FileAlignment>4096</FileAlignment>
<NoStdLib>false</NoStdLib>
<NoWarn>
</NoWarn>
<Optimize>true</Optimize>
<RegisterForComInterop>false</RegisterForComInterop>
<RemoveIntegerChecks>false</RemoveIntegerChecks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningLevel>4</WarningLevel>
<DebugType>none</DebugType>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System">
<Name>System</Name>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data">
<Name>System.Data</Name>
</Reference>
<Reference Include="System.Xml">
<Name>System.XML</Name>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Binary.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Boolean.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Float.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Integer.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Mapping.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Node.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Null.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ParseException.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ParseStream.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Scalar.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Sequence.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="String.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Timestamp.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="WriteStream.cs">
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
<Visible>False</Visible>
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
<Visible>False</Visible>
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
</Project>

19
thirdparty/yaml/Yaml.sln vendored Normal file
View File

@@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yaml", "Yaml.csproj", "{D4424F4D-7939-4247-98F5-6A7F6DEBA7C9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D4424F4D-7939-4247-98F5-6A7F6DEBA7C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4424F4D-7939-4247-98F5-6A7F6DEBA7C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4424F4D-7939-4247-98F5-6A7F6DEBA7C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4424F4D-7939-4247-98F5-6A7F6DEBA7C9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

24
thirdparty/yaml/test.yaml vendored Normal file
View File

@@ -0,0 +1,24 @@
? boolean: y
? float: 8.6e2
? integer: 174832
? null: ~
? inline sequence: [item1, item2]
? inline mappings: {key: value, key2: value2}
? sequence:
- item 1
- item 2
? tricky situations:
- ? block scalar: |
regel 1
regel 2
- ? folded scalar: >
regel 1
nog steeds regel 1
- ? double quoted: "met veel escapes aa\"bb\n\'cc"
- ? met tags:
- !!int 2
- !!string 2
- !!float 2
- { key: value, key 3: "{a: b}", key 2: a }
- ? [aaa]: bbb
- ? single quotes: 'regel 1 regel 2'

Some files were not shown because too many files have changed in this diff Show More