Compare commits

..

5 Commits

Author SHA1 Message Date
Chris Forbes
ae29941d52 fix bogus target lines being drawn to 0,0 2010-10-08 21:04:31 +13:00
Caleb Anderson
e224fadbeb bandage to fix dogs not killing infantry in certain cases 2010-10-08 19:56:27 +13:00
Bob
1cccef5434 use a getter for Aircraft.Location 2010-10-08 19:54:56 +13:00
Bob
319da4c5ae add IHasLocation 2010-10-08 19:54:52 +13:00
Bob
94fc260293 remove setters on Mobile.{from,to}Cell. use SetLocation instead 2010-10-08 19:54:49 +13:00
455 changed files with 13108 additions and 11473 deletions

View File

@@ -6,5 +6,4 @@ The OpenRA developers are:
* Matthew Bowra-Dean
* Paul Chote
* Alli Witheford
* Joakim Lindberg
* Andrew Riedi
* Joakim Lindberg

View File

@@ -1,7 +1,7 @@
CSC = gmcs
CSFLAGS = -nologo -warn:4 -debug:+ -debug:full -optimize- -codepage:utf8 -unsafe
DEFINE = DEBUG;TRACE
PROGRAMS =fileformats gl game ra cnc seqed editor ralint filex tsbuild utility
PROGRAMS =fileformats gl game ra cnc seqed editor ralint filex tsbuild
prefix = /usr/local
datarootdir = $(prefix)/share
datadir = $(datarootdir)
@@ -62,13 +62,13 @@ editor_EXTRA = -resource:OpenRA.Editor.Form1.resources -resource:OpenRA.Editor.
ralint_SRCS = $(shell find RALint/ -iname '*.cs')
ralint_TARGET = RALint.exe
ralint_KIND = exe
ralint_KIND = winexe
ralint_DEPS = $(fileformats_TARGET) $(game_TARGET)
ralint_LIBS = $(COMMON_LIBS) $(ralint_DEPS)
filex_SRCS = $(shell find FileExtractor/ -iname '*.cs')
filex_TARGET = FileExtractor.exe
filex_KIND = exe
filex_KIND = winexe
filex_DEPS = $(fileformats_TARGET)
filex_LIBS = $(COMMON_LIBS) $(filex_DEPS)
@@ -79,26 +79,19 @@ tsbuild_DEPS = $(fileformats_TARGET) $(game_TARGET)
tsbuild_LIBS = $(COMMON_LIBS) $(tsbuild_DEPS) System.Windows.Forms.dll
tsbuild_EXTRA = -resource:OpenRA.TilesetBuilder.Form1.resources
utility_SRCS = $(shell find OpenRA.Utility/ -iname '*.cs')
utility_TARGET = OpenRA.Utility.exe
utility_KIND = exe
utility_DEPS = $(fileformats_TARGET) thirdparty/ICSharpCode.SharpZipLib.dll
utility_LIBS = $(COMMON_LIBS) $(utility_DEPS)
# -platform:x86
.SUFFIXES:
.PHONY: clean all game tool default mods mod_ra mod_cnc install uninstall editor_res editor tsbuild ralint seqed filex utility
.PHONY: clean all game tool default mods mod_ra mod_cnc install uninstall editor_res editor tsbuild ralint seqed filex
game: $(fileformats_TARGET) $(gl_TARGET) $(game_TARGET) $(ra_TARGET) $(cnc_TARGET) $(utility_TARGET)
game: $(fileformats_TARGET) $(gl_TARGET) $(game_TARGET) $(ra_TARGET) $(cnc_TARGET)
clean:
@-rm *.exe *.dll *.mdb mods/**/*.dll mods/**/*.mdb *.resources
distclean: clean
CORE = fileformats gl game editor utility
CORE = fileformats gl game editor
install: all
@-echo "Installing OpenRA to $(INSTALL_DIR)"
@@ -130,7 +123,6 @@ install: all
@cp *.ttf $(INSTALL_DIR)
@cp --parents -r thirdparty/Tao $(INSTALL_DIR)
@$(INSTALL_PROGRAM) thirdparty/WindowsBase.dll $(INSTALL_DIR)
@$(INSTALL_PROGRAM) thirdparty/ICSharpCode.SharpZipLib.dll $(INSTALL_DIR)
@-$(INSTALL_PROGRAM) VERSION $(INSTALL_DIR)
@echo "#!/bin/sh" > openra
@@ -140,8 +132,8 @@ install: all
@$(INSTALL_PROGRAM) -m +rx openra $(BIN_INSTALL_DIR)
@echo "OpenRA is now installed. You will now want to download"
@echo "http://open-ra.org/get-dependency.php?file=ra-packages and"
@echo "http://open-ra.org/get-dependency.php?file=cnc-packages"
@echo "http://open-ra.org/get-dependency.php?ra-packages and"
@echo "http://open-ra.org/get-dependency.php?cnc-packages"
@echo "and extract their contents to"
@echo "$(INSTALL_DIR)/mods/ra/packages and "
@echo "$(INSTALL_DIR)/mods/cnc/packages respectively."

View File

@@ -18,7 +18,7 @@ namespace OpenRA.Editor
{
public Bitmap Bitmap;
public ActorInfo Info;
public EditorAppearanceInfo Appearance;
public bool Centered;
}
class BrushTemplate

877
OpenRA.Editor/Form1.Designer.cs generated Executable file → Normal file
View File

@@ -28,204 +28,221 @@
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.pmMiniMap = new System.Windows.Forms.PictureBox();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.tilePalette = new System.Windows.Forms.FlowLayoutPanel();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.actorPalette = new System.Windows.Forms.FlowLayoutPanel();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.resourcePalette = new System.Windows.Forms.FlowLayoutPanel();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.cCRedAlertMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.bitmapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuExport = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMinimapToPNG = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
this.exotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.resizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this.spawnpointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.layersFloaterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.tt = new System.Windows.Forms.ToolTip(this.components);
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.splitContainer3 = new System.Windows.Forms.SplitContainer();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabelFiller = new System.Windows.Forms.ToolStripStatusLabel();
this.toolStripStatusLabelMousePosition = new System.Windows.Forms.ToolStripStatusLabel();
this.surface1 = new OpenRA.Editor.Surface();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.splitContainer2.Panel1.SuspendLayout();
this.splitContainer2.Panel2.SuspendLayout();
this.splitContainer2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).BeginInit();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
this.tabPage3.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.splitContainer3.Panel1.SuspendLayout();
this.splitContainer3.Panel2.SuspendLayout();
this.splitContainer3.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.surface1);
this.splitContainer1.Size = new System.Drawing.Size(985, 744);
this.splitContainer1.SplitterDistance = 198;
this.splitContainer1.TabIndex = 0;
//
// splitContainer2
//
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
this.splitContainer2.Name = "splitContainer2";
this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainer2.Panel1
//
this.splitContainer2.Panel1.Controls.Add(this.pmMiniMap);
//
// splitContainer2.Panel2
//
this.splitContainer2.Panel2.Controls.Add(this.tabControl1);
this.splitContainer2.Size = new System.Drawing.Size(198, 744);
this.splitContainer2.SplitterDistance = 164;
this.splitContainer2.TabIndex = 1;
//
// pmMiniMap
//
this.pmMiniMap.BackColor = System.Drawing.Color.Black;
this.pmMiniMap.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.pmMiniMap.Dock = System.Windows.Forms.DockStyle.Fill;
this.pmMiniMap.Location = new System.Drawing.Point(0, 0);
this.pmMiniMap.Name = "pmMiniMap";
this.pmMiniMap.Size = new System.Drawing.Size(198, 164);
this.pmMiniMap.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pmMiniMap.TabIndex = 1;
this.pmMiniMap.TabStop = false;
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Controls.Add(this.tabPage3);
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl1.Location = new System.Drawing.Point(0, 0);
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
this.tabControl1.Multiline = true;
this.tabControl1.Name = "tabControl1";
this.tabControl1.Padding = new System.Drawing.Point(6, 0);
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(198, 576);
this.tabControl1.TabIndex = 0;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.tilePalette);
this.tabPage1.Location = new System.Drawing.Point(4, 20);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(190, 552);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Templates";
this.tabPage1.UseVisualStyleBackColor = true;
//
// tilePalette
//
this.tilePalette.AutoScroll = true;
this.tilePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tilePalette.Dock = System.Windows.Forms.DockStyle.Fill;
this.tilePalette.Location = new System.Drawing.Point(3, 3);
this.tilePalette.Name = "tilePalette";
this.tilePalette.Size = new System.Drawing.Size(184, 546);
this.tilePalette.TabIndex = 1;
//
// tabPage2
//
this.tabPage2.Controls.Add(this.actorPalette);
this.tabPage2.Location = new System.Drawing.Point(4, 20);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(190, 552);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Actors";
this.tabPage2.UseVisualStyleBackColor = true;
//
// actorPalette
//
this.actorPalette.AutoScroll = true;
this.actorPalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.actorPalette.Dock = System.Windows.Forms.DockStyle.Fill;
this.actorPalette.Location = new System.Drawing.Point(3, 3);
this.actorPalette.Name = "actorPalette";
this.actorPalette.Size = new System.Drawing.Size(184, 546);
this.actorPalette.TabIndex = 2;
//
// tabPage3
//
this.tabPage3.Controls.Add(this.resourcePalette);
this.tabPage3.Location = new System.Drawing.Point(4, 20);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Size = new System.Drawing.Size(190, 552);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "Resources";
this.tabPage3.UseVisualStyleBackColor = true;
//
// resourcePalette
//
this.resourcePalette.AutoScroll = true;
this.resourcePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.resourcePalette.Dock = System.Windows.Forms.DockStyle.Fill;
this.resourcePalette.Location = new System.Drawing.Point(0, 0);
this.resourcePalette.Name = "resourcePalette";
this.resourcePalette.Size = new System.Drawing.Size(190, 552);
this.resourcePalette.TabIndex = 3;
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
this.pmMiniMap = new System.Windows.Forms.PictureBox();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.tilePalette = new System.Windows.Forms.FlowLayoutPanel();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.actorPalette = new System.Windows.Forms.FlowLayoutPanel();
this.tabPage3 = new System.Windows.Forms.TabPage();
this.resourcePalette = new System.Windows.Forms.FlowLayoutPanel();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.cCRedAlertMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.bitmapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mnuExport = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMinimapToPNG = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
this.exotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.mapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.resizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this.spawnpointsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.layersFloaterToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.tt = new System.Windows.Forms.ToolTip(this.components);
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.surface1 = new OpenRA.Editor.Surface();
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
this.toolStripContainer1.ContentPanel.SuspendLayout();
this.toolStripContainer1.TopToolStripPanel.SuspendLayout();
this.toolStripContainer1.SuspendLayout();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.splitContainer2.Panel1.SuspendLayout();
this.splitContainer2.Panel2.SuspendLayout();
this.splitContainer2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).BeginInit();
this.tabControl1.SuspendLayout();
this.tabPage1.SuspendLayout();
this.tabPage2.SuspendLayout();
this.tabPage3.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
//
// toolStripContainer1
//
//
// toolStripContainer1.ContentPanel
//
this.toolStripContainer1.ContentPanel.Controls.Add(this.splitContainer1);
this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(985, 727);
this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.toolStripContainer1.Location = new System.Drawing.Point(0, 0);
this.toolStripContainer1.Name = "toolStripContainer1";
this.toolStripContainer1.Padding = new System.Windows.Forms.Padding(0, 0, 0, 22);
this.toolStripContainer1.Size = new System.Drawing.Size(985, 773);
this.toolStripContainer1.TabIndex = 1;
this.toolStripContainer1.Text = "toolStripContainer1";
//
// toolStripContainer1.TopToolStripPanel
//
this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.menuStrip1);
//
// splitContainer1
//
this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer1.Location = new System.Drawing.Point(0, 0);
this.splitContainer1.Name = "splitContainer1";
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.splitContainer2);
//
// splitContainer1.Panel2
//
this.splitContainer1.Panel2.Controls.Add(this.surface1);
this.splitContainer1.Size = new System.Drawing.Size(985, 727);
this.splitContainer1.SplitterDistance = 198;
this.splitContainer1.TabIndex = 0;
//
// splitContainer2
//
this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer2.Location = new System.Drawing.Point(0, 0);
this.splitContainer2.Name = "splitContainer2";
this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainer2.Panel1
//
this.splitContainer2.Panel1.Controls.Add(this.pmMiniMap);
//
// splitContainer2.Panel2
//
this.splitContainer2.Panel2.Controls.Add(this.tabControl1);
this.splitContainer2.Size = new System.Drawing.Size(198, 727);
this.splitContainer2.SplitterDistance = 160;
this.splitContainer2.TabIndex = 1;
//
// pmMiniMap
//
this.pmMiniMap.BackColor = System.Drawing.Color.Black;
this.pmMiniMap.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.pmMiniMap.Dock = System.Windows.Forms.DockStyle.Fill;
this.pmMiniMap.Location = new System.Drawing.Point(0, 0);
this.pmMiniMap.Name = "pmMiniMap";
this.pmMiniMap.Size = new System.Drawing.Size(198, 160);
this.pmMiniMap.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.pmMiniMap.TabIndex = 1;
this.pmMiniMap.TabStop = false;
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Controls.Add(this.tabPage2);
this.tabControl1.Controls.Add(this.tabPage3);
this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl1.Location = new System.Drawing.Point(0, 0);
this.tabControl1.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
this.tabControl1.Multiline = true;
this.tabControl1.Name = "tabControl1";
this.tabControl1.Padding = new System.Drawing.Point(6, 0);
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(198, 563);
this.tabControl1.TabIndex = 0;
//
// tabPage1
//
this.tabPage1.Controls.Add(this.tilePalette);
this.tabPage1.Location = new System.Drawing.Point(4, 20);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
this.tabPage1.Size = new System.Drawing.Size(190, 539);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "Templates";
this.tabPage1.UseVisualStyleBackColor = true;
//
// tilePalette
//
this.tilePalette.AutoScroll = true;
this.tilePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tilePalette.Dock = System.Windows.Forms.DockStyle.Fill;
this.tilePalette.Location = new System.Drawing.Point(3, 3);
this.tilePalette.Name = "tilePalette";
this.tilePalette.Size = new System.Drawing.Size(184, 533);
this.tilePalette.TabIndex = 1;
//
// tabPage2
//
this.tabPage2.Controls.Add(this.actorPalette);
this.tabPage2.Location = new System.Drawing.Point(4, 20);
this.tabPage2.Name = "tabPage2";
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
this.tabPage2.Size = new System.Drawing.Size(190, 539);
this.tabPage2.TabIndex = 1;
this.tabPage2.Text = "Actors";
this.tabPage2.UseVisualStyleBackColor = true;
//
// actorPalette
//
this.actorPalette.AutoScroll = true;
this.actorPalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.actorPalette.Dock = System.Windows.Forms.DockStyle.Fill;
this.actorPalette.Location = new System.Drawing.Point(3, 3);
this.actorPalette.Name = "actorPalette";
this.actorPalette.Size = new System.Drawing.Size(184, 533);
this.actorPalette.TabIndex = 2;
//
// tabPage3
//
this.tabPage3.Controls.Add(this.resourcePalette);
this.tabPage3.Location = new System.Drawing.Point(4, 20);
this.tabPage3.Name = "tabPage3";
this.tabPage3.Size = new System.Drawing.Size(190, 539);
this.tabPage3.TabIndex = 2;
this.tabPage3.Text = "Resources";
this.tabPage3.UseVisualStyleBackColor = true;
//
// resourcePalette
//
this.resourcePalette.AutoScroll = true;
this.resourcePalette.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.resourcePalette.Dock = System.Windows.Forms.DockStyle.Fill;
this.resourcePalette.Location = new System.Drawing.Point(0, 0);
this.resourcePalette.Name = "resourcePalette";
this.resourcePalette.Size = new System.Drawing.Size(190, 539);
this.resourcePalette.TabIndex = 3;
//
// menuStrip1
//
this.menuStrip1.Dock = System.Windows.Forms.DockStyle.None;
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem,
this.mapToolStripMenuItem,
this.toolsToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(985, 24);
this.menuStrip1.TabIndex = 1;
this.menuStrip1.Text = "menuStrip1";
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(985, 24);
this.menuStrip1.TabIndex = 1;
this.menuStrip1.Text = "menuStrip1";
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.newToolStripMenuItem,
this.toolStripSeparator1,
this.openToolStripMenuItem,
@@ -236,267 +253,232 @@
this.mnuExport,
this.toolStripSeparator3,
this.exotToolStripMenuItem});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.fileToolStripMenuItem.Text = "&File";
//
// newToolStripMenuItem
//
this.newToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("newToolStripMenuItem.Image")));
this.newToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Fuchsia;
this.newToolStripMenuItem.Name = "newToolStripMenuItem";
this.newToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
this.newToolStripMenuItem.Text = "&New...";
this.newToolStripMenuItem.Click += new System.EventHandler(this.NewClicked);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(120, 6);
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image")));
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
this.openToolStripMenuItem.Text = "&Open...";
this.openToolStripMenuItem.Click += new System.EventHandler(this.OpenClicked);
//
// saveToolStripMenuItem
//
this.saveToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image")));
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
this.saveToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
this.saveToolStripMenuItem.Text = "&Save";
this.saveToolStripMenuItem.Click += new System.EventHandler(this.SaveClicked);
//
// saveAsToolStripMenuItem
//
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
this.saveAsToolStripMenuItem.Text = "Save &As...";
this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.SaveAsClicked);
//
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(120, 6);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(35, 20);
this.fileToolStripMenuItem.Text = "&File";
//
// newToolStripMenuItem
//
this.newToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("newToolStripMenuItem.Image")));
this.newToolStripMenuItem.ImageTransparentColor = System.Drawing.Color.Fuchsia;
this.newToolStripMenuItem.Name = "newToolStripMenuItem";
this.newToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.newToolStripMenuItem.Text = "&New...";
this.newToolStripMenuItem.Click += new System.EventHandler(this.NewClicked);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(122, 6);
//
// openToolStripMenuItem
//
this.openToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("openToolStripMenuItem.Image")));
this.openToolStripMenuItem.Name = "openToolStripMenuItem";
this.openToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
this.openToolStripMenuItem.Text = "&Open...";
this.openToolStripMenuItem.Click += new System.EventHandler(this.OpenClicked);
//
// saveToolStripMenuItem
//
this.saveToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("saveToolStripMenuItem.Image")));
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem";
this.saveToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
this.saveToolStripMenuItem.Text = "&Save";
this.saveToolStripMenuItem.Click += new System.EventHandler(this.SaveClicked);
//
// saveAsToolStripMenuItem
//
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
this.saveAsToolStripMenuItem.Text = "Save &As...";
this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.SaveAsClicked);
//
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(122, 6);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.cCRedAlertMapToolStripMenuItem,
this.bitmapToolStripMenuItem});
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(123, 22);
this.toolStripMenuItem1.Text = "&Import";
//
// cCRedAlertMapToolStripMenuItem
//
this.cCRedAlertMapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cCRedAlertMapToolStripMenuItem.Image")));
this.cCRedAlertMapToolStripMenuItem.Name = "cCRedAlertMapToolStripMenuItem";
this.cCRedAlertMapToolStripMenuItem.Size = new System.Drawing.Size(195, 22);
this.cCRedAlertMapToolStripMenuItem.Text = "&C&&C / Red Alert Map...";
this.cCRedAlertMapToolStripMenuItem.Click += new System.EventHandler(this.ImportLegacyMapClicked);
//
// bitmapToolStripMenuItem
//
this.bitmapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("bitmapToolStripMenuItem.Image")));
this.bitmapToolStripMenuItem.Name = "bitmapToolStripMenuItem";
this.bitmapToolStripMenuItem.Size = new System.Drawing.Size(195, 22);
this.bitmapToolStripMenuItem.Text = "&Bitmap...";
this.bitmapToolStripMenuItem.Visible = false;
//
// mnuExport
//
this.mnuExport.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(125, 22);
this.toolStripMenuItem1.Text = "&Import";
//
// cCRedAlertMapToolStripMenuItem
//
this.cCRedAlertMapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("cCRedAlertMapToolStripMenuItem.Image")));
this.cCRedAlertMapToolStripMenuItem.Name = "cCRedAlertMapToolStripMenuItem";
this.cCRedAlertMapToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
this.cCRedAlertMapToolStripMenuItem.Text = "&C&&C / Red Alert Map...";
this.cCRedAlertMapToolStripMenuItem.Click += new System.EventHandler(this.ImportLegacyMapClicked);
//
// bitmapToolStripMenuItem
//
this.bitmapToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("bitmapToolStripMenuItem.Image")));
this.bitmapToolStripMenuItem.Name = "bitmapToolStripMenuItem";
this.bitmapToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
this.bitmapToolStripMenuItem.Text = "&Bitmap...";
this.bitmapToolStripMenuItem.Visible = false;
//
// mnuExport
//
this.mnuExport.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuMinimapToPNG});
this.mnuExport.Name = "mnuExport";
this.mnuExport.Size = new System.Drawing.Size(123, 22);
this.mnuExport.Text = "&Export";
//
// mnuMinimapToPNG
//
this.mnuMinimapToPNG.Image = ((System.Drawing.Image)(resources.GetObject("mnuMinimapToPNG.Image")));
this.mnuMinimapToPNG.Name = "mnuMinimapToPNG";
this.mnuMinimapToPNG.Size = new System.Drawing.Size(163, 22);
this.mnuMinimapToPNG.Text = "Minimap to PNG";
this.mnuMinimapToPNG.Click += new System.EventHandler(this.mnuMinimapToPNG_Click);
//
// toolStripSeparator3
//
this.toolStripSeparator3.Name = "toolStripSeparator3";
this.toolStripSeparator3.Size = new System.Drawing.Size(120, 6);
//
// exotToolStripMenuItem
//
this.exotToolStripMenuItem.Name = "exotToolStripMenuItem";
this.exotToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
this.exotToolStripMenuItem.Text = "E&xit";
this.exotToolStripMenuItem.Click += new System.EventHandler(this.CloseClicked);
//
// mapToolStripMenuItem
//
this.mapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuExport.Name = "mnuExport";
this.mnuExport.Size = new System.Drawing.Size(152, 22);
this.mnuExport.Text = "&Export";
//
// mnuMinimapToPNG
//
this.mnuMinimapToPNG.Image = ((System.Drawing.Image)(resources.GetObject("mnuMinimapToPNG.Image")));
this.mnuMinimapToPNG.Name = "mnuMinimapToPNG";
this.mnuMinimapToPNG.Size = new System.Drawing.Size(152, 22);
this.mnuMinimapToPNG.Text = "Minimap to PNG";
this.mnuMinimapToPNG.Click += new System.EventHandler(this.mnuMinimapToPNG_Click);
//
// toolStripSeparator3
//
this.toolStripSeparator3.Name = "toolStripSeparator3";
this.toolStripSeparator3.Size = new System.Drawing.Size(122, 6);
//
// exotToolStripMenuItem
//
this.exotToolStripMenuItem.Name = "exotToolStripMenuItem";
this.exotToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
this.exotToolStripMenuItem.Text = "E&xit";
this.exotToolStripMenuItem.Click += new System.EventHandler(this.CloseClicked);
//
// mapToolStripMenuItem
//
this.mapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.propertiesToolStripMenuItem,
this.resizeToolStripMenuItem,
this.toolStripSeparator4,
this.spawnpointsToolStripMenuItem});
this.mapToolStripMenuItem.Name = "mapToolStripMenuItem";
this.mapToolStripMenuItem.Size = new System.Drawing.Size(43, 20);
this.mapToolStripMenuItem.Text = "&Map";
//
// propertiesToolStripMenuItem
//
this.propertiesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("propertiesToolStripMenuItem.Image")));
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
this.propertiesToolStripMenuItem.Text = "&Properties...";
this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.PropertiesClicked);
//
// resizeToolStripMenuItem
//
this.resizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("resizeToolStripMenuItem.Image")));
this.resizeToolStripMenuItem.Name = "resizeToolStripMenuItem";
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
this.resizeToolStripMenuItem.Text = "&Resize...";
this.resizeToolStripMenuItem.Click += new System.EventHandler(this.ResizeClicked);
//
// toolStripSeparator4
//
this.toolStripSeparator4.Name = "toolStripSeparator4";
this.toolStripSeparator4.Size = new System.Drawing.Size(139, 6);
//
// spawnpointsToolStripMenuItem
//
this.spawnpointsToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("spawnpointsToolStripMenuItem.Image")));
this.spawnpointsToolStripMenuItem.Name = "spawnpointsToolStripMenuItem";
this.spawnpointsToolStripMenuItem.Size = new System.Drawing.Size(142, 22);
this.spawnpointsToolStripMenuItem.Text = "&Spawnpoints";
this.spawnpointsToolStripMenuItem.Click += new System.EventHandler(this.SpawnPointsClicked);
//
// toolsToolStripMenuItem
//
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mapToolStripMenuItem.Name = "mapToolStripMenuItem";
this.mapToolStripMenuItem.Size = new System.Drawing.Size(39, 20);
this.mapToolStripMenuItem.Text = "&Map";
//
// propertiesToolStripMenuItem
//
this.propertiesToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("propertiesToolStripMenuItem.Image")));
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
this.propertiesToolStripMenuItem.Text = "&Properties...";
this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.PropertiesClicked);
//
// resizeToolStripMenuItem
//
this.resizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("resizeToolStripMenuItem.Image")));
this.resizeToolStripMenuItem.Name = "resizeToolStripMenuItem";
this.resizeToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
this.resizeToolStripMenuItem.Text = "&Resize...";
this.resizeToolStripMenuItem.Click += new System.EventHandler(this.ResizeClicked);
//
// toolStripSeparator4
//
this.toolStripSeparator4.Name = "toolStripSeparator4";
this.toolStripSeparator4.Size = new System.Drawing.Size(132, 6);
//
// spawnpointsToolStripMenuItem
//
this.spawnpointsToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("spawnpointsToolStripMenuItem.Image")));
this.spawnpointsToolStripMenuItem.Name = "spawnpointsToolStripMenuItem";
this.spawnpointsToolStripMenuItem.Size = new System.Drawing.Size(135, 22);
this.spawnpointsToolStripMenuItem.Text = "&Spawnpoints";
this.spawnpointsToolStripMenuItem.Click += new System.EventHandler(this.SpawnPointsClicked);
//
// toolsToolStripMenuItem
//
this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.layersFloaterToolStripMenuItem});
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(48, 20);
this.toolsToolStripMenuItem.Text = "Tools";
this.toolsToolStripMenuItem.Visible = false;
//
// layersFloaterToolStripMenuItem
//
this.layersFloaterToolStripMenuItem.Name = "layersFloaterToolStripMenuItem";
this.layersFloaterToolStripMenuItem.Size = new System.Drawing.Size(144, 22);
this.layersFloaterToolStripMenuItem.Text = "Layers floater";
this.layersFloaterToolStripMenuItem.Click += new System.EventHandler(this.layersFloaterToolStripMenuItem_Click);
//
// tt
//
this.tt.ShowAlways = true;
//
// saveFileDialog
//
this.saveFileDialog.DefaultExt = "*.png";
this.saveFileDialog.Filter = "PNG Image (*.png)|";
this.saveFileDialog.Title = "Export minimap to PNG";
//
// splitContainer3
//
this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill;
this.splitContainer3.FixedPanel = System.Windows.Forms.FixedPanel.Panel1;
this.splitContainer3.IsSplitterFixed = true;
this.splitContainer3.Location = new System.Drawing.Point(0, 0);
this.splitContainer3.Name = "splitContainer3";
this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal;
//
// splitContainer3.Panel1
//
this.splitContainer3.Panel1.Controls.Add(this.menuStrip1);
//
// splitContainer3.Panel2
//
this.splitContainer3.Panel2.Controls.Add(this.splitContainer1);
this.splitContainer3.Size = new System.Drawing.Size(985, 773);
this.splitContainer3.SplitterDistance = 25;
this.splitContainer3.TabIndex = 6;
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabelFiller,
this.toolStripStatusLabelMousePosition});
this.statusStrip1.Location = new System.Drawing.Point(0, 751);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(985, 22);
this.statusStrip1.TabIndex = 7;
this.statusStrip1.Text = "statusStrip1";
//
// toolStripStatusLabelFiller
//
this.toolStripStatusLabelFiller.Name = "toolStripStatusLabelFiller";
this.toolStripStatusLabelFiller.Size = new System.Drawing.Size(948, 17);
this.toolStripStatusLabelFiller.Spring = true;
//
// toolStripStatusLabelMousePosition
//
this.toolStripStatusLabelMousePosition.Name = "toolStripStatusLabelMousePosition";
this.toolStripStatusLabelMousePosition.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
this.toolStripStatusLabelMousePosition.Size = new System.Drawing.Size(22, 17);
this.toolStripStatusLabelMousePosition.Text = "0,0";
//
// surface1
//
this.surface1.BackColor = System.Drawing.Color.Black;
this.surface1.Dock = System.Windows.Forms.DockStyle.Fill;
this.surface1.Location = new System.Drawing.Point(0, 0);
this.surface1.Name = "surface1";
this.surface1.Size = new System.Drawing.Size(783, 744);
this.surface1.TabIndex = 5;
this.surface1.Text = "surface1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(985, 773);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.splitContainer3);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.KeyPreview = true;
this.MainMenuStrip = this.menuStrip1;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "OpenRA Editor";
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
this.splitContainer1.ResumeLayout(false);
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel2.ResumeLayout(false);
this.splitContainer2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).EndInit();
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage2.ResumeLayout(false);
this.tabPage3.ResumeLayout(false);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.splitContainer3.Panel1.ResumeLayout(false);
this.splitContainer3.Panel1.PerformLayout();
this.splitContainer3.Panel2.ResumeLayout(false);
this.splitContainer3.ResumeLayout(false);
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem";
this.toolsToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
this.toolsToolStripMenuItem.Text = "Tools";
this.toolsToolStripMenuItem.Visible = false;
//
// layersFloaterToolStripMenuItem
//
this.layersFloaterToolStripMenuItem.Name = "layersFloaterToolStripMenuItem";
this.layersFloaterToolStripMenuItem.Size = new System.Drawing.Size(141, 22);
this.layersFloaterToolStripMenuItem.Text = "Layers floater";
this.layersFloaterToolStripMenuItem.Click += new System.EventHandler(this.layersFloaterToolStripMenuItem_Click);
//
// tt
//
this.tt.ShowAlways = true;
//
// statusStrip1
//
this.statusStrip1.Location = new System.Drawing.Point(0, 751);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(985, 22);
this.statusStrip1.TabIndex = 2;
this.statusStrip1.Text = "statusStrip1";
//
// surface1
//
this.surface1.BackColor = System.Drawing.Color.Black;
this.surface1.Dock = System.Windows.Forms.DockStyle.Fill;
this.surface1.Location = new System.Drawing.Point(0, 0);
this.surface1.Name = "surface1";
this.surface1.Size = new System.Drawing.Size(783, 727);
this.surface1.TabIndex = 5;
this.surface1.Text = "surface1";
this.surface1.Click += new System.EventHandler(this.OnSurfaceClicked);
//
// saveFileDialog
//
this.saveFileDialog.DefaultExt = "*.png";
this.saveFileDialog.Filter = "PNG Image (*.png)|";
this.saveFileDialog.Title = "Export minimap to PNG";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(985, 773);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.toolStripContainer1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.KeyPreview = true;
this.MainMenuStrip = this.menuStrip1;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "OpenRA Editor";
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OnFormClosing);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.toolStripContainer1.ContentPanel.ResumeLayout(false);
this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
this.toolStripContainer1.TopToolStripPanel.PerformLayout();
this.toolStripContainer1.ResumeLayout(false);
this.toolStripContainer1.PerformLayout();
this.splitContainer1.Panel1.ResumeLayout(false);
this.splitContainer1.Panel2.ResumeLayout(false);
this.splitContainer1.ResumeLayout(false);
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel2.ResumeLayout(false);
this.splitContainer2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pmMiniMap)).EndInit();
this.tabControl1.ResumeLayout(false);
this.tabPage1.ResumeLayout(false);
this.tabPage2.ResumeLayout(false);
this.tabPage3.ResumeLayout(false);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ToolStripContainer toolStripContainer1;
private System.Windows.Forms.SplitContainer splitContainer1;
private System.Windows.Forms.ToolTip tt;
private System.Windows.Forms.TabControl tabControl1;
@@ -524,18 +506,15 @@
private System.Windows.Forms.ToolStripMenuItem propertiesToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem resizeToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
private System.Windows.Forms.ToolStripMenuItem spawnpointsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem spawnpointsToolStripMenuItem;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem layersFloaterToolStripMenuItem;
private System.Windows.Forms.PictureBox pmMiniMap;
private System.Windows.Forms.SplitContainer splitContainer2;
private System.Windows.Forms.ToolStripMenuItem mnuExport;
private System.Windows.Forms.ToolStripMenuItem mnuMinimapToPNG;
private System.Windows.Forms.SaveFileDialog saveFileDialog;
private System.Windows.Forms.SplitContainer splitContainer3;
private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelMousePosition;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelFiller;
private System.Windows.Forms.SaveFileDialog saveFileDialog;
}
}

18
OpenRA.Editor/Form1.cs Executable file → Normal file
View File

@@ -35,14 +35,7 @@ namespace OpenRA.Editor
Rules.LoadRules(Game.modData.Manifest, new Map());
surface1.AfterChange += OnMapChanged;
surface1.MousePositionChanged += s => toolStripStatusLabelMousePosition.Text = s;
}
void OnMapChanged()
{
MakeDirty();
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
surface1.AfterChange += MakeDirty;
}
void MakeDirty() { dirty = true; }
@@ -62,7 +55,7 @@ namespace OpenRA.Editor
Game.modData = new ModData(currentMod);
// load the map
var map = new Map(new Folder(mapname, 0));
var map = new Map(new Folder(mapname));
// upgrade maps that have no player definitions. editor doesnt care,
// but this breaks the game pretty badly.
@@ -241,6 +234,7 @@ namespace OpenRA.Editor
else
{
surface1.Map.PlayerCount = surface1.Map.Waypoints.Count;
surface1.Map.Package = new Folder(loadedMapName);
surface1.Map.Save(loadedMapName);
dirty = false;
}
@@ -364,6 +358,7 @@ namespace OpenRA.Editor
Directory.CreateDirectory(savePath);
var map = LegacyMapImporter.Import(ofd.FileName);
map.Package = new Folder(savePath);
map.Players.Add("Neutral", new PlayerReference("Neutral",
Rules.Info["world"].Traits.WithInterface<CountryInfo>().First().Race, true, true));
@@ -395,6 +390,11 @@ namespace OpenRA.Editor
pb.Show();
}
private void OnSurfaceClicked(object sender, EventArgs e)
{
pmMiniMap.Image = Minimap.AddStaticResources(surface1.Map, Minimap.TerrainBitmap(surface1.Map, true));
}
private void mnuMinimapToPNG_Click(object sender, EventArgs e)
{
try

6
OpenRA.Editor/Form1.resx Executable file → Normal file
View File

@@ -308,12 +308,12 @@
<metadata name="tt.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>307, 17</value>
</metadata>
<metadata name="saveFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>76, 17</value>
</metadata>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>313, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>45</value>
</metadata>

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Editor
if (MapList.SelectedItems.Count == 1)
{
txtNew.Text = MapList.SelectedItems[0].Text;
var map = new Map(new Folder(Path.Combine(MapFolderPath, MapList.SelectedItems[0].Text), 0));
var map = new Map(new Folder(Path.Combine(MapFolderPath, MapList.SelectedItems[0].Text)));
txtTitle.Text = map.Title;
txtAuthor.Text = map.Author;
txtTheater.Text = map.Theater;

View File

@@ -8,7 +8,6 @@
*/
#endregion
using System;
using System.Drawing;
using System.Drawing.Imaging;
using OpenRA.FileFormats;
@@ -18,34 +17,19 @@ namespace OpenRA.Editor
{
static class RenderUtils
{
public static ColorPalette MakeSystemPalette(Palette p)
{
ColorPalette pal;
using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
pal = b.Palette;
for (var i = 0; i < 256; i++)
pal.Entries[i] = p.GetColor(i);
return pal;
}
public static Bitmap RenderTemplate(TileSet ts, ushort n, Palette p)
{
var template = ts.Templates[n];
var tile = ts.Tiles[n];
var bitmap = new Bitmap(ts.TileSize * template.Size.X, ts.TileSize * template.Size.Y,
PixelFormat.Format8bppIndexed);
bitmap.Palette = MakeSystemPalette(p);
var bitmap = new Bitmap(ts.TileSize * template.Size.X, ts.TileSize * template.Size.Y);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
byte* q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride;
int* q = (int*)data.Scan0.ToPointer();
var stride = data.Stride >> 2;
for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++)
@@ -54,13 +38,13 @@ namespace OpenRA.Editor
var rawImage = tile.TileBitmapBytes[u + v * template.Size.X];
for (var i = 0; i < ts.TileSize; i++)
for (var j = 0; j < ts.TileSize; j++)
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = rawImage[i + ts.TileSize * j];
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = p.GetColor(rawImage[i + ts.TileSize * j]).ToArgb();
}
else
{
for (var i = 0; i < ts.TileSize; i++)
for (var j = 0; j < ts.TileSize; j++)
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = 0;
q[(v * ts.TileSize + j) * stride + u * ts.TileSize + i] = Color.Transparent.ToArgb();
}
}
@@ -72,21 +56,18 @@ namespace OpenRA.Editor
{
var frame = shp[0];
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
bitmap.Palette = MakeSystemPalette(p);
var bitmap = new Bitmap(shp.Width, shp.Height);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
byte* q = (byte*)data.Scan0.ToPointer();
var stride2 = data.Stride;
int* q = (int*)data.Scan0.ToPointer();
var stride2 = data.Stride >> 2;
for (var i = 0; i < shp.Width; i++)
for (var j = 0; j < shp.Height; j++)
q[j * stride2 + i] = frame.Image[i + shp.Width * j];
q[j * stride2 + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
}
bitmap.UnlockBits(data);
@@ -121,12 +102,7 @@ namespace OpenRA.Editor
}
catch { }
return new ActorTemplate
{
Bitmap = bitmap,
Info = info,
Appearance = info.Traits.GetOrDefault<EditorAppearanceInfo>()
};
return new ActorTemplate { Bitmap = bitmap, Info = info, Centered = !info.Traits.Contains<BuildingInfo>() };
}
}
@@ -138,19 +114,18 @@ namespace OpenRA.Editor
var shp = new ShpReader(s);
var frame = shp[shp.ImageCount - 1];
var bitmap = new Bitmap(shp.Width, shp.Height, PixelFormat.Format8bppIndexed);
bitmap.Palette = MakeSystemPalette(p);
var bitmap = new Bitmap(shp.Width, shp.Height);
var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
unsafe
{
byte* q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride;
int* q = (int*)data.Scan0.ToPointer();
var stride = data.Stride >> 2;
for (var i = 0; i < shp.Width; i++)
for (var j = 0; j < shp.Height; j++)
q[j * stride + i] = frame.Image[i + shp.Width * j];
q[j * stride + i] = p.GetColor(frame.Image[i + shp.Width * j]).ToArgb();
}
bitmap.UnlockBits(data);

View File

@@ -15,7 +15,6 @@ using System.Drawing.Imaging;
using System.Linq;
using System.Windows.Forms;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Editor
{
@@ -35,7 +34,6 @@ namespace OpenRA.Editor
public bool IsPanning;
public event Action AfterChange = () => { };
public event Action<string> MousePositionChanged = _ => { };
Dictionary<string, ActorTemplate> ActorTemplates = new Dictionary<string, ActorTemplate>();
Dictionary<int, ResourceTemplate> ResourceTemplates = new Dictionary<int, ResourceTemplate>();
@@ -46,7 +44,6 @@ namespace OpenRA.Editor
TileSet = ts;
Palette = p;
Brush = null;
PlayerPalettes = null;
Chunks.Clear();
}
@@ -90,8 +87,6 @@ namespace OpenRA.Editor
{
base.OnMouseWheel(e);
if (Map == null) return;
Zoom *= e.Delta > 0 ? 4.0f / 3.0f : .75f;
Invalidate();
@@ -119,11 +114,8 @@ namespace OpenRA.Editor
{
base.OnMouseMove(e);
if (Map == null) return;
var oldMousePos = MousePos;
MousePos = new int2(e.Location);
MousePositionChanged(GetBrushLocation().ToString());
if (e.Button == MouseButtons.Middle || (e.Button != MouseButtons.None && IsPanning))
Scroll(oldMousePos - MousePos);
@@ -175,7 +167,7 @@ namespace OpenRA.Editor
{
for (; ; )
{
var q = p + d;
var q = p+d;
if (!Map.IsInMap(q)) return p;
if (!Map.MapTiles[q.X, q.Y].Equals(replace)) return p;
p = q;
@@ -207,7 +199,7 @@ namespace OpenRA.Editor
{
type = Brush.N,
index = template.PickAny ? byte.MaxValue : (byte)z,
image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4) * 4) : (byte)z,
image = template.PickAny ? (byte)((u + pos.X) % 4 + ((v + pos.Y) % 4)*4) : (byte)z,
};
var ch = new int2((pos.X + u) / ChunkSize, (pos.Y + v) / ChunkSize);
@@ -340,8 +332,6 @@ namespace OpenRA.Editor
{
base.OnMouseDown(e);
if (Map == null) return;
if (!IsPanning)
{
if (e.Button == MouseButtons.Right) Erase();
@@ -411,25 +401,19 @@ namespace OpenRA.Editor
return new int2(vX / TileSet.TileSize, vY / TileSet.TileSize);
}
void DrawActor(System.Drawing.Graphics g, int2 p, ActorTemplate t, ColorPalette cp)
void DrawActor(System.Drawing.Graphics g, int2 p, ActorTemplate t)
{
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
float OffsetX = centered ? t.Bitmap.Width / 2 - TileSet.TileSize / 2 : 0;
float OffsetX = t.Centered ? t.Bitmap.Width / 2 - TileSet.TileSize/2 : 0;
float DrawX = TileSet.TileSize * p.X * Zoom + Offset.X - OffsetX;
float OffsetY = centered ? t.Bitmap.Height / 2 - TileSet.TileSize / 2 : 0;
float OffsetY = t.Centered ? t.Bitmap.Height / 2 - TileSet.TileSize/2 : 0;
float DrawY = TileSet.TileSize * p.Y * Zoom + Offset.Y - OffsetY;
float width = t.Bitmap.Width * Zoom;
float height = t.Bitmap.Height * Zoom;
RectangleF sourceRect = new RectangleF(0, 0, t.Bitmap.Width, t.Bitmap.Height);
RectangleF destRect = new RectangleF(DrawX, DrawY, width, height);
var restorePalette = t.Bitmap.Palette;
if (cp != null) t.Bitmap.Palette = cp;
g.DrawImage(t.Bitmap, destRect, sourceRect, GraphicsUnit.Pixel);
if (cp != null) t.Bitmap.Palette = restorePalette;
}
void DrawImage(System.Drawing.Graphics g, Bitmap bmp, int2 location)
@@ -449,12 +433,10 @@ namespace OpenRA.Editor
void DrawActorBorder(System.Drawing.Graphics g, int2 p, ActorTemplate t)
{
var centered = t.Appearance == null || !t.Appearance.RelativeToTopLeft;
float OffsetX = centered ? t.Bitmap.Width / 2 - TileSet.TileSize / 2 : 0;
float OffsetX = t.Centered ? t.Bitmap.Width / 2 - TileSet.TileSize / 2 : 0;
float DrawX = TileSet.TileSize * p.X * Zoom + Offset.X - OffsetX;
float OffsetY = centered ? t.Bitmap.Height / 2 - TileSet.TileSize / 2 : 0;
float OffsetY = t.Centered ? t.Bitmap.Height / 2 - TileSet.TileSize / 2 : 0;
float DrawY = TileSet.TileSize * p.Y * Zoom + Offset.Y - OffsetY;
g.DrawRectangle(CordonPen,
@@ -462,42 +444,20 @@ namespace OpenRA.Editor
t.Bitmap.Width * Zoom, t.Bitmap.Height * Zoom);
}
ColorPalette GetPaletteForPlayer(string name)
{
var pr = Map.Players[name];
var pcpi = Rules.Info["player"].Traits.Get<PlayerColorPaletteInfo>();
var remap = new PlayerColorRemap(pr.Color, pr.Color2, pcpi.PaletteFormat);
return RenderUtils.MakeSystemPalette(new Palette(Palette, remap));
}
Cache<string, ColorPalette> PlayerPalettes;
ColorPalette GetPaletteForActor(ActorReference ar)
{
if (PlayerPalettes == null)
PlayerPalettes = new Cache<string, ColorPalette>(GetPaletteForPlayer);
var ownerInit = ar.InitDict.GetOrDefault<OwnerInit>();
if (ownerInit == null)
return null;
return PlayerPalettes[ownerInit.PlayerName];
}
protected override void OnPaint(PaintEventArgs e)
{
if (Map == null) return;
if (TileSet == null) return;
for (var u = 0; u < Map.MapSize.X; u += ChunkSize)
for( var u = 0; u < Map.MapSize.X; u += ChunkSize )
for (var v = 0; v < Map.MapSize.Y; v += ChunkSize)
{
var x = new int2(u / ChunkSize, v / ChunkSize);
var x = new int2(u/ChunkSize,v/ChunkSize);
if (!Chunks.ContainsKey(x)) Chunks[x] = RenderChunk(u / ChunkSize, v / ChunkSize);
Bitmap bmp = Chunks[x];
float DrawX = TileSet.TileSize * 1f * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
float DrawX = TileSet.TileSize* 1f * (float)ChunkSize * (float)x.X * Zoom + Offset.X;
float DrawY = TileSet.TileSize * 1f * (float)ChunkSize * (float)x.Y * Zoom + Offset.Y;
RectangleF sourceRect = new RectangleF(0, 0, bmp.Width, bmp.Height);
RectangleF destRect = new RectangleF(DrawX, DrawY, bmp.Width * Zoom, bmp.Height * Zoom);
@@ -511,8 +471,7 @@ namespace OpenRA.Editor
Map.Height * TileSet.TileSize * Zoom);
foreach (var ar in Map.Actors)
DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type],
GetPaletteForActor(ar.Value));
DrawActor(e.Graphics, ar.Value.Location(), ActorTemplates[ar.Value.Type]);
foreach (var wp in Map.Waypoints)
e.Graphics.DrawRectangle(Pens.LimeGreen,
@@ -528,8 +487,7 @@ namespace OpenRA.Editor
Brush.Bitmap.Height * Zoom);
if (Actor != null)
DrawActor(e.Graphics, GetBrushLocation(), Actor, null); /* todo: include the player
* in the brush so we can color new buildings too */
DrawActor(e.Graphics, GetBrushLocation(), Actor);
if (Resource != null)
DrawImage(e.Graphics, Resource.Bitmap, GetBrushLocation());

View File

@@ -21,11 +21,9 @@ namespace OpenRA.FileFormats
readonly uint[] hashes;
readonly Stream s;
readonly ZipPackage pkg;
int priority;
public CompressedPackage(string filename, int priority)
public CompressedPackage(string filename)
{
this.priority = priority;
s = FileSystem.Open(filename);
pkg = (ZipPackage)ZipPackage.Open(s, FileMode.Open);
hashes = pkg.GetParts()
@@ -43,11 +41,5 @@ namespace OpenRA.FileFormats
{
return hashes.Contains(PackageEntry.HashFilename(filename));
}
public int Priority
{
get { return 500 + priority; }
}
}
}

View File

@@ -105,14 +105,6 @@ namespace OpenRA.FileFormats
return InvalidValueAction(x,fieldType, field);
}
else if (fieldType == typeof(decimal))
{
decimal res;
if (decimal.TryParse(x.Replace("%",""), System.Globalization.NumberStyles.Any, NumberFormatInfo.InvariantInfo, out res))
return res * (x.Contains( '%' ) ? 0.01m : 1m);
return InvalidValueAction(x,fieldType, field);
}
else if (fieldType == typeof(string))
return x;

View File

@@ -12,7 +12,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Linq;
namespace OpenRA.FileFormats
{
@@ -34,16 +33,14 @@ namespace OpenRA.FileFormats
}
}
static int order = 0;
static IFolder OpenPackage(string filename)
{
if (filename.EndsWith(".mix"))
return new Package(filename, order++);
return new Package(filename);
else if (filename.EndsWith(".zip"))
return new CompressedPackage(filename, order++);
return new CompressedPackage(filename);
else
return new Folder(filename, order++);
return new Folder(filename);
}
public static void Mount(string name)
@@ -76,14 +73,9 @@ namespace OpenRA.FileFormats
static Stream GetFromCache( Cache<uint, List<IFolder>> index, string filename )
{
var folder = index[PackageEntry.HashFilename(filename)]
.Where(x => x.Exists(filename))
.OrderBy(x => x.Priority)
.FirstOrDefault();
if (folder != null)
return folder.GetContent(filename);
foreach( var folder in index[ PackageEntry.HashFilename( filename ) ] )
if (folder.Exists(filename))
return folder.GetContent(filename);
return null;
}
@@ -96,13 +88,11 @@ namespace OpenRA.FileFormats
return ret;
}
var folder = mountedFolders
.Where(x => x.Exists(filename))
.OrderByDescending(x => x.Priority)
.FirstOrDefault();
if (folder != null)
return folder.GetContent(filename);
foreach( IFolder folder in mountedFolders )
{
if (folder.Exists(filename))
return folder.GetContent(filename);
}
throw new FileNotFoundException( string.Format( "File not found: {0}", filename ), filename );
}

View File

@@ -17,9 +17,7 @@ namespace OpenRA.FileFormats
{
readonly string path;
int priority;
public Folder(string path, int priority) { this.path = path; this.priority = priority; }
public Folder(string path) { this.path = path; }
public Stream GetContent(string filename)
{
@@ -30,18 +28,12 @@ namespace OpenRA.FileFormats
public IEnumerable<uint> AllFileHashes()
{
foreach( var filename in Directory.GetFiles( path, "*", SearchOption.TopDirectoryOnly ) )
yield return PackageEntry.HashFilename( Path.GetFileName(filename) );
yield return PackageEntry.HashFilename( filename );
}
public bool Exists(string filename)
{
return File.Exists(Path.Combine(path,filename));
}
public int Priority
{
get { return priority; }
}
}
}

View File

@@ -37,8 +37,10 @@ namespace OpenRA.FileFormats.Graphics
Size WindowSize { get; }
void Begin();
void End();
void Clear( Color color );
void Present( IInputHandler inputHandler );
void Present();
void DrawIndexedPrimitives( PrimitiveType type, Range<int> vertexRange, Range<int> indexRange );
void DrawIndexedPrimitives( PrimitiveType type, int vertexPool, int numPrimitives );

View File

@@ -18,17 +18,15 @@ namespace OpenRA.FileFormats
public class Manifest
{
public readonly string[]
Mods, Folders, Packages, Rules,
Folders, Packages, Rules,
Sequences, Cursors, Chrome, Assemblies, ChromeLayout,
Weapons, Voices, Music, Movies, TileSets;
public string[] LocalRules = new string[0];
public string[] LocalAssemblies = new string[0];
public readonly string ShellmapUid, LoadScreen;
public readonly int TileSize = 24;
public Manifest(string[] mods)
{
Mods = mods;
var yaml = mods
.Select(m => MiniYaml.FromFile("mods/" + m + "/mod.yaml"))
.Aggregate(MiniYaml.Merge);

View File

@@ -17,10 +17,10 @@ namespace OpenRA.FileFormats
{
public class MapStub
{
public IFolder Package { get; protected set; }
public readonly IFolder Package;
// Yaml map data
public string Uid { get; protected set; }
public readonly string Uid;
[FieldLoader.Load] public bool Selectable;
[FieldLoader.Load] public string Title;
@@ -37,8 +37,7 @@ namespace OpenRA.FileFormats
[FieldLoader.Load] public int2 BottomRight;
public int Width { get { return BottomRight.X - TopLeft.X; } }
public int Height { get { return BottomRight.Y - TopLeft.Y; } }
public MapStub() {} // Hack for the editor - not used for anything important
public MapStub(IFolder package)
{
Package = package;

View File

@@ -16,16 +16,11 @@ namespace OpenRA.FileFormats
{
public string Name;
public string Palette;
public string Race;
public bool OwnsWorld = false;
public bool NonCombatant = false;
public bool Playable = false;
public bool DefaultStartingUnits = false;
public bool AllowBots = true;
public bool LockRace = false;
public string Race;
public bool LockColor = false;
public Color Color = Color.FromArgb(238,238,238);
public Color Color2 = Color.FromArgb(44,28,24);

View File

@@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace OpenRA.FileFormats
{
public class Mod
{
public string Title;
public string Description;
public string Version;
public string Author;
public string[] RequiresMods;
public bool Standalone = false;
public static readonly Dictionary<string, Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
public static Dictionary<string, Mod> ValidateMods(string[] mods)
{
var ret = new Dictionary<string, Mod>();
foreach (var m in mods)
{
if (!File.Exists("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"))
continue;
var yaml = new MiniYaml(null, MiniYaml.FromFile("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"));
if (!yaml.NodesDict.ContainsKey("Metadata"))
{
continue;
}
ret.Add(m, FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]));
}
return ret;
}
}
}

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BDAEAB25-991E-46A7-AF1E-4F0E03358DAA}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -45,7 +45,6 @@
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Tao.Sdl, Version=1.2.13.0, Culture=neutral, PublicKeyToken=9c7a200e36c0094e">
<SpecificVersion>False</SpecificVersion>
@@ -62,11 +61,9 @@
<Compile Include="FileSystem.cs" />
<Compile Include="Folder.cs" />
<Compile Include="Graphics\IGraphicsDevice.cs" />
<Compile Include="Graphics\IInputHandler.cs" />
<Compile Include="Graphics\Vertex.cs" />
<Compile Include="Manifest.cs" />
<Compile Include="MiniYaml.cs" />
<Compile Include="Mod.cs" />
<Compile Include="PackageEntry.cs" />
<Compile Include="Package.cs" />
<Compile Include="PackageWriter.cs" />

View File

@@ -20,7 +20,6 @@ namespace OpenRA.FileFormats
Stream GetContent(string filename);
bool Exists(string filename);
IEnumerable<uint> AllFileHashes();
int Priority { get; }
}
public class Package : IFolder
@@ -29,11 +28,9 @@ namespace OpenRA.FileFormats
readonly bool isRmix, isEncrypted;
readonly long dataStart;
readonly Stream s;
int priority;
public Package(string filename, int priority)
public Package(string filename)
{
this.priority = priority;
s = FileSystem.Open(filename);
BinaryReader reader = new BinaryReader(s);
@@ -152,12 +149,6 @@ namespace OpenRA.FileFormats
{
return index.ContainsKey(PackageEntry.HashFilename(filename));
}
public int Priority
{
get { return 1000 + priority; }
}
}
[Flags]

View File

@@ -8,8 +8,11 @@
*/
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System;
namespace OpenRA.FileFormats
{

31
OpenRA.FileFormats/PlayerColorRemap.cs Executable file → Normal file
View File

@@ -32,7 +32,7 @@ namespace OpenRA.FileFormats
.ToDictionary(u => u.First, u => u.Second);
}
public static Color ColorLerp(float t, Color c1, Color c2)
static Color ColorLerp(float t, Color c1, Color c2)
{
return Color.FromArgb(255,
(int)(t * c2.R + (1 - t) * c1.R),
@@ -46,34 +46,5 @@ namespace OpenRA.FileFormats
return remapColors.TryGetValue(index, out c)
? c : original;
}
// hk is hue in the range [0,1] instead of [0,360]
public static Color ColorFromHSL(float hk, float s, float l)
{
// Convert from HSL to RGB
var q = (l < 0.5f) ? l * (1 + s) : l + s - (l * s);
var p = 2 * l - q;
float[] trgb = { hk + 1 / 3.0f,
hk,
hk - 1/3.0f };
float[] rgb = { 0, 0, 0 };
for (int k = 0; k < 3; k++)
{
while (trgb[k] < 0) trgb[k] += 1.0f;
while (trgb[k] > 1) trgb[k] -= 1.0f;
}
for (int k = 0; k < 3; k++)
{
if (trgb[k] < 1 / 6.0f) { rgb[k] = (p + ((q - p) * 6 * trgb[k])); }
else if (trgb[k] >= 1 / 6.0f && trgb[k] < 0.5) { rgb[k] = q; }
else if (trgb[k] >= 0.5f && trgb[k] < 2.0f / 3) { rgb[k] = (p + ((q - p) * 6 * (2.0f / 3 - trgb[k]))); }
else { rgb[k] = p; }
}
return Color.FromArgb((int)(rgb[0] * 255), (int)(rgb[1] * 255), (int)(rgb[2] * 255));
}
}
}

View File

@@ -62,8 +62,7 @@ namespace OpenRA
Constrain(Y, min.Y, max.Y));
}
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
public static float2 operator *(float2 b, float a) { return new float2(a * b.X, a * b.Y); }
public static float2 operator *(float a, float2 b) { return new float2(a * b.X, a * b.Y); }
public static float2 operator *( float2 a, float2 b ) { return new float2( a.X * b.X, a.Y * b.Y ); }
public static float2 operator /( float2 a, float2 b ) { return new float2( a.X / b.X, a.Y / b.Y ); }

View File

@@ -27,8 +27,6 @@ namespace OpenRA
public static int2 operator *(int2 b, int a) { return new int2(a * b.X, a * b.Y); }
public static int2 operator /(int2 a, int b) { return new int2(a.X / b, a.Y / b); }
public static int2 operator -(int2 a) { return new int2(-a.X, -a.Y); }
public static bool operator ==(int2 me, int2 other) { return (me.X == other.X && me.Y == other.Y); }
public static bool operator !=(int2 me, int2 other) { return !(me == other); }

View File

@@ -61,8 +61,8 @@ namespace OpenRA
// auto size from render
var firstSprite = TraitsImplementing<IRender>().SelectMany(x => x.Render(this)).FirstOrDefault();
if (firstSprite.Sprite == null) return float2.Zero;
return firstSprite.Sprite.size * firstSprite.Scale;
if (firstSprite.Sprite == null) return float2.Zero;
return firstSprite.Sprite.size;
});
}
@@ -110,13 +110,7 @@ namespace OpenRA
{
var si = Info.Traits.GetOrDefault<SelectableInfo>();
var size = Size.Value;
/* apply scaling */
var scale = this.TraitOrDefault<Scale>();
if (scale != null && scale.Info.Value != 1)
size = size*scale.Info.Value;
var size = Size.Value;
var loc = CenterLocation - 0.5f * size;
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
@@ -200,8 +194,6 @@ namespace OpenRA
{
World.AddFrameEndTask( w =>
{
if (Destroyed) return;
World.Remove( this );
World.traitDict.RemoveActor( this );
Destroyed = true;

View File

@@ -20,9 +20,9 @@ namespace OpenRA
sequence = CursorProvider.GetCursorSequence(cursor);
}
public void Draw(WorldRenderer wr, int frame, float2 pos)
public void Draw(int frame, float2 pos)
{
sequence.GetSprite(frame).DrawAt(wr, pos - sequence.Hotspot, sequence.Palette);
sequence.GetSprite(frame).DrawAt(pos - sequence.Hotspot, sequence.Palette);
}
}
}

View File

@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Support;
using OpenRA.Traits;
namespace OpenRA
{

514
OpenRA.Game/Game.cs Executable file → Normal file
View File

@@ -6,20 +6,18 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using System.Windows.Forms;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Server;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Server;
using OpenRA.Support;
using OpenRA.Widgets;
@@ -32,8 +30,7 @@ namespace OpenRA
public static int CellSize { get { return modData.Manifest.TileSize; } }
public static ModData modData;
private static WorldRenderer worldRenderer;
public static World world;
public static Viewport viewport;
public static Settings Settings;
@@ -42,25 +39,36 @@ namespace OpenRA
public static XRandom CosmeticRandom = new XRandom(); // not synced
public static Renderer Renderer;
public static Session LobbyInfo = new Session();
public static bool HasInputFocus = false;
public static void MoveViewport(float2 loc)
static void LoadMap(string uid)
{
var map = modData.PrepareMap(uid);
viewport = new Viewport(new float2(Renderer.Resolution), map.TopLeft, map.BottomRight, Renderer);
world = new World(modData.Manifest, map);
}
public static void MoveViewport(int2 loc)
{
viewport.Center(loc);
}
internal static string CurrentHost = "";
internal static int CurrentPort = 0;
internal static void JoinServer(string host, int port)
{
if (orderManager != null) orderManager.Dispose();
var replayFilename = ChooseReplayFilename();
string path = Path.Combine( Game.SupportDir, "Replays" );
if( !Directory.Exists( path ) ) Directory.CreateDirectory( path );
var replayFile = File.Create( Path.Combine( path, replayFilename ) );
CurrentHost = host;
CurrentPort = port;
orderManager = new OrderManager( host, port, new ReplayRecorderConnection( new NetworkConnection( host, port ), replayFile ) );
lastConnectionState = ConnectionState.PreConnecting;
ConnectionStateChanged(orderManager);
ConnectionStateChanged();
orderManager = new OrderManager(new NetworkConnection(host, port), ChooseReplayFilename());
}
static string ChooseReplayFilename()
@@ -70,36 +78,73 @@ namespace OpenRA
static void JoinLocal()
{
if (orderManager != null) orderManager.Dispose();
orderManager = new OrderManager("<no server>", -1, new EchoConnection());
lastConnectionState = ConnectionState.PreConnecting;
ConnectionStateChanged( orderManager );
ConnectionStateChanged();
if (orderManager != null) orderManager.Dispose();
orderManager = new OrderManager(new EchoConnection());
}
static int lastTime = Environment.TickCount;
static void ResetTimer()
{
lastTime = Environment.TickCount;
}
internal static int RenderFrame = 0;
internal static int LocalTick { get { return orderManager.LocalFrameNumber; } }
internal static int LocalTick = 0;
const int NetTickScale = 3; // 120ms net tick for 40ms local tick
public static event Action<OrderManager> ConnectionStateChanged = _ => { };
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
public static event Action ConnectionStateChanged = () => { };
static ConnectionState lastConnectionState = ConnectionState.PreConnecting;
public static int LocalClientId { get { return orderManager.Connection.LocalClientId; } }
static void Tick( OrderManager orderManager, Viewport viewPort )
static void Tick( World world, OrderManager orderManager, Viewport viewPort )
{
if (orderManager.Connection.ConnectionState != lastConnectionState)
{
lastConnectionState = orderManager.Connection.ConnectionState;
ConnectionStateChanged( orderManager );
}
if (orderManager.Connection.ConnectionState != lastConnectionState)
{
lastConnectionState = orderManager.Connection.ConnectionState;
ConnectionStateChanged();
}
Tick( orderManager );
if( orderManager.world != worldRenderer.world )
Tick( worldRenderer.world.orderManager );
int t = Environment.TickCount;
int dt = t - lastTime;
if (dt >= Settings.Game.Timestep)
{
using (new PerfSample("tick_time"))
{
lastTime += Settings.Game.Timestep;
Widget.DoTick(world);
Sound.Tick();
orderManager.TickImmediate(world);
var isNetTick = LocalTick % NetTickScale == 0;
if (!isNetTick || orderManager.IsReadyForNextFrame)
{
++LocalTick;
Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local");
if (isNetTick) orderManager.Tick(world);
world.OrderGenerator.Tick(world);
world.Selection.Tick(world);
world.Tick();
PerfHistory.Tick();
}
else
if (orderManager.FrameNumber == 0)
lastTime = Environment.TickCount;
}
}
using (new PerfSample("render"))
{
++RenderFrame;
viewport.DrawRegions(worldRenderer, new DefaultInputHandler( orderManager.world ));
viewport.DrawRegions(world);
Sound.SetListenerPosition(viewport.Location + .5f * new float2(viewport.Width, viewport.Height));
}
@@ -111,73 +156,64 @@ namespace OpenRA
MasterServerQuery.Tick();
}
private static void Tick( OrderManager orderManager )
internal static event Action LobbyInfoChanged = () => { };
internal static void SyncLobbyInfo( World world, string data)
{
int t = Environment.TickCount;
int dt = t - orderManager.LastTickTime;
if (dt >= Settings.Game.Timestep)
using( new PerfSample( "tick_time" ) )
{
orderManager.LastTickTime += Settings.Game.Timestep;
Widget.DoTick();
var world = orderManager.world;
if( orderManager.GameStarted && world.LocalPlayer != null )
++Viewport.TicksSinceLastMove;
Sound.Tick();
Sync.CheckSyncUnchanged( world, () => { orderManager.TickImmediate(); } );
LobbyInfo = Session.Deserialize(data);
var isNetTick = LocalTick % NetTickScale == 0;
if( !world.GameHasStarted )
world.SharedRandom = new XRandom( LobbyInfo.GlobalSettings.RandomSeed );
if( !isNetTick || orderManager.IsReadyForNextFrame )
{
++orderManager.LocalFrameNumber;
if (orderManager.Connection.ConnectionState == ConnectionState.Connected)
world.SetLocalPlayer(orderManager.Connection.LocalClientId);
Log.Write( "debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local" );
if (orderManager.FramesAhead != LobbyInfo.GlobalSettings.OrderLatency
&& !orderManager.GameStarted)
{
orderManager.FramesAhead = LobbyInfo.GlobalSettings.OrderLatency;
Debug("Order lag is now {0} frames.".F(LobbyInfo.GlobalSettings.OrderLatency));
}
if( isNetTick ) orderManager.Tick();
Sync.CheckSyncUnchanged(world, () =>
{
world.OrderGenerator.Tick(world);
world.Selection.Tick(world);
});
world.Tick();
PerfHistory.Tick();
}
else
if( orderManager.NetFrameNumber == 0 )
orderManager.LastTickTime = Environment.TickCount;
}
}
public static event Action LobbyInfoChanged = () => { };
public static event Action ConnectedToLobby = () => { };
internal static void SyncLobbyInfo()
{
LobbyInfoChanged();
}
public static event Action<World> AfterGameStart = _ => {};
public static void IssueOrder( Order o ) { orderManager.IssueOrder( o ); } /* avoid exposing the OM to mod code */
public static event Action AfterGameStart = () => {};
public static event Action BeforeGameStart = () => {};
internal static void StartGame(string mapUID)
internal static void StartGame(string map)
{
world = null;
BeforeGameStart();
var map = modData.PrepareMap(mapUID);
viewport = new Viewport(new int2(Renderer.Resolution), map.TopLeft, map.BottomRight, Renderer);
orderManager.world = new World(modData.Manifest, map, orderManager);
worldRenderer = new WorldRenderer(orderManager.world);
LoadMap(map);
if (orderManager.GameStarted) return;
Widget.SelectedWidget = null;
orderManager.LocalFrameNumber = 0;
orderManager.StartGame();
worldRenderer.RefreshPalette();
AfterGameStart( orderManager.world );
LocalTick = 0;
orderManager.StartGame();
viewport.RefreshPalette();
AfterGameStart();
}
public static void DispatchMouseInput(MouseInputEvent ev, MouseEventArgs e, Modifiers modifierKeys)
{
var world = Game.world;
if (world == null) return;
Sync.CheckSyncUnchanged( world, () =>
{
var mi = new MouseInput
{
Button = (MouseButton)(int)e.Button,
Event = ev,
Location = new int2( e.Location ),
Modifiers = modifierKeys,
};
Widget.HandleInput( world, mi );
} );
}
public static bool IsHost
@@ -185,26 +221,40 @@ namespace OpenRA
get { return orderManager.Connection.LocalClientId == 0; }
}
internal static Session.Client LocalClient
{
get { return LobbyInfo.Clients.FirstOrDefault(c => c.Index == orderManager.Connection.LocalClientId); }
}
public static void HandleKeyEvent(KeyInput e)
{
var world = Game.world;
if( world == null ) return;
Sync.CheckSyncUnchanged( world, () =>
{
Widget.HandleKeyPress( e );
} );
}
static Modifiers modifiers;
public static Modifiers GetModifierKeys() { return modifiers; }
internal static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
public static void HandleModifierKeys(Modifiers mods) { modifiers = mods; }
internal static void Initialize(Arguments args)
{
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
+ Path.DirectorySeparatorChar + "OpenRA";
SupportDir = args.GetValue("SupportDir", defaultSupport);
Settings = new Settings(SupportDir + "settings.yaml", args);
Settings.Save();
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
Log.AddChannel("perf", "perf.log");
Log.AddChannel("debug", "debug.log");
Log.AddChannel("sync", "syncreport.log");
AppDomain.CurrentDomain.AssemblyResolve += FileSystem.ResolveAssembly;
var defaultSupport = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
+ Path.DirectorySeparatorChar + "OpenRA";
SupportDir = args.GetValue("SupportDir", defaultSupport);
Settings = new Settings(SupportDir + "settings.yaml", args);
Log.LogPath = SupportDir + "Logs" + Path.DirectorySeparatorChar;
Log.AddChannel("perf", "perf.log");
Log.AddChannel("debug", "debug.log");
Log.AddChannel("sync", "syncreport.log");
FileSystem.Mount("."); // Needed to access shaders
Renderer.Initialize( Game.Settings.Graphics.Mode );
@@ -212,148 +262,55 @@ namespace OpenRA
Renderer = new Renderer();
Console.WriteLine("Available mods:");
foreach(var mod in Mod.AllMods)
foreach(var mod in ModData.AllMods)
Console.WriteLine("\t{0}: {1} ({2})", mod.Key, mod.Value.Title, mod.Value.Version);
// Discard any invalid mods
var mods = Settings.Game.Mods.Where( m => Mod.AllMods.ContainsKey( m ) ).ToArray();
Console.WriteLine("Loading mods: {0}",string.Join(",",mods));
LobbyInfo.GlobalSettings.Mods = Settings.Game.Mods.Where(m => ModData.AllMods.ContainsKey(m)).ToArray();
Console.WriteLine("Loading mods: {0}",string.Join(",",LobbyInfo.GlobalSettings.Mods));
modData = new ModData( LobbyInfo.GlobalSettings.Mods );
modData = new ModData( mods );
// when this client is running in dedicated mode ...
if (Settings.Server.IsDedicated)
{
// it may specify a yaml extension file (to add non synced traits)
if (!string.IsNullOrEmpty(Settings.Server.ExtensionYaml))
{
var r = modData.Manifest.LocalRules.ToList();
r.Add(Settings.Server.ExtensionYaml);
modData.Manifest.LocalRules = r.ToArray();
}
// and a dll to the assemblies (to add those non synced traits)
if (!string.IsNullOrEmpty(Settings.Server.ExtensionDll))
{
var r = modData.Manifest.LocalAssemblies.ToList();
r.Add(Settings.Server.ExtensionDll);
modData.Manifest.LocalAssemblies = r.ToArray();
}
if (!string.IsNullOrEmpty(Settings.Server.ExtensionClass))
Settings.Server.Extension = modData.ObjectCreator.CreateObject<IServerExtension>(Settings.Server.ExtensionClass);
}
Sound.Initialize();
PerfHistory.items["render"].hasNormalTick = false;
PerfHistory.items["batches"].hasNormalTick = false;
PerfHistory.items["text"].hasNormalTick = false;
PerfHistory.items["cursor"].hasNormalTick = false;
PerfHistory.items["cursor"].hasNormalTick = false;
JoinLocal();
StartGame(modData.Manifest.ShellmapUid);
if (!Settings.Graphics.UseNullRenderer)
Game.BeforeGameStart += () => Widget.OpenWindow("INGAME_ROOT");
Game.ConnectionStateChanged += () =>
JoinLocal();
StartGame(modData.Manifest.ShellmapUid);
Game.ConnectionStateChanged += om =>
{
Widget.CloseWindow();
switch (om.Connection.ConnectionState)
{
case ConnectionState.PreConnecting:
Widget.OpenWindow("MAINMENU_BG");
break;
case ConnectionState.Connecting:
Widget.OpenWindow("CONNECTING_BG",
new Dictionary<string, object>
{{"host", om.Host}, {"port", om.Port}});
break;
case ConnectionState.NotConnected:
Widget.OpenWindow("CONNECTION_FAILED_BG",
new Dictionary<string, object>
{{"host", om.Host}, {"port", om.Port}});
break;
case ConnectionState.Connected:
var lobby = Widget.OpenWindow("SERVER_LOBBY",
new Dictionary<string, object>
{{"orderManager", om}});
lobby.GetWidget<ChatDisplayWidget>("CHAT_DISPLAY").ClearChat();
lobby.GetWidget("CHANGEMAP_BUTTON").Visible = true;
lobby.GetWidget("LOCKTEAMS_CHECKBOX").Visible = true;
lobby.GetWidget("DISCONNECT_BUTTON").Visible = true;
// Inform whoever is willing to hear it that the player is connected to the lobby
if (ConnectedToLobby != null)
ConnectedToLobby();
if (Settings.Server.IsDedicated)
{
// Force spectator as a default
Game.orderManager.IssueOrder(Order.Command("spectator"));
}
if (Game.Settings.Server.Extension != null)
Game.Settings.Server.Extension.OnLobbyUp();
break;
}
};
modData.WidgetLoader.LoadWidget(new Dictionary<string, object>(), Widget.RootWidget, "PERF_BG");
Widget.OpenWindow("MAINMENU_BG");
}else
{
JoinLocal();
StartGame(modData.Manifest.ShellmapUid);
Game.ConnectionStateChanged += om =>
{
Widget.CloseWindow();
switch( Game.orderManager.Connection.ConnectionState )
Widget.CloseWindow();
switch (om.Connection.ConnectionState)
{
case ConnectionState.PreConnecting:
Widget.OpenWindow("MAINMENU_BG");
break;
case ConnectionState.Connecting:
Widget.OpenWindow("CONNECTING_BG",
new Dictionary<string, object> { { "host", om.Host }, { "port", om.Port } });
break;
case ConnectionState.NotConnected:
Widget.OpenWindow("CONNECTION_FAILED_BG",
new Dictionary<string, object> { { "host", om.Host }, { "port", om.Port } });
break;
case ConnectionState.Connected:
var lobby = Widget.OpenWindow("SERVER_LOBBY",
new Dictionary<string, object> { { "orderManager", om } });
{
case ConnectionState.PreConnecting:
Widget.OpenWindow("MAINMENU_BG");
break;
case ConnectionState.Connecting:
Widget.OpenWindow("CONNECTING_BG");
break;
case ConnectionState.NotConnected:
Widget.OpenWindow("CONNECTION_FAILED_BG");
break;
case ConnectionState.Connected:
var lobby = Widget.OpenWindow("SERVER_LOBBY");
lobby.GetWidget<ChatDisplayWidget>("CHAT_DISPLAY").ClearChat();
lobby.GetWidget("CHANGEMAP_BUTTON").Visible = true;
lobby.GetWidget("LOCKTEAMS_CHECKBOX").Visible = true;
lobby.GetWidget("DISCONNECT_BUTTON").Visible = true;
//r.GetWidget("INGAME_ROOT").GetWidget<ChatDisplayWidget>("CHAT_DISPLAY").ClearChat();
break;
}
};
// Inform whoever is willing to hear it that the player is connected to the lobby
if (ConnectedToLobby != null)
ConnectedToLobby();
modData.WidgetLoader.LoadWidget( Widget.RootWidget, "PERF_BG" );
Widget.OpenWindow("MAINMENU_BG");
if (Settings.Server.IsDedicated)
{
// Force spectator as a default
Game.orderManager.IssueOrder(Order.Command("spectator"));
}
if (Game.Settings.Server.Extension != null)
Game.Settings.Server.Extension.OnLobbyUp();
break;
}
};
modData.WidgetLoader.LoadWidget(new Dictionary<string, object>(), Widget.RootWidget, "PERF_BG");
Widget.OpenWindow("MAINMENU_BG");
}
if (Settings.Server.IsDedicated)
{
// Auto-host
var map = Game.modData.AvailableMaps.FirstOrDefault(m => m.Value.Selectable).Key;
Server.Server.ServerMain(Game.modData, Settings, map);
Game.JoinServer(IPAddress.Loopback.ToString(), Settings.Server.ListenPort);
}
Game.orderManager.LastTickTime = Environment.TickCount;
ResetTimer();
}
@@ -361,90 +318,55 @@ namespace OpenRA
internal static void Run()
{
while (!quit)
Tick( orderManager, viewport );
{
Tick( world, orderManager, viewport );
Application.DoEvents();
}
}
public static void Exit() { quit = true; }
public static void Exit() { quit = true; }
public static Action<Color,string,string> AddChatLine = (c,n,s) => {};
public static void Debug(string s, params object[] args)
{
AddChatLine(Color.White, "Debug", String.Format(s,args));
public static void Debug(string s, params object[] args)
{
AddChatLine(Color.White, "Debug", String.Format(s,args));
}
public static void Disconnect()
if (IsHost)
Server.Server.StopListening();
{
orderManager.Dispose();
var shellmap = modData.Manifest.ShellmapUid;
LobbyInfo = new Session();
LobbyInfo.GlobalSettings.Mods = Settings.Game.Mods;
JoinLocal();
StartGame(shellmap);
Widget.CloseWindow();
}
static string baseSupportDir = null;
public static string SupportDir
{
set
{
var dir = value;
// Expand paths relative to the personal directory
if (dir.ElementAt(0) == '~')
dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
baseSupportDir = dir + Path.DirectorySeparatorChar;
Widget.OpenWindow("MAINMENU_BG");
}
static string baseSupportDir = null;
public static string SupportDir
{
set
{
var dir = value;
// Expand paths relative to the personal directory
if (dir.ElementAt(0) == '~')
dir = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir.Substring(1);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
baseSupportDir = dir + Path.DirectorySeparatorChar;
get { return baseSupportDir; }
}
get { return baseSupportDir; }
}
public static T CreateObject<T>( string name )
{
return modData.ObjectCreator.CreateObject<T>( name );
public static void RejoinLobby(World world)
{
if (Game.IsHost && Game.Settings.Server.Extension != null)
Game.Settings.Server.Extension.OnRejoinLobby(world);
var map = orderManager.LobbyInfo.GlobalSettings.Map;
var host = orderManager.Host;
var port = orderManager.Port;
var isHost = Game.IsHost;
Disconnect();
ConnectedToLobby += () =>
{
if (world.LocalPlayer != null)
{
/* Try to get back the old slot */
Game.orderManager.IssueOrder(Order.Command("race " + world.LocalPlayer.Country.Race));
Game.orderManager.IssueOrder(Order.Command("slot " + world.LobbyInfo.ClientWithIndex(world.LocalPlayer.ClientIndex).Slot));
}else /* a spectator */
{
Game.orderManager.IssueOrder(Order.Command("spectator"));
}
ConnectedToLobby = null;
};
if (isHost)
{
Server.Server.ServerMain(Game.modData, Settings, map);
JoinServer(IPAddress.Loopback.ToString(), Settings.Server.ListenPort);
}
else
JoinServer(host, port);
}
}
}
}

View File

@@ -66,21 +66,21 @@ namespace OpenRA
var ret = new List<ITraitInfo>();
var t = Traits.WithInterface<ITraitInfo>().ToList();
int index = 0;
while (t.Count != 0)
while( t.Count != 0 )
{
var prereqs = PrerequisitesOf(t[index]);
var unsatisfied = prereqs.Where(n => !ret.Any(x => x.GetType() == n || x.GetType().IsSubclassOf(n)));
if (!unsatisfied.Any())
if( index >= t.Count )
throw new InvalidOperationException( "Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1}".F(
Name, string.Join( ",", t.Select( x => x.GetType().Name ).ToArray())));
var prereqs = PrerequisitesOf( t[ index ] );
if( prereqs.Count == 0 || prereqs.All( n => ret.Any( x => x.GetType() == n || x.GetType().IsSubclassOf( n ) ) ) )
{
ret.Add(t[index]);
t.RemoveAt(index);
ret.Add( t[ index ] );
t.RemoveAt( index );
index = 0;
}
else if (++index >= t.Count)
throw new InvalidOperationException("Trait prerequisites not satisfied (or prerequisite loop) Actor={0} Unresolved={1} Missing={2}".F(
Name,
string.Join(",", t.Select(x => x.GetType().Name).ToArray()),
string.Join(",", unsatisfied.Select(x => x.Name).ToArray())));
else
++index;
}
return ret;

View File

@@ -11,10 +11,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
namespace OpenRA.GameRules
{
public static class FootprintUtils
public static class Footprint
{
public static IEnumerable<int2> Tiles( string name, BuildingInfo buildingInfo, int2 topLeft )
{

View File

@@ -27,9 +27,7 @@ namespace OpenRA
public static void LoadRules(Manifest m, Map map)
{
// Added support to extend the list of rules (add it to m.LocalRules)
// Should only be used to add ITraitNoSync traits! (otherwise BOOM)
Info = LoadYamlRules(m.Rules.Concat(m.LocalRules).ToArray(), map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
Weapons = LoadYamlRules(m.Weapons, new List<MiniYamlNode>(), (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
Voices = LoadYamlRules(m.Voices, new List<MiniYamlNode>(), (k, _) => new VoiceInfo(k.Value));
Music = LoadYamlRules(m.Music, new List<MiniYamlNode>(), (k, _) => new MusicInfo(k.Key, k.Value));

View File

@@ -15,7 +15,6 @@ using System.IO;
using System.Windows.Forms;
using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics;
using OpenRA.Server;
namespace OpenRA.GameRules
{
@@ -27,32 +26,22 @@ namespace OpenRA.GameRules
public bool AdvertiseOnline = true;
public string MasterServer = "http://master.open-ra.org/";
public bool AllowCheats = false;
public string ExtensionDll = "";
public string ExtensionClass = "";
/* not storeable */
public IServerExtension Extension { get; set; }
public string ExtensionYaml { get; set; }
public bool IsDedicated { get; set; }
}
public class DebugSettings
{
public bool BotDebug = false;
public bool PerfGraph = false;
public bool RecordSyncReports = true;
public bool ShowCollisions = false;
public float LongTickThreshold = 0.001f;
}
public class GraphicSettings
{
public WindowMode Mode = WindowMode.PseudoFullscreen;
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
public int2 WindowedSize = new int2(1024, 768);
public int2 FullscreenSize = new int2(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);
public int2 WindowedSize = new int2(1024,768);
public readonly int2 MinResolution = new int2(800, 600);
public readonly string RenderEngine = "OpenRA.Gl.dll";
public readonly string NullRenderEngine = "OpenRA.Renderer.Null.dll";
public bool UseNullRenderer { get; set; }
}
public class SoundSettings
@@ -77,9 +66,6 @@ namespace OpenRA.GameRules
public string[] Mods = { "ra" };
public bool MatchTimer = true;
// Chat settings
public bool TeamChatToggle = false;
// Behaviour settings
public bool ViewportEdgeScroll = true;
public bool InverseDragScroll = false;
@@ -115,23 +101,18 @@ namespace OpenRA.GameRules
{"Debug", Debug}
};
// Should we run in dedicated mode (use the server extension)
Server.IsDedicated = args.GetValue("Server.IsDedicated", false);
if (Server.IsDedicated)
Graphics.UseNullRenderer = args.GetValue("Graphics.UseNullRenderer", false);
// Override fieldloader to ignore invalid entries
var err1 = FieldLoader.UnknownFieldAction;
var err2 = FieldLoader.InvalidValueAction;
FieldLoader.UnknownFieldAction = (s,f) =>
{
Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
System.Console.WriteLine( "Ignoring unknown field `{0}` on `{1}`".F( s, f.Name ) );
};
if (File.Exists(SettingsFile))
{
Console.WriteLine("Loading settings file {0}",SettingsFile);
System.Console.WriteLine("Loading settings file {0}",SettingsFile);
var yaml = MiniYaml.DictFromFile(SettingsFile);
foreach (var kv in Sections)
@@ -143,7 +124,7 @@ namespace OpenRA.GameRules
foreach (var kv in Sections)
foreach (var f in kv.Value.GetType().GetFields())
if (args.Contains(kv.Key+"."+f.Name))
FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") );
OpenRA.FileFormats.FieldLoader.LoadField( kv.Value, f.Name, args.GetValue(kv.Key+"."+f.Name, "") );
FieldLoader.UnknownFieldAction = err1;
FieldLoader.InvalidValueAction = err2;
@@ -153,7 +134,7 @@ namespace OpenRA.GameRules
{
var root = new List<MiniYamlNode>();
foreach( var kv in Sections )
root.Add( new MiniYamlNode( kv.Key, FieldSaver.SaveDifferences(kv.Value, Activator.CreateInstance(kv.Value.GetType())) ) );
root.Add( new MiniYamlNode( kv.Key, FieldSaver.Save(kv.Value) ) );
root.WriteToFile(SettingsFile);
}

View File

@@ -31,7 +31,7 @@ namespace OpenRA.GameRules
: new Dictionary<string, string[]>();
}
public readonly OpenRA.FileFormats.Lazy<Dictionary<string, VoicePool>> Pools;
public readonly Lazy<Dictionary<string, VoicePool>> Pools;
public VoiceInfo( MiniYaml y )
{
@@ -41,9 +41,6 @@ namespace OpenRA.GameRules
if (!Voices.ContainsKey("Attack"))
Voices.Add("Attack", Voices["Move"]);
if (!Voices.ContainsKey("AttackMove"))
Voices.Add("AttackMove", Voices["Move"]);
Pools = Lazy.New(() => Voices.ToDictionary( a => a.Key, a => new VoicePool(a.Value) ));
}

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Graphics
}
Sprite[] LoadCursors(string filename)
{
{
try
{
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));

View File

@@ -135,12 +135,10 @@ namespace OpenRA.Graphics
unsafe
{
int* c = (int*)bitmapData.Scan0;
var player = world.LocalPlayer;
foreach (var t in world.Queries.WithTraitMultiple<IRadarSignature>())
{
if (!t.Actor.IsVisible(player))
if (!t.Actor.IsVisible(world.LocalPlayer))
continue;
var color = t.Trait.RadarSignatureColor(t.Actor);
@@ -164,9 +162,7 @@ namespace OpenRA.Graphics
var shroud = Color.Black.ToArgb();
var fog = Color.FromArgb(128, Color.Black).ToArgb();
var playerShroud = world.LocalPlayer.Shroud;
unsafe
{
int* c = (int*)bitmapData.Scan0;
@@ -176,9 +172,9 @@ namespace OpenRA.Graphics
{
var mapX = x + map.TopLeft.X;
var mapY = y + map.TopLeft.Y;
if (!playerShroud.IsExplored(mapX, mapY))
if (!world.LocalPlayer.Shroud.IsExplored(mapX, mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = shroud;
else if (!playerShroud.IsVisible(mapX,mapY))
else if (!world.LocalPlayer.Shroud.IsVisible(mapX,mapY))
*(c + (y * bitmapData.Stride >> 2) + x) = fog;
}
}

View File

@@ -9,14 +9,14 @@
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using OpenRA.FileFormats;
using OpenRA.FileFormats.Graphics;
using OpenRA.Support;
using System.Windows.Forms;
using System.Collections.Generic;
namespace OpenRA.Graphics
{
@@ -71,6 +71,7 @@ namespace OpenRA.Graphics
public void BeginFrame(float2 scroll)
{
device.Begin();
device.Clear(Color.Black);
float2 r1 = new float2(2f/Resolution.Width, -2f/Resolution.Height);
@@ -85,16 +86,17 @@ namespace OpenRA.Graphics
private void SetShaderParams( IShader s, float2 r1, float2 r2, float2 scroll )
{
s.SetValue( "Palette", PaletteTexture );
s.SetValue( "Scroll", (int) scroll.X, (int) scroll.Y );
s.SetValue( "Scroll", scroll.X, scroll.Y );
s.SetValue( "r1", r1.X, r1.Y );
s.SetValue( "r2", r2.X, r2.Y );
s.Commit();
}
public void EndFrame( IInputHandler inputHandler )
public void EndFrame()
{
Flush();
device.Present( inputHandler );
device.End();
device.Present();
}
public void DrawBatch<T>(IVertexBuffer<T> vertices, IIndexBuffer indices,
@@ -133,11 +135,7 @@ namespace OpenRA.Graphics
internal static void Initialize( OpenRA.FileFormats.Graphics.WindowMode windowMode )
{
var resolution = GetResolution( windowMode );
if (Game.Settings.Graphics.UseNullRenderer)
device = CreateDevice(Assembly.LoadFile(Path.GetFullPath(Game.Settings.Graphics.NullRenderEngine)), resolution.Width, resolution.Height, windowMode, false);
else
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( Game.Settings.Graphics.RenderEngine ) ), resolution.Width, resolution.Height, windowMode, false );
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Gl.dll" ) ), resolution.Width, resolution.Height, windowMode, false );
}
static Size GetResolution(WindowMode windowmode)

View File

@@ -50,9 +50,9 @@ namespace OpenRA.Graphics
return uvhax[ k ];
}
public void DrawAt( WorldRenderer wr, float2 location, string palette )
public void DrawAt( float2 location, string palette )
{
Game.Renderer.SpriteRenderer.DrawSprite( this, location, wr, palette, this.size );
Game.Renderer.SpriteRenderer.DrawSprite( this, location, palette, this.size );
}
public void DrawAt( float2 location, int paletteIndex )
@@ -60,10 +60,10 @@ namespace OpenRA.Graphics
Game.Renderer.SpriteRenderer.DrawSprite( this, location, paletteIndex, this.size );
}
public void DrawAt(float2 location, int paletteIndex, float scale)
{
Game.Renderer.SpriteRenderer.DrawSprite(this, location, paletteIndex, this.size * scale);
}
public void DrawAt(float2 location, string palette, float2 size)
{
Game.Renderer.SpriteRenderer.DrawSprite( this, location, palette, size );
}
public void DrawAt( float2 location, int paletteIndex, float2 size )
{

View File

@@ -54,14 +54,14 @@ namespace OpenRA.Graphics
}
}
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette)
public void DrawSprite(Sprite s, float2 location, string palette)
{
DrawSprite(s, location, wr.GetPaletteIndex(palette), s.size);
DrawSprite(s, location, Game.world.WorldRenderer.GetPaletteIndex(palette), s.size);
}
public void DrawSprite(Sprite s, float2 location, WorldRenderer wr, string palette, float2 size)
public void DrawSprite(Sprite s, float2 location, string palette, float2 size)
{
DrawSprite(s, location, wr.GetPaletteIndex(palette), size);
DrawSprite(s, location, Game.world.WorldRenderer.GetPaletteIndex(palette), size);
}
public void DrawSprite(Sprite s, float2 location, int paletteIndex, float2 size)

View File

@@ -62,7 +62,7 @@ namespace OpenRA.Graphics
indexBuffer.SetData( indices, ni );
}
public void Draw( WorldRenderer wr, Viewport viewport )
public void Draw( Viewport viewport )
{
int indicesPerRow = map.Width * 6;
int verticesPerRow = map.Width * 4;
@@ -98,7 +98,7 @@ namespace OpenRA.Graphics
PrimitiveType.TriangleList, Game.Renderer.SpriteShader));
foreach (var r in world.WorldActor.TraitsImplementing<IRenderOverlay>())
r.Render( wr );
r.Render();
}
}
}

54
OpenRA.Game/Graphics/Viewport.cs Executable file → Normal file
View File

@@ -11,6 +11,7 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Support;
using OpenRA.Traits;
using OpenRA.Widgets;
@@ -18,16 +19,16 @@ namespace OpenRA.Graphics
{
public class Viewport
{
readonly int2 screenSize;
int2 scrollPosition;
readonly float2 screenSize;
float2 scrollPosition;
readonly Renderer renderer;
readonly int2 mapStart;
readonly int2 mapEnd;
public float2 Location { get { return scrollPosition; } }
public int Width { get { return screenSize.X; } }
public int Height { get { return screenSize.Y; } }
public int Width { get { return (int)screenSize.X; } }
public int Height { get { return (int)screenSize.Y; } }
float cursorFrame = 0f;
@@ -41,8 +42,7 @@ namespace OpenRA.Graphics
public void Scroll(float2 delta, bool ignoreBorders)
{
var d = delta.ToInt2();
var newScrollPosition = scrollPosition + d;
float2 newScrollPosition = scrollPosition + delta;
if(!ignoreBorders)
newScrollPosition = this.NormalizeScrollPosition(newScrollPosition);
@@ -50,10 +50,10 @@ namespace OpenRA.Graphics
scrollPosition = newScrollPosition;
}
private int2 NormalizeScrollPosition(int2 newScrollPosition)
private float2 NormalizeScrollPosition(float2 newScrollPosition)
{
var topLeftBorder = Game.CellSize* mapStart;
var bottomRightBorder = Game.CellSize* mapEnd;
float2 topLeftBorder = (Game.CellSize* mapStart).ToFloat2();
float2 bottomRightBorder = (Game.CellSize* mapEnd).ToFloat2();
if(newScrollPosition.Y < topLeftBorder.Y - screenSize.Y/2)
newScrollPosition.Y = topLeftBorder.Y - screenSize.Y/2;
@@ -86,7 +86,7 @@ namespace OpenRA.Graphics
return blockedDirections;
}
public Viewport(int2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
public Viewport(float2 screenSize, int2 mapStart, int2 mapEnd, Renderer renderer)
{
this.screenSize = screenSize;
this.renderer = renderer;
@@ -96,23 +96,30 @@ namespace OpenRA.Graphics
this.scrollPosition = Game.CellSize* mapStart;
}
public void DrawRegions( WorldRenderer wr, IInputHandler inputHandler )
public void DrawRegions( World world )
{
renderer.BeginFrame(scrollPosition);
wr.Draw();
world.WorldRenderer.Draw();
Widget.DoDraw( wr );
Widget.DoDraw(world);
var cursorName = Widget.RootWidget.GetCursorOuter(Viewport.LastMousePos) ?? "default";
var c = new Cursor(cursorName);
c.Draw(wr, (int)cursorFrame, Viewport.LastMousePos + Location);
c.Draw((int)cursorFrame, Viewport.LastMousePos + Location);
renderer.EndFrame( inputHandler );
renderer.EndFrame();
}
public void RefreshPalette()
{
Game.world.WorldRenderer.palette.Update(
Game.world.WorldActor.TraitsImplementing<IPaletteModifier>());
}
public void Tick()
{
cursorFrame += 0.5f;
RefreshPalette();
}
public float2 ViewToWorld(int2 loc)
@@ -124,9 +131,9 @@ namespace OpenRA.Graphics
return ViewToWorld(mi.Location);
}
public void Center(float2 loc)
public void Center(int2 loc)
{
scrollPosition = this.NormalizeScrollPosition((Game.CellSize*loc - screenSize / 2).ToInt2());
scrollPosition = this.NormalizeScrollPosition(Game.CellSize*loc - .5f * new float2(Width, Height));
}
public void Center(IEnumerable<Actor> actors)
@@ -137,16 +144,15 @@ namespace OpenRA.Graphics
.Select(a => a.CenterLocation)
.Aggregate((a, b) => a + b);
scrollPosition = this.NormalizeScrollPosition((avgPos.ToInt2() - screenSize / 2));
scrollPosition = this.NormalizeScrollPosition((avgPos - .5f * new float2(Width, Height)));
}
public Rectangle ShroudBounds( World world )
public Rectangle? ShroudBounds()
{
var localPlayer = world.LocalPlayer;
if( localPlayer == null ) return world.Map.Bounds;
if( localPlayer.Shroud.Disabled ) return world.Map.Bounds;
if( !localPlayer.Shroud.Bounds.HasValue ) return world.Map.Bounds;
return Rectangle.Intersect( localPlayer.Shroud.Bounds.Value, world.Map.Bounds );
var localPlayer = Game.world.LocalPlayer;
if (localPlayer == null) return null;
if (localPlayer.Shroud.Disabled) return null;
return localPlayer.Shroud.Bounds;
}
public Rectangle ViewBounds()

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Graphics
{
public class WorldRenderer
{
public readonly World world;
readonly World world;
internal readonly TerrainRenderer terrainRenderer;
public readonly UiOverlay uiOverlay;
internal readonly HardwarePalette palette;
@@ -31,9 +31,6 @@ namespace OpenRA.Graphics
terrainRenderer = new TerrainRenderer(world, this);
uiOverlay = new UiOverlay();
palette = new HardwarePalette(world.Map);
foreach( var pal in world.traitDict.ActorsWithTraitMultiple<IPalette>( world ) )
pal.Trait.InitPalette( this );
}
public int GetPaletteIndex(string name) { return palette.GetPaletteIndex(name); }
@@ -70,7 +67,8 @@ namespace OpenRA.Graphics
return new Rectangle(0, 0, Game.viewport.Width, Game.viewport.Height);
}
IEnumerable<Renderable> SpritesToRender()
Renderable[] worldSprites = { };
public void Tick()
{
var bounds = GetBoundsRect();
var comparer = new SpriteComparer();
@@ -86,35 +84,28 @@ namespace OpenRA.Graphics
var effects = world.Effects.SelectMany(e => e.Render());
return renderables.Concat(effects);
worldSprites = renderables.Concat(effects).ToArray();
}
public void Draw()
{
RefreshPalette();
var bounds = GetBoundsRect();
Game.Renderer.EnableScissor(bounds.Left, bounds.Top, bounds.Width, bounds.Height);
terrainRenderer.Draw(this, Game.viewport);
terrainRenderer.Draw(Game.viewport);
if (world.OrderGenerator != null)
world.OrderGenerator.RenderBeforeWorld(this, world);
foreach (var image in SpritesToRender() )
image.Sprite.DrawAt(image.Pos, this.GetPaletteIndex(image.Palette), image.Scale);
uiOverlay.Draw(this, world);
world.OrderGenerator.RenderBeforeWorld(world);
// added for contrails
foreach (var a in world.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPostRender>())
t.RenderAfterWorld(this, a);
foreach( var image in worldSprites )
image.Sprite.DrawAt( image.Pos, this.GetPaletteIndex( image.Palette ) );
uiOverlay.Draw(world);
if (world.OrderGenerator != null)
world.OrderGenerator.RenderAfterWorld(this, world);
world.OrderGenerator.RenderAfterWorld(world);
if (world.LocalPlayer != null)
world.LocalPlayer.Shroud.Draw( this );
world.LocalPlayer.Shroud.Draw();
Game.Renderer.DisableScissor();
}
@@ -194,10 +185,5 @@ namespace OpenRA.Graphics
prev = pos;
}
}
public void RefreshPalette()
{
palette.Update( world.WorldActor.TraitsImplementing<IPaletteModifier>() );
}
}
}

View File

@@ -1,52 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using OpenRA.Widgets;
namespace OpenRA
{
public class NullInputHandler : IInputHandler
{
// ignore all input
public void ModifierKeys( Modifiers mods ) { }
public void OnKeyInput( KeyInput input ) { }
public void OnMouseInput( MouseInput input ) { }
}
public class DefaultInputHandler : IInputHandler
{
readonly World world;
public DefaultInputHandler( World world )
{
this.world = world;
}
public void ModifierKeys( Modifiers mods )
{
Game.HandleModifierKeys( mods );
}
public void OnKeyInput( KeyInput input )
{
Sync.CheckSyncUnchanged( world, () =>
{
Widget.HandleKeyPress( input );
} );
}
public void OnMouseInput( MouseInput input )
{
Sync.CheckSyncUnchanged( world, () =>
{
Widget.HandleInput( input );
} );
}
}
}

View File

@@ -1,4 +1,4 @@
#region Copyright & License Information
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
@@ -9,33 +9,16 @@
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace OpenRA
{
public interface IInputHandler
{
void ModifierKeys( Modifiers mods );
void OnKeyInput( KeyInput input );
void OnMouseInput( MouseInput input );
}
public struct MouseInput
{
public MouseInputEvent Event;
public MouseButton Button;
public int2 Location;
public MouseButton Button;
public Modifiers Modifiers;
public MouseInput( MouseInputEvent ev, MouseButton button, int2 location, Modifiers mods )
{
this.Event = ev;
this.Button = button;
this.Location = location;
this.Modifiers = mods;
}
}
public enum MouseInputEvent { Down, Move, Up };

View File

@@ -19,14 +19,24 @@ using OpenRA.FileFormats;
namespace OpenRA
{
public class Map : MapStub
public class Map
{
public IFolder Package;
public string Uid;
// Yaml map data
[FieldLoader.Load] public bool Selectable = true;
[FieldLoader.Load] public int MapFormat;
[FieldLoader.Load] public string Title;
[FieldLoader.Load] public string Description;
[FieldLoader.Load] public string Author;
[FieldLoader.Load] public int PlayerCount;
[FieldLoader.Load] public string Tileset;
public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
public Dictionary<string, ActorReference> Actors = new Dictionary<string, ActorReference>();
public List<SmudgeReference> Smudges = new List<SmudgeReference>();
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
// Rules overrides
public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
@@ -35,6 +45,8 @@ namespace OpenRA
public byte TileFormat = 1;
[FieldLoader.Load] public int2 MapSize;
[FieldLoader.Load] public int2 TopLeft;
[FieldLoader.Load] public int2 BottomRight;
public TileReference<ushort, byte>[,] MapTiles;
public TileReference<byte, byte>[,] MapResources;
@@ -43,7 +55,10 @@ namespace OpenRA
// Temporary compat hacks
public int XOffset { get { return TopLeft.X; } }
public int YOffset { get { return TopLeft.Y; } }
public int Width { get { return BottomRight.X - TopLeft.X; } }
public int Height { get { return BottomRight.Y - TopLeft.Y; } }
public string Theater { get { return Tileset; } }
public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } }
public Rectangle Bounds { get { return Rectangle.FromLTRB(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); } }
public Map()
@@ -82,13 +97,19 @@ namespace OpenRA
}
public Map(IFolder package)
: base(package)
{
Package = package;
var yaml = new MiniYaml( null, MiniYaml.FromStream( Package.GetContent( "map.yaml" ) ) );
// 'Simple' metadata
FieldLoader.Load( this, yaml );
// Waypoints
foreach (var wp in yaml.NodesDict["Waypoints"].NodesDict)
{
string[] loc = wp.Value.Value.Split(',');
Waypoints.Add(wp.Key, new int2(int.Parse(loc[0]), int.Parse(loc[1])));
}
// Players & Actors -- this has changed several times.
// - Be backwards compatible wherever possible.
@@ -178,13 +199,12 @@ namespace OpenRA
Rules = yaml.NodesDict["Rules"].Nodes;
CustomTerrain = new string[MapSize.X, MapSize.Y];
LoadUid();
LoadBinaryData();
}
public void Save(string filepath)
{
// Todo: save to a zip file in the support dir by default
Package = new Folder(filepath, 0);
MapFormat = 3;
var root = new List<MiniYamlNode>();
@@ -294,6 +314,11 @@ namespace OpenRA
File.Move(filepath + ".tmp", filepath);
}
public void LoadUid()
{
Uid = Package.GetContent("map.uid").ReadAllText();
}
public void SaveUid(string filename)
{
// UID is calculated by taking an SHA1 of the yaml and binary data

View File

@@ -13,11 +13,41 @@ using System.IO;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Support;
namespace OpenRA
{
public class ModData
{
public static readonly Dictionary<string,Mod> AllMods = ValidateMods(Directory.GetDirectories("mods").Select(x => x.Substring(5)).ToArray());
public static Dictionary<string,Mod> ValidateMods(string[] mods)
{
var ret = new Dictionary<string,Mod>();
foreach (var m in mods)
{
if (!File.Exists("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"))
continue;
var yaml = new MiniYaml( null, MiniYaml.FromFile("mods" + Path.DirectorySeparatorChar + m + Path.DirectorySeparatorChar + "mod.yaml"));
if (!yaml.NodesDict.ContainsKey("Metadata"))
{
System.Console.WriteLine("Invalid mod: "+m);
continue;
}
ret.Add(m,FieldLoader.Load<Mod>(yaml.NodesDict["Metadata"]));
}
return ret;
}
public class Mod
{
public string Title;
public string Description;
public string Version;
}
public readonly Manifest Manifest;
public readonly ObjectCreator ObjectCreator;
public readonly SheetBuilder SheetBuilder;
@@ -49,7 +79,7 @@ namespace OpenRA
.Where(p => Directory.Exists(p))
.SelectMany(p => Directory.GetDirectories(p)).ToList();
return paths.Select(p => new MapStub(new Folder(p, 0))).ToDictionary(m => m.Uid);
return paths.Select(p => new MapStub(new Folder(p))).ToDictionary(m => m.Uid);
}
string cachedTheatre = null;

View File

@@ -18,7 +18,7 @@ using OpenRA.Support;
namespace OpenRA.Network
{
public enum ConnectionState
enum ConnectionState
{
PreConnecting,
NotConnected,
@@ -26,13 +26,11 @@ namespace OpenRA.Network
Connected,
}
public interface IConnection : IDisposable
interface IConnection
{
int LocalClientId { get; }
ConnectionState ConnectionState { get; }
void Send( int frame, List<byte[]> orders );
void SendImmediate( List<byte[]> orders );
void SendSync( int frame, byte[] syncData );
void Send( byte[] packet );
void Receive( Action<int, byte[]> packetFn );
}
@@ -55,33 +53,7 @@ namespace OpenRA.Network
get { return ConnectionState.PreConnecting; }
}
public virtual void Send( int frame, List<byte[]> orders )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
foreach( var o in orders )
ms.Write( o );
Send( ms.ToArray() );
}
public virtual void SendImmediate( List<byte[]> orders )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( (int)0 ) );
foreach( var o in orders )
ms.Write( o );
Send( ms.ToArray() );
}
public virtual void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
ms.Write( syncData );
Send( ms.ToArray() );
}
protected virtual void Send( byte[] packet )
public virtual void Send( byte[] packet )
{
if( packet.Length == 0 )
throw new NotImplementedException();
@@ -101,11 +73,9 @@ namespace OpenRA.Network
foreach( var p in packets )
packetFn( p.FromClient, p.Data );
}
public virtual void Dispose() { }
}
class NetworkConnection : EchoConnection
class NetworkConnection : EchoConnection, IDisposable
{
TcpClient socket;
int clientId;
@@ -142,13 +112,12 @@ namespace OpenRA.Network
receivedPackets.Add( new ReceivedPacket { FromClient = client, Data = buf } );
}
}
catch { }
finally
catch( SocketException )
{
connectionState = ConnectionState.NotConnected;
if( socket != null )
socket.Close();
}
catch ( IOException ) { socket.Close(); }
catch (ThreadAbortException ) { socket.Close(); }
}
) { IsBackground = true };
t.Start();
@@ -157,42 +126,26 @@ namespace OpenRA.Network
public override int LocalClientId { get { return clientId; } }
public override ConnectionState ConnectionState { get { return connectionState; } }
List<byte[]> queuedSyncPackets = new List<byte[]>();
public override void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
ms.Write( syncData );
queuedSyncPackets.Add( ms.ToArray() );
}
protected override void Send( byte[] packet )
public override void Send( byte[] packet )
{
base.Send( packet );
try
{
var ms = new MemoryStream();
ms.Write(BitConverter.GetBytes((int)packet.Length));
ms.Write(packet);
foreach( var q in queuedSyncPackets )
{
ms.Write( BitConverter.GetBytes( (int)q.Length ) );
ms.Write( q );
base.Send( q );
}
queuedSyncPackets.Clear();
ms.WriteTo(socket.GetStream());
}
catch (SocketException) { /* drop this on the floor; we'll pick up the disconnect from the reader thread */ }
catch (ObjectDisposedException) { /* ditto */ }
catch (InvalidOperationException) { /* ditto */ }
}
bool disposed = false;
public override void Dispose ()
public void Dispose ()
{
if (disposed) return;
disposed = true;
@@ -207,4 +160,48 @@ namespace OpenRA.Network
~NetworkConnection() { Dispose(); }
}
class ReplayConnection : IConnection
{
//uint nextFrame = 1;
FileStream replayStream;
public ReplayConnection( string replayFilename )
{
replayStream = File.OpenRead( replayFilename );
}
public int LocalClientId
{
get { return 0; }
}
public ConnectionState ConnectionState
{
get { return ConnectionState.Connected; }
}
public void Send( byte[] packet )
{
// do nothing; ignore locally generated orders
}
public void Receive( Action<int, byte[]> packetFn )
{
if( replayStream == null ) return;
var reader = new BinaryReader( replayStream );
while( replayStream.Position < replayStream.Length )
{
var client = reader.ReadInt32();
var packetLen = reader.ReadInt32();
var packet = reader.ReadBytes( packetLen );
packetFn( client, packet );
if( !Game.orderManager.GameStarted )
return;
}
replayStream = null;
}
}
}

View File

@@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenRA.Network
{
class FrameData
{
public struct ClientOrder
{
public int Client;
public Order Order;
}
readonly Dictionary<int, int> clientQuitTimes = new Dictionary<int, int>();
readonly Dictionary<int, Dictionary<int, byte[]>> framePackets = new Dictionary<int, Dictionary<int, byte[]>>();
public IEnumerable<int> ClientsPlayingInFrame( int frame )
{
return clientQuitTimes
.Where( x => frame <= x.Value )
.Select( x => x.Key )
.OrderBy( x => x );
}
public void ClientQuit( int clientId, int lastClientFrame )
{
clientQuitTimes[clientId] = lastClientFrame;
}
public void AddFrameOrders( int clientId, int frame, byte[] orders )
{
var frameData = framePackets.GetOrAdd( frame );
frameData.Add( clientId, orders );
}
public bool IsReadyForFrame( int frame )
{
var frameData = framePackets.GetOrAdd( frame );
return ClientsPlayingInFrame( frame )
.All( client => frameData.ContainsKey( client ) );
}
public IEnumerable<ClientOrder> OrdersForFrame( World world, int frame )
{
var frameData = framePackets[ frame ];
var clientData = ClientsPlayingInFrame( frame )
.ToDictionary( k => k, v => frameData[ v ] );
return clientData
.SelectMany( x => x.Value
.ToOrderList( world )
.Select( o => new ClientOrder { Client = x.Key, Order = o } ) );
}
}
}

View File

@@ -132,7 +132,7 @@ namespace OpenRA
{
return "OrderString: \"{0}\" \n\t Subject: \"{1}\". \n\t TargetActor: \"{2}\" \n\t TargetLocation: {3}." +
"\n\t TargetString: \"{4}\".\n\t IsImmediate: {5}.\n\t Player(PlayerName): {6}\n".F(
OrderString, Subject, TargetActor != null ? TargetActor.Info.Name : null , TargetLocation, TargetString, IsImmediate, Player != null ? Player.PlayerName : null);
OrderString, Subject, TargetActor.Info.Name , TargetLocation, TargetString, IsImmediate, Player.PlayerName);
}
static uint UIntFromActor(Actor a)

View File

@@ -22,6 +22,22 @@ namespace OpenRA.Network
s.Write(buf, 0, buf.Length);
}
public static void WriteFrameData(this Stream s, IEnumerable<Order> orders, int frameNumber)
{
var bytes = Serialize( orders, frameNumber );
s.Write( BitConverter.GetBytes( (int)bytes.Length ) );
s.Write( bytes );
}
public static byte[] Serialize( this IEnumerable<Order> orders, int frameNumber )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frameNumber ) );
foreach( var o in orders.Select( o => o.Serialize() ) )
ms.Write( o );
return ms.ToArray();
}
public static List<Order> ToOrderList(this byte[] bytes, World world)
{
var ms = new MemoryStream(bytes, 4, bytes.Length - 4);
@@ -36,11 +52,12 @@ namespace OpenRA.Network
return ret;
}
public static byte[] SerializeSync( this List<int> sync )
public static byte[] SerializeSync( this List<int> sync, int frameNumber )
{
var ms = new MemoryStream();
using( var writer = new BinaryWriter( ms ) )
{
writer.Write( frameNumber );
writer.Write( (byte)0x65 );
foreach( var s in sync )
writer.Write( s );

View File

@@ -16,46 +16,47 @@ using OpenRA.FileFormats;
namespace OpenRA.Network
{
public class OrderManager : IDisposable
class OrderManager : IDisposable
{
readonly SyncReport syncReport;
readonly FrameData frameData = new FrameData();
SyncReport syncReport = new SyncReport();
public Session LobbyInfo = new Session( Game.Settings.Game.Mods );
public Session.Client LocalClient { get { return LobbyInfo.ClientWithIndex( Connection.LocalClientId ); } }
public World world;
public int FrameNumber { get; private set; }
public readonly string Host;
public readonly int Port;
public int NetFrameNumber { get; private set; }
public int LocalFrameNumber;
public int FramesAhead = 0;
public int LastTickTime = Environment.TickCount;
public bool GameStarted { get { return NetFrameNumber != 0; } }
public bool GameStarted { get { return FrameNumber != 0; } }
public IConnection Connection { get; private set; }
public readonly int SyncHeaderSize = 9;
Dictionary<int, int> clientQuitTimes = new Dictionary<int, int>();
Dictionary<int, Dictionary<int, byte[]>> frameClientData =
new Dictionary<int, Dictionary<int, byte[]>>();
List<Order> localOrders = new List<Order>();
FileStream replaySaveFile;
public void StartGame()
{
if (GameStarted) return;
NetFrameNumber = 1;
for( int i = NetFrameNumber ; i <= FramesAhead ; i++ )
Connection.Send( i, new List<byte[]>() );
FrameNumber = 1;
for( int i = FrameNumber ; i <= FramesAhead ; i++ )
Connection.Send( new List<Order>().Serialize( i ) );
}
public OrderManager( string host, int port, IConnection conn )
public OrderManager( IConnection conn )
{
this.Host = host;
this.Port = port;
Connection = conn;
syncReport = new SyncReport( this );
}
public OrderManager( IConnection conn, string replayFilename )
: this( conn )
{
string path = Game.SupportDir + "Replays" + Path.DirectorySeparatorChar;
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
replaySaveFile = File.Create( path + replayFilename );
}
public void IssueOrders( Order[] orders )
@@ -69,11 +70,11 @@ namespace OpenRA.Network
localOrders.Add( order );
}
public void TickImmediate()
public void TickImmediate( World world )
{
var immediateOrders = localOrders.Where( o => o.IsImmediate ).ToList();
if( immediateOrders.Count != 0 )
Connection.SendImmediate( immediateOrders.Select( o => o.Serialize() ).ToList() );
Connection.Send( immediateOrders.Serialize( 0 ) );
localOrders.RemoveAll( o => o.IsImmediate );
var immediatePackets = new List<Pair<int, byte[]>>();
@@ -83,23 +84,26 @@ namespace OpenRA.Network
{
var frame = BitConverter.ToInt32( packet, 0 );
if( packet.Length == 5 && packet[ 4 ] == 0xBF )
frameData.ClientQuit( clientId, frame );
clientQuitTimes[ clientId ] = frame;
else if( packet.Length >= 5 && packet[ 4 ] == 0x65 )
CheckSync( packet );
else if( frame == 0 )
immediatePackets.Add( Pair.New( clientId, packet ) );
else
frameData.AddFrameOrders( clientId, frame, packet );
frameClientData.GetOrAdd( frame ).Add( clientId, packet );
} );
foreach( var p in immediatePackets )
{
foreach( var o in p.Second.ToOrderList( world ) )
UnitOrders.ProcessOrder( this, world, p.First, o );
UnitOrders.ProcessOrder( world, p.First, o );
WriteImmediateToReplay( immediatePackets );
}
}
Dictionary<int, byte[]> syncForFrame = new Dictionary<int, byte[]>();
void CheckSync( byte[] packet )
void CheckSync(byte[] packet)
{
var frame = BitConverter.ToInt32(packet, 0);
byte[] existingSync;
@@ -130,9 +134,14 @@ namespace OpenRA.Network
syncForFrame.Add(frame, packet);
}
void OutOfSync(int frame, int index)
{
var order = frameData.OrdersForFrame( world, frame ).ElementAt(index);
void OutOfSync( int frame , int index)
{
var frameData = clientQuitTimes
.Where( x => frame <= x.Value )
.OrderBy( x => x.Key )
.ToDictionary( k => k.Key, v => frameClientData[ FrameNumber ][ v.Key ] );
var order = frameData.SelectMany( o => o.Value.ToOrderList( Game.world ).Select( a => new { Client = o.Key, Order = a } ) ).ElementAt(index);
throw new InvalidOperationException("Out of sync in frame {0}.\n {1}".F(frame, order.Order.ToString()));
}
@@ -148,32 +157,72 @@ namespace OpenRA.Network
public bool IsReadyForNextFrame
{
get { return NetFrameNumber >= 1 && frameData.IsReadyForFrame( NetFrameNumber ); }
get
{
return FrameNumber > 0 &&
clientQuitTimes
.Where( x => FrameNumber <= x.Value )
.All( x => frameClientData.GetOrAdd( FrameNumber ).ContainsKey( x.Key ) );
}
}
public void Tick()
public void Tick( World world )
{
if( !IsReadyForNextFrame )
throw new InvalidOperationException();
Connection.Send( NetFrameNumber + FramesAhead, localOrders.Select( o => o.Serialize() ).ToList() );
Connection.Send( localOrders.Serialize( FrameNumber + FramesAhead ) );
localOrders.Clear();
var frameData = clientQuitTimes
.Where( x => FrameNumber <= x.Value )
.OrderBy( x => x.Key )
.ToDictionary( k => k.Key, v => frameClientData[ FrameNumber ][ v.Key ] );
var sync = new List<int>();
sync.Add( world.SyncHash() );
foreach( var order in frameData.OrdersForFrame( world, NetFrameNumber) )
foreach( var order in frameData.SelectMany( o => o.Value.ToOrderList( world ).Select( a => new { Client = o.Key, Order = a } ) ) )
{
UnitOrders.ProcessOrder( this, world, order.Client, order.Order );
UnitOrders.ProcessOrder( world, order.Client, order.Order );
sync.Add( world.SyncHash() );
}
var ss = sync.SerializeSync();
Connection.SendSync( NetFrameNumber, ss );
var ss = sync.SerializeSync( FrameNumber );
Connection.Send( ss );
WriteToReplay( frameData, ss );
syncReport.UpdateSyncReport();
++NetFrameNumber;
CheckSync( ss );
++FrameNumber;
}
void WriteToReplay( Dictionary<int, byte[]> frameData, byte[] syncData )
{
if( replaySaveFile == null ) return;
foreach( var f in frameData )
{
replaySaveFile.Write( BitConverter.GetBytes( f.Key ) );
replaySaveFile.Write( BitConverter.GetBytes( f.Value.Length ) );
replaySaveFile.Write( f.Value );
}
replaySaveFile.Write( BitConverter.GetBytes( (int)0 ) );
replaySaveFile.Write( BitConverter.GetBytes( (int)syncData.Length ) );
replaySaveFile.Write( syncData );
}
void WriteImmediateToReplay( List<Pair<int, byte[]>> immediatePackets )
{
if( replaySaveFile == null ) return;
foreach( var i in immediatePackets )
{
replaySaveFile.Write( BitConverter.GetBytes( i.First ) );
replaySaveFile.Write( BitConverter.GetBytes( i.Second.Length ) );
replaySaveFile.Write( i.Second );
}
}
bool disposed;
@@ -181,7 +230,11 @@ namespace OpenRA.Network
{
if (disposed) return;
Connection.Dispose();
if (replaySaveFile != null)
replaySaveFile.Dispose();
var disposableConnection = Connection as IDisposable;
if (disposableConnection != null) disposableConnection.Dispose();
disposed = true;
GC.SuppressFinalize(this);

View File

@@ -1,110 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace OpenRA.Network
{
class ReplayConnection : IConnection
{
//uint nextFrame = 1;
FileStream replayStream;
public ReplayConnection( string replayFilename )
{
replayStream = File.OpenRead( replayFilename );
}
public int LocalClientId
{
get { return 0; }
}
public ConnectionState ConnectionState
{
get { return ConnectionState.Connected; }
}
// do nothing; ignore locally generated orders
public void Send( int frame, List<byte[]> orders ) { }
public void SendImmediate( List<byte[]> orders ) { }
public void SendSync( int frame, byte[] syncData )
{
var ms = new MemoryStream();
ms.Write( BitConverter.GetBytes( frame ) );
ms.Write( syncData );
sync.Add( ms.ToArray() );
}
List<byte[]> sync = new List<byte[]>();
public void Receive( Action<int, byte[]> packetFn )
{
while( sync.Count != 0 )
{
packetFn( LocalClientId, sync[ 0 ] );
sync.RemoveAt( 0 );
}
if( replayStream == null ) return;
var reader = new BinaryReader( replayStream );
while( replayStream.Position < replayStream.Length )
{
var client = reader.ReadInt32();
var packetLen = reader.ReadInt32();
var packet = reader.ReadBytes( packetLen );
packetFn( client, packet );
}
replayStream = null;
}
public void Dispose() { }
}
class ReplayRecorderConnection : IConnection
{
IConnection inner;
BinaryWriter writer;
public ReplayRecorderConnection( IConnection inner, FileStream replayFile )
{
this.inner = inner;
this.writer = new BinaryWriter( replayFile );
}
public int LocalClientId { get { return inner.LocalClientId; } }
public ConnectionState ConnectionState { get { return inner.ConnectionState; } }
public void Send( int frame, List<byte[]> orders ) { inner.Send( frame, orders ); }
public void SendImmediate( List<byte[]> orders ) { inner.SendImmediate( orders ); }
public void SendSync( int frame, byte[] syncData ) { inner.SendSync( frame, syncData ); }
public void Receive( Action<int, byte[]> packetFn )
{
inner.Receive( ( client, data ) =>
{
writer.Write( client );
writer.Write( data.Length );
writer.Write( data );
packetFn( client, data );
} );
}
bool disposed;
public void Dispose()
{
if( disposed )
return;
writer.Close();
disposed = true;
}
~ReplayRecorderConnection()
{
Dispose();
}
}
}

View File

@@ -10,7 +10,6 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
namespace OpenRA.Network
@@ -21,21 +20,10 @@ namespace OpenRA.Network
public List<Slot> Slots = new List<Slot>();
public Global GlobalSettings = new Global();
public Client ClientWithIndex(int clientID)
{
return Clients.SingleOrDefault(c => c.Index == clientID);
}
public Client ClientInSlot(Slot slot)
{
return Clients.SingleOrDefault(c => c.Slot == slot.Index);
}
public enum ClientState
{
NotReady,
Ready,
Disconnected = 1000
Ready
}
public class Client
@@ -56,14 +44,13 @@ namespace OpenRA.Network
public int Index;
public string Bot; // trait name of the bot to initialize in this slot, or null otherwise.
public bool Closed; // host has explicitly closed this slot.
public string MapPlayer; // playerReference to bind against.
public bool Spectator = false; // Spectating or not
public string MapPlayer; // playerReference to bind against.
// todo: more stuff?
}
public class Global
{
public string ServerName;
public string Map;
public string[] Mods = { "ra" }; // mod names
public int OrderLatency = 3;
@@ -72,36 +59,32 @@ namespace OpenRA.Network
public bool AllowCheats = false;
}
public Session(string[] mods)
{
this.GlobalSettings.Mods = mods.ToArray();
}
public string Serialize()
{
var clientData = new List<MiniYamlNode>();
foreach (var client in Clients)
clientData.Add(new MiniYamlNode("Client@{0}".F(client.Index), FieldSaver.Save(client)));
foreach( var client in Clients )
clientData.Add( new MiniYamlNode( "Client@{0}".F( client.Index ), FieldSaver.Save( client ) ) );
foreach (var slot in Slots)
clientData.Add(new MiniYamlNode("Slot@{0}".F(slot.Index), FieldSaver.Save(slot)));
foreach( var slot in Slots )
clientData.Add( new MiniYamlNode( "Slot@{0}".F( slot.Index ), FieldSaver.Save( slot ) ) );
clientData.Add(new MiniYamlNode("GlobalSettings", FieldSaver.Save(GlobalSettings)));
clientData.Add( new MiniYamlNode( "GlobalSettings", FieldSaver.Save( GlobalSettings ) ) );
return clientData.WriteToString();
}
public static Session Deserialize(string data)
{
var session = new Session(Game.Settings.Game.Mods);
var session = new Session();
session.GlobalSettings.Mods = Game.Settings.Game.Mods;
var ys = MiniYaml.FromString(data);
foreach (var y in ys)
{
var yy = y.Key.Split('@');
switch (yy[0])
switch( yy[0] )
{
case "GlobalSettings":
FieldLoader.Load(session.GlobalSettings, y.Value);
@@ -112,7 +95,7 @@ namespace OpenRA.Network
break;
case "Slot":
session.Slots.Add(FieldLoader.Load<Session.Slot>(y.Value));
session.Slots.Add(FieldLoader.Load<Session.Slot>(y.Value ));
break;
}
}

View File

@@ -4,20 +4,17 @@ using System.Linq;
using System.Text;
using OpenRA.FileFormats;
using OpenRA.Support;
using OpenRA.Traits;
namespace OpenRA.Network
{
class SyncReport
{
readonly OrderManager orderManager;
const int numSyncReports = 5;
Report[] syncReports = new Report[numSyncReports];
int curIndex = 0;
public SyncReport( OrderManager orderManager )
public SyncReport()
{
this.orderManager = orderManager;
for (var i = 0; i < numSyncReports; i++)
syncReports[i] = new SyncReport.Report();
}
@@ -33,12 +30,11 @@ namespace OpenRA.Network
void GenerateSyncReport(Report report)
{
report.Frame = orderManager.NetFrameNumber;
report.SyncedRandom = orderManager.world.SharedRandom.Last;
report.Frame = Game.orderManager.FrameNumber;
report.SyncedRandom = Game.world.SharedRandom.Last;
report.Traits.Clear();
foreach (var a in orderManager.world.Queries.WithTraitMultiple<object>())
foreach (var a in Game.world.Queries.WithTraitMultiple<object>())
{
if (a.Trait is ITraitNotSynced ) continue;
var sync = Sync.CalculateSyncHash(a.Trait);
if (sync != 0)
report.Traits.Add(new TraitReport()

View File

@@ -16,150 +16,92 @@ namespace OpenRA.Network
{
static class UnitOrders
{
static Player FindPlayerByClient(this World world, Session.Client c)
static Session.Client FindClientById(int id)
{
/* todo: this is still a hack.
* the cases we're trying to avoid are the extra players on the host's client -- Neutral, other MapPlayers,
* bots,.. */
return world.players.Values.FirstOrDefault(
p => p.ClientIndex == c.Index && p.PlayerName == c.Name);
return Game.LobbyInfo.Clients.FirstOrDefault(c => c.Index == id);
}
public static void ProcessOrder(OrderManager orderManager, World world, int clientId, Order order)
static Player FindPlayerByClientId( this World world, int id)
{
if (world != null)
/* todo: find the interactive player. */
return world.players.Values.FirstOrDefault(p => p.ClientIndex == id);
}
public static void ProcessOrder( World world, int clientId, Order order )
{
// Drop exploiting orders
if (order.Subject != null && order.Subject.Owner.ClientIndex != clientId)
{
if (!world.WorldActor.TraitsImplementing<IValidateOrder>().All(vo =>
vo.OrderValidation(orderManager, world, clientId, order)))
return;
Game.Debug("Detected exploit order from {0}: {1}".F(clientId, order.OrderString));
return;
}
switch (order.OrderString)
switch( order.OrderString )
{
case "Chat":
case "Chat":
{
var client = FindClientById(clientId);
if (client != null)
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (Game.IsHost && Game.Settings.Server.Extension != null && !Game.Settings.Server.Extension.OnIngameChat(client, order.TargetString, false))
break;
if (client != null)
var player = world.FindPlayerByClientId(clientId);
if (player != null && player.WinState == WinState.Lost)
Game.AddChatLine(client.Color1, client.Name + " (Dead)", order.TargetString);
else
Game.AddChatLine(client.Color1, client.Name, order.TargetString);
}
break;
}
case "TeamChat":
{
var client = FindClientById(clientId);
if (client != null)
{
var player = world.FindPlayerByClientId(clientId);
var display = (world.GameHasStarted) ?
player != null && (world.LocalPlayer != null && player.Stances[world.LocalPlayer] == Stance.Ally
|| player.WinState == WinState.Lost) :
client == Game.LocalClient || (client.Team == Game.LocalClient.Team && client.Team != 0);
if (display)
{
var player = world != null ? world.FindPlayerByClient(client) : null;
var suffix = (player != null && player.WinState == WinState.Lost) ? " (Dead)" : "";
var suffix = (player != null && player.WinState == WinState.Lost) ? " (Dead)" : " (Team)";
Game.AddChatLine(client.Color1, client.Name + suffix, order.TargetString);
}
else
Game.AddChatLine(Color.White, "(player {0})".F(clientId), order.TargetString);
break;
}
case "Disconnected": /* reports that the target player disconnected */
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (client != null)
{
client.State = Session.ClientState.Disconnected;
}
break;
}
case "TeamChat":
{
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
if (Game.IsHost && Game.Settings.Server.Extension != null && !Game.Settings.Server.Extension.OnIngameChat(client, order.TargetString, true))
break;
if (client != null)
{
if (world == null)
{
if (client.Team == orderManager.LocalClient.Team)
Game.AddChatLine(client.Color1, client.Name + " (Team)",
order.TargetString);
}
else
{
var player = world.FindPlayerByClient(client);
var display = player != null
&&
(world.LocalPlayer != null &&
player.Stances[world.LocalPlayer] == Stance.Ally
|| player.WinState == WinState.Lost);
if (display)
{
var suffix = (player != null && player.WinState == WinState.Lost)
? " (Dead)"
: " (Team)";
Game.AddChatLine(client.Color1, client.Name + suffix, order.TargetString);
}
}
}
break;
}
case "StartGame":
{
Game.AddChatLine(Color.White, "Server", "The game has started.");
Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map);
break;
}
case "SyncInfo":
{
orderManager.LobbyInfo = Session.Deserialize(order.TargetString);
if (orderManager.FramesAhead != orderManager.LobbyInfo.GlobalSettings.OrderLatency
&& !orderManager.GameStarted)
{
orderManager.FramesAhead = orderManager.LobbyInfo.GlobalSettings.OrderLatency;
Game.Debug(
"Order lag is now {0} frames.".F(orderManager.LobbyInfo.GlobalSettings.OrderLatency));
}
Game.SyncLobbyInfo();
break;
}
case "SetStance":
{
var targetPlayer = order.Player.World.players[order.TargetLocation.X];
var newStance = (Stance)order.TargetLocation.Y;
if (Game.IsHost && Game.Settings.Server.Extension != null)
Game.Settings.Server.Extension.OnIngameSetStance(order.Player, targetPlayer, newStance);
SetPlayerStance(world, order.Player, targetPlayer, newStance);
// automatically declare war reciprocally
if (newStance == Stance.Enemy)
SetPlayerStance(world, targetPlayer, order.Player, newStance);
Game.Debug("{0} has set diplomatic stance vs {1} to {2}".F(
order.Player.PlayerName, targetPlayer.PlayerName, newStance));
break;
}
default:
{
if( !order.IsImmediate )
{
var self = order.Subject;
var health = self.TraitOrDefault<Health>();
if( health == null || !health.IsDead )
foreach( var t in self.TraitsImplementing<IResolveOrder>() )
t.ResolveOrder( self, order );
}
break;
}
break;
}
case "StartGame":
{
Game.AddChatLine(Color.White, "Server", "The game has started.");
Game.StartGame(Game.LobbyInfo.GlobalSettings.Map);
break;
}
case "SyncInfo":
{
Game.SyncLobbyInfo( world, order.TargetString);
break;
}
case "SetStance":
{
var targetPlayer = order.Player.World.players[order.TargetLocation.X];
var oldStance = order.Player.Stances[targetPlayer];
order.Player.Stances[targetPlayer] = (Stance)order.TargetLocation.Y;
if (targetPlayer == world.LocalPlayer)
world.WorldActor.Trait<Shroud>().UpdatePlayerStance(world, order.Player, oldStance, order.Player.Stances[targetPlayer]);
Game.Debug("{0} has set diplomatic stance vs {1} to {2}".F(
order.Player.PlayerName, targetPlayer.PlayerName, order.Player.Stances[targetPlayer]));
break;
}
default:
{
if( !order.IsImmediate )
foreach (var t in order.Subject.TraitsImplementing<IResolveOrder>())
t.ResolveOrder(order.Subject, order);
break;
}
}
}
static void SetPlayerStance(World w, Player a, Player b, Stance s)
{
var oldStance = a.Stances[b];
a.Stances[b] = s;
if (b == w.LocalPlayer)
w.WorldActor.Trait<Shroud>().UpdatePlayerStance(w, b, oldStance, s);
}
}
}

View File

@@ -1,19 +1,9 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using OpenRA.FileFormats;
using System.Collections.Generic;
namespace OpenRA
{
@@ -29,7 +19,7 @@ namespace OpenRA
.ToList();
// Namespaces from each mod assembly
foreach (var a in manifest.Assemblies.Concat(manifest.LocalAssemblies))
foreach (var a in manifest.Assemblies)
{
var asm = Assembly.LoadFile(Path.GetFullPath(a));
asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
@@ -52,7 +42,7 @@ namespace OpenRA
{
var type = mod.First.GetType( mod.Second + "." + className, false );
if( type == null ) continue;
var ctors = type.GetConstructors( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance ).Where( x => x.HasAttribute<UseCtorAttribute>() ).ToList();
var ctors = type.GetConstructors().Where( x => x.HasAttribute<UseCtorAttribute>() ).ToList();
if( ctors.Count == 0 )
return (T)CreateBasic( type );
else if( ctors.Count == 1 )
@@ -77,7 +67,7 @@ namespace OpenRA
{
var attrs = p[ i ].GetCustomAttributes<ParamAttribute>();
if( attrs.Length != 1 ) throw new InvalidOperationException( "ObjectCreator: argument in [UseCtor] doesn't have [Param]" );
a[ i ] = args[ attrs[ 0 ].ParamName ?? p[i].Name ];
a[ i ] = args[ attrs[ 0 ].ParamName ];
}
return ctor.Invoke( a );
}
@@ -87,8 +77,6 @@ namespace OpenRA
{
public string ParamName { get; private set; }
public ParamAttribute() { }
public ParamAttribute( string paramName )
{
ParamName = paramName;

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</ProjectGuid>
<OutputType>WinExe</OutputType>
@@ -79,6 +79,7 @@
<Compile Include="Group.cs" />
<Compile Include="Orders\GenericSelectTarget.cs" />
<Compile Include="Server\ProtocolVersion.cs" />
<Compile Include="Traits\BaseBuilding.cs" />
<Compile Include="Traits\LintAttributes.cs" />
<Compile Include="Traits\Player\PlayerResources.cs" />
<Compile Include="Traits\World\Shroud.cs" />
@@ -105,6 +106,7 @@
<Compile Include="Network\Connection.cs" />
<Compile Include="Network\OrderIO.cs" />
<Compile Include="Network\OrderManager.cs" />
<Compile Include="PathSearch.cs" />
<Compile Include="Selection.cs" />
<Compile Include="Server\Connection.cs" />
<Compile Include="Server\Exts.cs" />
@@ -115,10 +117,12 @@
<Compile Include="Sound.cs" />
<Compile Include="Support\PerfHistory.cs" />
<Compile Include="Sync.cs" />
<Compile Include="Traits\CustomSellValue.cs" />
<Compile Include="Traits\World\SpatialBins.cs" />
<Compile Include="Traits\World\Country.cs" />
<Compile Include="Actor.cs" />
<Compile Include="Cursor.cs" />
<Compile Include="GameRules\Footprint.cs" />
<Compile Include="GameRules\Rules.cs" />
<Compile Include="Graphics\Animation.cs" />
<Compile Include="Game.cs" />
@@ -127,14 +131,19 @@
<Compile Include="Graphics\LineRenderer.cs" />
<Compile Include="Graphics\WorldRenderer.cs" />
<Compile Include="Traits\Activities\Idle.cs" />
<Compile Include="Traits\Activities\RemoveSelf.cs" />
<Compile Include="Traits\Activities\Sell.cs" />
<Compile Include="Orders\IOrderGenerator.cs" />
<Compile Include="Player.cs" />
<Compile Include="Graphics\Sheet.cs" />
<Compile Include="PathFinder.cs" />
<Compile Include="Graphics\Sequence.cs" />
<Compile Include="Network\Order.cs" />
<Compile Include="Graphics\SequenceProvider.cs" />
<Compile Include="Graphics\SheetBuilder.cs" />
<Compile Include="Graphics\HardwarePalette.cs" />
<Compile Include="MainWindow.cs">
</Compile>
<Compile Include="Support\Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Graphics\Renderer.cs" />
@@ -142,10 +151,15 @@
<Compile Include="Graphics\SpriteRenderer.cs" />
<Compile Include="Graphics\SpriteSheetBuilder.cs" />
<Compile Include="Graphics\TerrainRenderer.cs" />
<Compile Include="Traits\Activities\Move.cs" />
<Compile Include="Traits\Activities\Turn.cs" />
<Compile Include="Traits\Building.cs" />
<Compile Include="Traits\World\BuildingInfluence.cs" />
<Compile Include="Traits\World\PlayerColorPalette.cs" />
<Compile Include="Traits\World\ResourceLayer.cs" />
<Compile Include="Traits\World\ResourceType.cs" />
<Compile Include="Traits\Selectable.cs" />
<Compile Include="Traits\Mobile.cs" />
<Compile Include="Traits\Render\RenderSimple.cs" />
<Compile Include="Traits\TraitsInterfaces.cs" />
<Compile Include="Traits\World\UnitInfluence.cs" />
@@ -155,10 +169,12 @@
<Compile Include="Graphics\Util.cs" />
<Compile Include="Graphics\Viewport.cs" />
<Compile Include="Orders\UnitOrderGenerator.cs" />
<Compile Include="Widgets\WorldTooltipWidget.cs" />
<Compile Include="World.cs" />
<Compile Include="WorldUtils.cs" />
<Compile Include="Traits\Player\EvaAlerts.cs" />
<Compile Include="Traits\World\ScreenShaker.cs" />
<Compile Include="Traits\LineBuild.cs" />
<Compile Include="Widgets\WidgetLoader.cs" />
<Compile Include="Widgets\ButtonWidget.cs" />
<Compile Include="Widgets\Widget.cs" />
@@ -184,7 +200,9 @@
<Compile Include="Widgets\ViewportScrollControllerWidget.cs" />
<Compile Include="Traits\Player\DeveloperMode.cs" />
<Compile Include="Traits\RevealsShroud.cs" />
<Compile Include="Traits\Targetable.cs" />
<Compile Include="Traits\Health.cs" />
<Compile Include="Traits\Activities\Drag.cs" />
<Compile Include="Widgets\VqaPlayerWidget.cs" />
<Compile Include="Widgets\Delegates\VideoPlayerDelegate.cs" />
<Compile Include="GameRules\Settings.cs" />
@@ -192,6 +210,8 @@
<Compile Include="Traits\ActorStance.cs" />
<Compile Include="Traits\Armor.cs" />
<Compile Include="Graphics\CursorProvider.cs" />
<Compile Include="Traits\Player\TechTree.cs" />
<Compile Include="Traits\Player\PowerManager.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
@@ -200,24 +220,15 @@
</ProjectReference>
<Compile Include="ActorInitializer.cs" />
<Compile Include="ActorReference.cs" />
<Compile Include="InputHandler.cs" />
<Compile Include="ModData.cs" />
<Compile Include="Map.cs" />
<Compile Include="Network\FrameData.cs" />
<Compile Include="Network\ReplayConnection.cs" />
<Compile Include="Network\Session.cs" />
<Compile Include="ObjectCreator.cs" />
<Compile Include="Network\SyncReport.cs" />
<Compile Include="Server\IServerExtension.cs" />
<Compile Include="Server\NullServerExtension.cs" />
<Compile Include="Traits\BaseBuilding.cs" />
<Compile Include="Traits\EditorAppearance.cs" />
<Compile Include="Traits\ValidateOrder.cs" />
<Compile Include="Traits\Scale.cs" />
<Compile Include="TraitDictionary.cs" />
<Compile Include="Traits\Activities\CancelableActivity.cs" />
<Compile Include="Traits\SharesCell.cs" />
<Compile Include="Widgets\PasswordFieldWidget.cs" />
<Compile Include="Traits\Valued.cs" />
<Compile Include="Traits\World\BibLayer.cs" />
<Compile Include="Widgets\Delegates\DeveloperModeDelegate.cs" />
<Compile Include="Widgets\ScrollingTextWidget.cs" />
</ItemGroup>

View File

@@ -10,27 +10,18 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
namespace OpenRA.Orders
{
public class GenericSelectTarget : IOrderGenerator
{
readonly IEnumerable<Actor> subjects;
readonly Actor subject;
readonly string order;
readonly string cursor;
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor)
{
this.subjects = subjects;
this.order = order;
this.cursor = cursor;
}
public GenericSelectTarget(Actor subject, string order, string cursor)
{
this.subjects = new Actor[] { subject };
this.subject = subject;
this.order = order;
this.cursor = cursor;
}
@@ -44,35 +35,16 @@ namespace OpenRA.Orders
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Left && world.Map.IsInMap(xy))
if( mi.Button == MouseButton.Left && world.Map.IsInMap( xy ) )
{
world.CancelInputMode();
foreach (var subject in subjects)
yield return new Order(order, subject, xy);
yield return new Order( order, subject, xy );
}
}
public virtual void Tick(World world) { }
public void RenderBeforeWorld(WorldRenderer wr, World world)
{
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
t.RenderBeforeWorld(wr, a);
Game.Renderer.Flush();
}
public void RenderAfterWorld(WorldRenderer wr, World world)
{
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPostRenderSelection>())
t.RenderAfterWorld(wr, a);
Game.Renderer.Flush();
}
public void RenderAfterWorld(World world) { }
public void RenderBeforeWorld(World world) { }
public string GetCursor(World world, int2 xy, MouseInput mi) { return world.Map.IsInMap(xy) ? cursor : "generic-blocked"; }
}
@@ -94,4 +66,5 @@ namespace OpenRA.Orders
world.CancelInputMode();
}
}
}

View File

@@ -9,7 +9,6 @@
#endregion
using System.Collections.Generic;
using OpenRA.Graphics;
namespace OpenRA
{
@@ -17,8 +16,8 @@ namespace OpenRA
{
IEnumerable<Order> Order(World world, int2 xy, MouseInput mi);
void Tick(World world);
void RenderBeforeWorld(WorldRenderer wr, World world);
void RenderAfterWorld(WorldRenderer wr, World world);
void RenderBeforeWorld(World world);
void RenderAfterWorld(World world);
string GetCursor(World world, int2 xy, MouseInput mi);
}
}

View File

@@ -6,107 +6,65 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;
#endregion
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Traits;
using OpenRA.FileFormats;
namespace OpenRA.Orders
{
class UnitOrderGenerator : IOrderGenerator
{
public IEnumerable<Order> Order( World world, int2 xy, MouseInput mi )
{
var custom = world.WorldActor.TraitOrDefault<ICustomUnitOrderGenerator>();
if (custom != null)
{
var customOrders = custom.Order(world, xy, mi);
public IEnumerable<Order> Order( World world, int2 xy, MouseInput mi )
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.Info.Traits.Contains<TargetableInfo>())
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
.FirstOrDefault();
var orders = world.Selection.Actors
.Select(a => OrderForUnit(a, xy, mi, underCursor))
.Where(o => o != null)
.ToArray();
var actorsInvolved = orders.Select(o => o.self).Distinct();
if (actorsInvolved.Any())
yield return new Order("CreateGroup", actorsInvolved.First().Owner.PlayerActor,
string.Join(",", actorsInvolved.Select(a => a.ActorID.ToString()).ToArray()));
foreach (var o in customOrders)
yield return o;
}
else
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.HasTrait<ITargetable>())
.OrderByDescending(
a =>
a.Info.Traits.Contains<SelectableInfo>()
? a.Info.Traits.Get<SelectableInfo>().Priority
: int.MinValue)
.FirstOrDefault();
var orders = world.Selection.Actors
.Select(a => OrderForUnit(a, xy, mi, underCursor))
.Where(o => o != null)
.ToArray();
var actorsInvolved = orders.Select(o => o.self).Distinct();
if (actorsInvolved.Any())
yield return new Order("CreateGroup", actorsInvolved.First().Owner.PlayerActor,
string.Join(",", actorsInvolved.Select(a => a.ActorID.ToString()).ToArray()))
;
foreach (var o in orders)
yield return CheckSameOrder(o.iot, o.trait.IssueOrder(o.self, o.iot, o.target));
}
foreach( var o in orders )
yield return CheckSameOrder( o.iot, o.trait.IssueOrder( o.self, o.iot, o.target ) );
}
public void Tick( World world )
{
var custom = world.WorldActor.TraitOrDefault<ICustomUnitOrderGenerator>();
if (custom != null)
{
custom.Tick(world);
}
}
public void RenderBeforeWorld( WorldRenderer wr, World world )
{
var custom = world.WorldActor.TraitOrDefault<ICustomUnitOrderGenerator>();
if (custom != null)
{
custom.RenderBeforeWorld(wr, world);
return;
}
public void Tick( World world ) {}
public void RenderBeforeWorld(World world)
{
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPreRenderSelection>())
t.RenderBeforeWorld( wr, a );
t.RenderBeforeWorld(a);
Game.Renderer.Flush();
}
public void RenderAfterWorld( WorldRenderer wr, World world )
{
var custom = world.WorldActor.TraitOrDefault<ICustomUnitOrderGenerator>();
if (custom != null)
{
custom.RenderAfterWorld(wr, world);
return;
}
public void RenderAfterWorld( World world )
{
foreach (var a in world.Selection.Actors)
if (!a.Destroyed)
foreach (var t in a.TraitsImplementing<IPostRenderSelection>())
t.RenderAfterWorld( wr, a );
t.RenderAfterWorld(a);
Game.Renderer.Flush();
}
public string GetCursor( World world, int2 xy, MouseInput mi )
{
var custom = world.WorldActor.TraitOrDefault<ICustomUnitOrderGenerator>();
if (custom != null)
{
return custom.GetCursor(world, xy, mi);
}
public string GetCursor( World world, int2 xy, MouseInput mi )
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.HasTrait<ITargetable>())
.Where(a => a.Info.Traits.Contains<TargetableInfo>())
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>() ? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
.FirstOrDefault();

View File

@@ -15,17 +15,16 @@ using System.Linq;
using OpenRA.Support;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Move
namespace OpenRA
{
public class PathFinderInfo : ITraitInfo
{
public object Create( ActorInitializer init ) { return new PathFinder( init.world ); }
}
public class PathFinder
{
readonly World world;
public PathFinder( World world ) { this.world = world; }
public PathFinder( World world )
{
this.world = world;
}
class CachedPath
{
@@ -41,13 +40,13 @@ namespace OpenRA.Mods.RA.Move
public List<int2> FindUnitPath(int2 from, int2 target, Actor self)
{
using (new PerfSample("Pathfinder"))
using (new PerfSample("find_unit_path"))
{
var cached = CachedPaths.FirstOrDefault(p => p.from == from && p.to == target && p.actor == self);
if (cached != null)
{
Log.Write("debug", "Actor {0} asked for a path from {1} tick(s) ago", self.ActorID, world.FrameNumber - cached.tick);
cached.tick = world.FrameNumber;
Log.Write("debug", "Actor {0} asked for a path from {1} tick(s) ago", self.ActorID, Game.LocalTick - cached.tick);
cached.tick = Game.LocalTick;
return new List<int2>(cached.result);
}
@@ -62,15 +61,15 @@ namespace OpenRA.Mods.RA.Move
CheckSanePath2(pb, from, target);
CachedPaths.RemoveAll(p => world.FrameNumber - p.tick > MaxPathAge);
CachedPaths.Add(new CachedPath { from = from, to = target, actor = self, result = pb, tick = world.FrameNumber });
CachedPaths.RemoveAll(p => Game.LocalTick - p.tick > MaxPathAge);
CachedPaths.Add(new CachedPath { from = from, to = target, actor = self, result = pb, tick = Game.LocalTick });
return new List<int2>(pb);
}
}
public List<int2> FindUnitPathToRange( int2 src, int2 target, int range, Actor self )
{
using( new PerfSample( "Pathfinder" ) )
using( new PerfSample( "find_unit_path_multiple_src" ) )
{
var mobileInfo = self.Info.Traits.Get<MobileInfo>();
var tilesInRange = world.FindTilesInCircle(target, range)
@@ -94,11 +93,13 @@ namespace OpenRA.Mods.RA.Move
public List<int2> FindPath( PathSearch search )
{
using (new PerfSample("Pathfinder"))
//using (new PerfSample("find_path_inner"))
{
while (!search.queue.Empty)
{
var p = search.Expand( world );
PerfHistory.Increment("nodes_expanded", .01);
if (search.heuristic(p) == 0)
return MakePath(search.cellInfo, p);
}
@@ -126,29 +127,26 @@ namespace OpenRA.Mods.RA.Move
public List<int2> FindBidiPath( /* searches from both ends toward each other */
List<int2> FindBidiPath( /* searches from both ends toward each other */
PathSearch fromSrc,
PathSearch fromDest)
{
using (new PerfSample("Pathfinder"))
while (!fromSrc.queue.Empty && !fromDest.queue.Empty)
{
while (!fromSrc.queue.Empty && !fromDest.queue.Empty)
{
/* make some progress on the first search */
var p = fromSrc.Expand( world );
/* make some progress on the first search */
var p = fromSrc.Expand( world );
if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, p);
if (fromDest.cellInfo[p.X, p.Y].Seen && fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, p);
/* make some progress on the second search */
var q = fromDest.Expand( world );
/* make some progress on the second search */
var q = fromDest.Expand( world );
if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, q);
}
return new List<int2>();
if (fromSrc.cellInfo[q.X, q.Y].Seen && fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
return MakeBidiPath(fromSrc, fromDest, q);
}
return new List<int2>();
}
static List<int2> MakeBidiPath(PathSearch a, PathSearch b, int2 p)

View File

@@ -13,7 +13,7 @@ using System.Collections.Generic;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Move
namespace OpenRA
{
public class PathSearch
{
@@ -27,11 +27,13 @@ namespace OpenRA.Mods.RA.Move
public bool inReverse;
MobileInfo mobileInfo;
BuildingInfluence bim;
UnitInfluence uim;
public PathSearch(World world, MobileInfo mobileInfo)
{
this.world = world;
bim = world.WorldActor.Trait<BuildingInfluence>();
uim = world.WorldActor.Trait<UnitInfluence>();
cellInfo = InitCellInfo();
this.mobileInfo = mobileInfo;
@@ -70,7 +72,7 @@ namespace OpenRA.Mods.RA.Move
public PathSearch FromPoint(int2 from)
{
AddInitialCell( from );
AddInitialCell( world, from );
return this;
}
@@ -105,7 +107,7 @@ namespace OpenRA.Mods.RA.Move
if (costHere == int.MaxValue)
continue;
if (!Mobile.CanEnterCell(mobileInfo, world, uim, newHere, ignoreBuilding, checkForBlocked))
if (!Mobile.CanEnterCell(mobileInfo, world, uim, bim, newHere, ignoreBuilding, checkForBlocked))
continue;
if (customBlock != null && customBlock(newHere))
@@ -153,7 +155,7 @@ namespace OpenRA.Mods.RA.Move
new int2( 1, 1 ),
};
public void AddInitialCell( int2 location )
public void AddInitialCell( World world, int2 location )
{
if (!world.Map.IsInMap(location.X, location.Y))
return;
@@ -175,7 +177,7 @@ namespace OpenRA.Mods.RA.Move
heuristic = DefaultEstimator( target ),
checkForBlocked = checkForBlocked };
search.AddInitialCell( from );
search.AddInitialCell( world, from );
return search;
}
@@ -187,8 +189,8 @@ namespace OpenRA.Mods.RA.Move
checkForBlocked = checkForBlocked
};
foreach( var sl in froms )
search.AddInitialCell( sl );
foreach (var sl in froms)
search.AddInitialCell(world, sl);
return search;
}

View File

@@ -13,86 +13,94 @@ using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Network;
using OpenRA.Traits;
namespace OpenRA
{
public enum PowerState { Normal, Low, Critical };
public enum WinState { Won, Lost, Undefined };
public class Player
{
public Actor PlayerActor;
public int Kills;
using OpenRA.Traits;
namespace OpenRA
{
public enum PowerState { Normal, Low, Critical };
public enum WinState { Won, Lost, Undefined };
public class Player
{
public Actor PlayerActor;
public int Kills;
public int Deaths;
public WinState WinState = WinState.Undefined;
public readonly string Palette;
public readonly Color Color;
public readonly Color Color2;
public readonly string PlayerName;
public readonly string InternalName;
public readonly CountryInfo Country;
public readonly int Index;
public WinState WinState = WinState.Undefined;
public readonly string Palette;
public readonly Color Color;
public readonly Color Color2;
public readonly string PlayerName;
public readonly string InternalName;
public readonly CountryInfo Country;
public readonly int Index;
public readonly bool NonCombatant = false;
public readonly int ClientIndex;
public readonly PlayerReference PlayerRef;
public bool IsBot;
public ShroudRenderer Shroud;
public World World { get; private set; }
public Player(World world, PlayerReference pr, int index)
{
World = world;
Shroud = new ShroudRenderer(this, world.Map);
Index = index;
Palette = "player" + index;
Color = pr.Color;
public readonly PlayerReference PlayerRef;
public ShroudRenderer Shroud;
public World World { get; private set; }
public Player( World world, PlayerReference pr, int index )
{
World = world;
Shroud = new ShroudRenderer(this, world.Map);
Index = index;
Palette = "player"+index;
Color = pr.Color;
Color2 = pr.Color2;
ClientIndex = 0; /* it's a map player, "owned" by host */
PlayerName = InternalName = pr.Name;
NonCombatant = pr.NonCombatant;
Country = world.GetCountries()
ClientIndex = 0; /* it's a map player, "owned" by host */
PlayerName = InternalName = pr.Name;
NonCombatant = pr.NonCombatant;
Country = world.GetCountries()
.FirstOrDefault(c => pr.Race == c.Race)
?? world.GetCountries().Random(world.SharedRandom);
PlayerRef = pr;
PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) });
}
public Player(World world, Session.Client client, PlayerReference pr, int index)
{
World = world;
Shroud = new ShroudRenderer(this, world.Map);
PlayerRef = pr;
RegisterPlayerColor(world, Palette);
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
}
public Player( World world, Session.Client client, PlayerReference pr, int index )
{
World = world;
Shroud = new ShroudRenderer(this, world.Map);
Index = index;
Palette = "player" + index;
Color = client.Color1;
Color2 = client.Color2;
Palette = "player"+index;
Color = client.Color1;
Color2 = client.Color2;
PlayerName = client.Name;
InternalName = pr.Name;
Country = world.GetCountries()
.FirstOrDefault(c => client != null && client.Country == c.Race)
InternalName = pr.Name;
Country = world.GetCountries()
.FirstOrDefault(c => client != null && client.Country == c.Race)
?? world.GetCountries().Random(world.SharedRandom);
ClientIndex = client.Index;
PlayerRef = pr;
PlayerActor = world.CreateActor("Player", new TypeDictionary { new OwnerInit(this) });
}
public void GiveAdvice(string advice)
{
Sound.PlayToPlayer(this, advice);
}
public Dictionary<Player, Stance> Stances = new Dictionary<Player, Stance>();
}
PlayerRef = pr;
RegisterPlayerColor(world, Palette);
PlayerActor = world.CreateActor("Player", new TypeDictionary{ new OwnerInit( this ) });
}
public void RegisterPlayerColor(World world, string palette)
{
var info = Rules.Info["world"].Traits.Get<PlayerColorPaletteInfo>();
var newpal = new Palette(world.WorldRenderer.GetPalette(info.BasePalette),
new PlayerColorRemap(Color, Color2, info.PaletteFormat));
world.WorldRenderer.AddPalette(palette, newpal);
}
public void GiveAdvice(string advice)
{
Sound.PlayToPlayer(this, advice);
}
public Dictionary<Player, Stance> Stances = new Dictionary<Player, Stance>();
}
}

View File

@@ -15,20 +15,20 @@ using System.Net.Sockets;
namespace OpenRA.Server
{
public class Connection
class Connection
{
internal Socket socket;
internal List<byte> data = new List<byte>();
internal ReceiveState State = ReceiveState.Header;
internal int ExpectLength = 8;
internal int Frame = 0;
public Socket socket;
public List<byte> data = new List<byte>();
public ReceiveState State = ReceiveState.Header;
public int ExpectLength = 8;
public int Frame = 0;
internal int MostRecentFrame = 0;
public int MostRecentFrame = 0;
/* client data */
public int PlayerIndex { get; internal set; }
public int PlayerIndex;
internal byte[] PopBytes(int n)
public byte[] PopBytes(int n)
{
var result = data.GetRange(0, n);
data.RemoveRange(0, n);
@@ -65,7 +65,7 @@ namespace OpenRA.Server
return true;
}
internal void ReadData()
public void ReadData()
{
if (ReadDataInner())
while (data.Count >= ExpectLength)

View File

@@ -1,84 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Drawing;
using OpenRA.Network;
using OpenRA.Traits;
namespace OpenRA.Server
{
public interface IServerExtension
{
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnReadyUp(Connection conn, Session.Client client);
void OnStartGame();
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnNickChange(Connection conn, Session.Client client, string newName);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnRaceChange(Connection conn, Session.Client client, string newRace);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnSlotChange(Connection conn, Session.Client client, Session.Slot slot, Map map);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnTeamChange(Connection conn, Session.Client getClient, int team);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnSpawnpointChange(Connection conn, Session.Client getClient, int spawnPoint);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnColorChange(Connection conn, Session.Client getClient, Color fromArgb, Color color);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnChat(Connection conn, string message, bool teamChat);
void OnServerStart();
void OnServerStop(bool forced);
void OnLoadMap(Map map);
/// <summary>
/// Return false to drop the connection
/// </summary>
bool OnValidateConnection(bool gameStarted, Connection newConn);
void OnLobbySync(Session lobbyInfo, bool gameStarted);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnPingMasterServer(Session lobbyInfo, bool gameStarted);
/// <summary>
/// Return true to use the built-in handling
/// </summary>
bool OnIngameChat(Session.Client client, string message, bool teamChat);
void OnIngameSetStance(Player player, Player stanceForPlayer, Stance newStance);
void OnLobbyUp();
void OnRejoinLobby(World world);
}
}

View File

@@ -18,7 +18,7 @@ using OpenRA.Widgets;
namespace OpenRA.Server
{
public static class MasterServerQuery
static class MasterServerQuery
{
public static event Action<GameServer[]> OnComplete = _ => { };
public static event Action<string> OnVersion = _ => { };
@@ -62,13 +62,8 @@ namespace OpenRA.Server
{
try
{
string motdText = GetData(new Uri(masterServerUrl + "motd.php?v=" + ClientVersion));
string[] p = motdText.Split('|');
if (p.Length == 2 && p[1].Length == int.Parse(p[0]))
{
motd.SetText(p[1]);
motd.ResetScroll();
}
motd.SetText(GetData(new Uri(masterServerUrl + "motd.php?v=" + ClientVersion)));
motd.ResetScroll();
}
catch
{
@@ -114,7 +109,7 @@ namespace OpenRA.Server
}
}
public class GameServer
class GameServer
{
public readonly int Id = 0;
public readonly string Name = null;

View File

@@ -1,40 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Drawing;
using OpenRA.Network;
using OpenRA.Traits;
namespace OpenRA.Server
{
public class NullServerExtension : IServerExtension
{
public virtual bool OnReadyUp(Connection conn, Session.Client client) { return true; }
public virtual void OnStartGame() { }
public virtual bool OnNickChange(Connection conn, Session.Client client, string newName) { return true; }
public virtual bool OnRaceChange(Connection conn, Session.Client client, string newRace) { return true; }
public virtual bool OnSlotChange(Connection conn, Session.Client client, Session.Slot slot, Map map) { return true; }
public virtual bool OnTeamChange(Connection conn, Session.Client getClient, int team) { return true; }
public virtual bool OnSpawnpointChange(Connection conn, Session.Client getClient, int spawnPoint) { return true; }
public virtual bool OnColorChange(Connection conn, Session.Client getClient, Color fromArgb, Color color) { return true; }
public virtual bool OnChat(Connection conn, string message, bool teamChat) { return true; }
public virtual void OnServerStart() { }
public virtual void OnServerStop(bool forced) { }
// Good spot to manipulate number of spectators! ie set Server.MaxSpectators
public virtual void OnLoadMap(Map map) { }
public virtual bool OnValidateConnection(bool gameStarted, Connection newConn) { return true; }
public virtual void OnLobbySync(Session lobbyInfo, bool gameStarted) { }
public virtual bool OnPingMasterServer(Session lobbyInfo, bool gameStarted) { return true; }
public virtual bool OnIngameChat(Session.Client client, string message, bool teamChat) { return true; }
public virtual void OnIngameSetStance(Player player, Player stanceForPlayer, Stance newStance) { }
public virtual void OnLobbyUp() { }
public virtual void OnRejoinLobby(World world) { }
}
}

View File

@@ -25,17 +25,12 @@ namespace OpenRA.Server
{
static class Server
{
public static Connection[] Connections
{
get { return conns.ToArray(); }
}
static List<Connection> conns = new List<Connection>();
static TcpListener listener = null;
static Dictionary<int, List<Connection>> inFlightFrames
= new Dictionary<int, List<Connection>>();
static Session lobbyInfo;
internal static bool GameStarted = false;
static bool GameStarted = false;
static string Name;
static int ExternalPort;
static int randomSeed;
@@ -45,9 +40,6 @@ namespace OpenRA.Server
const int MasterPingInterval = 60 * 3; // 3 minutes. server has a 5 minute TTL for games, so give ourselves a bit
// of leeway.
public static int MaxSpectators = 4; // How many spectators to allow // @todo Expose this as an option
static int lastPing = 0;
static bool isInternetServer;
static string masterServerUrl;
@@ -55,27 +47,6 @@ namespace OpenRA.Server
static ModData ModData;
static Map Map;
public static void StopListening()
{
conns.Clear();
GameStarted = false;
try { listener.Stop(); }
catch { }
E(e => e.OnServerStop(true));
}
public static void E(Action<IServerExtension> f)
{
E(g => { f(g); return true; });
}
public static bool E(Func<IServerExtension, bool> f)
{
return Game.Settings.Server.Extension == null ||
f(Game.Settings.Server.Extension);
}
public static void ServerMain(ModData modData, Settings settings, string map)
{
Log.AddChannel("server", "server.log");
@@ -83,18 +54,17 @@ namespace OpenRA.Server
isInitialPing = true;
Server.masterServerUrl = settings.Server.MasterServer;
isInternetServer = settings.Server.AdvertiseOnline;
listener = new TcpListener(IPAddress.Any, settings.Server.ListenPort);
Name = settings.Server.Name;
ExternalPort = settings.Server.ExternalPort;
randomSeed = (int)DateTime.Now.ToBinary();
ModData = modData;
lobbyInfo = new Session( settings.Game.Mods );
lobbyInfo = new Session();
lobbyInfo.GlobalSettings.Mods = settings.Game.Mods;
lobbyInfo.GlobalSettings.RandomSeed = randomSeed;
lobbyInfo.GlobalSettings.Map = map;
lobbyInfo.GlobalSettings.AllowCheats = settings.Server.AllowCheats;
lobbyInfo.GlobalSettings.ServerName = settings.Server.Name;
LoadMap(); // populates the Session's slots, too.
@@ -113,8 +83,6 @@ namespace OpenRA.Server
throw new InvalidOperationException( "Unable to start server: port is already in use" );
}
E(e => e.OnServerStart());
new Thread( _ =>
{
for( ; ; )
@@ -127,7 +95,7 @@ namespace OpenRA.Server
foreach( Socket s in checkRead )
if( s == listener.Server ) AcceptConnection();
else if (conns.Count > 0) conns.Single( c => c.socket == s ).ReadData();
else conns.Single( c => c.socket == s ).ReadData();
if (Environment.TickCount - lastPing > MasterPingInterval * 1000)
PingMasterServer();
@@ -140,7 +108,6 @@ namespace OpenRA.Server
{
listener.Stop();
GameStarted = false;
E(e => e.OnServerStop(false));
break;
}
}
@@ -168,32 +135,31 @@ namespace OpenRA.Server
.Where(s => s != null)
.Select((s, i) => { s.Index = i; return s; })
.ToList();
E(e => e.OnLoadMap(Map));
// Generate slots for spectators
for (int i = 0; i < MaxSpectators; i++)
lobbyInfo.Slots.Add(new Session.Slot
{
Spectator = true,
Index = lobbyInfo.Slots.Count(),
MapPlayer = null,
Bot = null
});
}
/* lobby rework todo:
*
* - auto-assign players to slots
* - show all the slots in the lobby ui.
* - rework the game start so we actually use the slots.
* - all players should be able to click an empty slot to move to it
* - host should be able to choose whether a slot is open/closed/bot, with
* potentially more than one choice of bot class.
* - host should be able to kick a client from the lobby by closing its slot.
* - change lobby commands so the host can configure bots, rather than
* just configuring itself.
* - "teams together" option for team games -- will eliminate most need
* for manual spawnpoint choosing.
* - 256 max players is a dirty hack
* - pick sensible non-conflicting colors for bots.
*/
static int ChooseFreePlayerIndex()
{
for (var i = 0; i < 256; i++)
for (var i = 0; i < 8; i++)
if (conns.All(c => c.PlayerIndex != i))
return i;
throw new InvalidOperationException("Already got 256 players");
throw new InvalidOperationException("Already got 8 players");
}
static int ChooseFreeSlot()
@@ -204,30 +170,7 @@ namespace OpenRA.Server
static void AcceptConnection()
{
Socket newSocket = null;
try
{
if (!listener.Server.IsBound) return;
newSocket = listener.AcceptSocket();
}catch
{
/* could have an exception here when listener 'goes away' when calling AcceptConnection! */
/* alternative would be to use locking but the listener doesnt go away without a reason */
return;
}
var newConn = new Connection { socket = newSocket };
if (!E(e => e.OnValidateConnection(GameStarted, newConn)))
{
DropClient(newConn, new Exception() );
return;
}
var newConn = new Connection { socket = listener.AcceptSocket() };
try
{
if (GameStarted)
@@ -248,25 +191,19 @@ namespace OpenRA.Server
conns.Add(newConn);
var defaults = new GameRules.PlayerSettings();
var client = new Session.Client()
{
Index = newConn.PlayerIndex,
Color1 = defaults.Color1,
Color2 = defaults.Color2,
Name = defaults.Name,
Country = "random",
State = Session.ClientState.NotReady,
SpawnPoint = 0,
Team = 0,
Slot = ChooseFreeSlot(),
};
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == client.Slot );
if (slotData != null)
SyncClientToPlayerReference(client, Map.Players[slotData.MapPlayer]);
lobbyInfo.Clients.Add(client);
lobbyInfo.Clients.Add(
new Session.Client()
{
Index = newConn.PlayerIndex,
Color1 = defaults.Color1,
Color2 = defaults.Color2,
Name = defaults.Name,
Country = "random",
State = Session.ClientState.NotReady,
SpawnPoint = 0,
Team = 0,
Slot = ChooseFreeSlot(),
});
Log.Write("server", "Client {0}: Accepted connection from {1}",
newConn.PlayerIndex, newConn.socket.RemoteEndPoint);
@@ -338,20 +275,7 @@ namespace OpenRA.Server
catch (NotImplementedException) { }
}
public static void SyncClientToPlayerReference(Session.Client c, PlayerReference pr)
{
if (pr == null)
return;
if (pr.LockColor)
{
c.Color1 = pr.Color;
c.Color2 = pr.Color2;
}
if (pr.LockRace)
c.Country = pr.Race;
}
public static bool InterpretCommand(Connection conn, string cmd)
static bool InterpretCommand(Connection conn, string cmd)
{
var dict = new Dictionary<string, Func<string, bool>>
{
@@ -371,12 +295,9 @@ namespace OpenRA.Server
SyncLobbyInfo();
if (Game.Settings.Server.Extension== null || Game.Settings.Server.Extension.OnReadyUp(conn, client))
{
if (conns.Count > 0 && conns.All(c => GetClient(c).State == Session.ClientState.Ready))
InterpretCommand(conn, "startgame");
}
if (conns.Count > 0 && conns.All(c => GetClient(c).State == Session.ClientState.Ready))
InterpretCommand(conn, "startgame");
return true;
}},
{ "startgame",
@@ -390,8 +311,6 @@ namespace OpenRA.Server
DispatchOrders(null, 0,
new ServerOrder("StartGame", "").Serialize());
E(e => e.OnStartGame());
PingMasterServer();
return true;
}},
@@ -399,10 +318,7 @@ namespace OpenRA.Server
s =>
{
Log.Write("server", "Player@{0} is now known as {1}", conn.socket.RemoteEndPoint, s);
if (E(e => e.OnNickChange(conn, GetClient(conn), s)))
GetClient(conn).Name = s;
GetClient(conn).Name = s;
SyncLobbyInfo();
return true;
}},
@@ -420,29 +336,8 @@ namespace OpenRA.Server
}},
{ "race",
s =>
{
if (E(e => e.OnRaceChange(conn, GetClient(conn), s)))
GetClient(conn).Country = s;
SyncLobbyInfo();
return true;
}},
{ "spectator",
s =>
{
var slotData = lobbyInfo.Slots.Where(ax => ax.Spectator && !lobbyInfo.Clients.Any(l => l.Slot == ax.Index)).FirstOrDefault();
if (slotData == null)
return true;
var cl = GetClient(conn);
if (E(e => e.OnSlotChange(conn, cl, slotData, Map)))
{
cl.Slot = slotData.Index;
SyncClientToPlayerReference(cl, slotData.MapPlayer != null
? Map.Players[slotData.MapPlayer] : null);
}
{
GetClient(conn).Country = s;
SyncLobbyInfo();
return true;
}},
@@ -451,10 +346,8 @@ namespace OpenRA.Server
{
int team;
if (!int.TryParse(s, out team)) { Log.Write("server", "Invalid team: {0}", s ); return false; }
if (E(e => e.OnTeamChange(conn, GetClient(conn), team)))
{
GetClient(conn).Team = team;
}
GetClient(conn).Team = team;
SyncLobbyInfo();
return true;
}},
@@ -473,10 +366,8 @@ namespace OpenRA.Server
SendChatTo( conn, "You can't be at the same spawn point as another player" );
return true;
}
if (E(e => e.OnSpawnpointChange(conn, GetClient(conn), spawnPoint)))
{
GetClient(conn).SpawnPoint = spawnPoint;
}
GetClient(conn).SpawnPoint = spawnPoint;
SyncLobbyInfo();
return true;
}},
@@ -484,14 +375,8 @@ namespace OpenRA.Server
s =>
{
var c = s.Split(',').Select(cc => int.Parse(cc)).ToArray();
var c1 = Color.FromArgb(c[0], c[1], c[2]);
var c2 = Color.FromArgb(c[3], c[4], c[5]);
if (E(e => e.OnColorChange(conn, GetClient(conn), c1, c2)))
{
GetClient(conn).Color1 = c1;
GetClient(conn).Color2 = c2;
}
GetClient(conn).Color1 = Color.FromArgb(c[0],c[1],c[2]);
GetClient(conn).Color2 = Color.FromArgb(c[3],c[4],c[5]);
SyncLobbyInfo();
return true;
}},
@@ -506,15 +391,7 @@ namespace OpenRA.Server
|| lobbyInfo.Clients.Any( c => c.Slot == slot ))
return false;
var cl = GetClient(conn);
if (E(e => e.OnSlotChange(conn, cl, slotData, Map)))
{
cl.Slot = slot;
SyncClientToPlayerReference(cl, slotData.MapPlayer != null
? Map.Players[slotData.MapPlayer] : null);
}
GetClient(conn).Slot = slot;
SyncLobbyInfo();
return true;
}},
@@ -614,13 +491,18 @@ namespace OpenRA.Server
foreach(var client in lobbyInfo.Clients)
{
client.SpawnPoint = 0;
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == client.Slot );
if (slotData != null)
SyncClientToPlayerReference(client, Map.Players[slotData.MapPlayer]);
client.State = Session.ClientState.NotReady;
}
SyncLobbyInfo();
return true;
}},
{ "mods",
s =>
{
var args = s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
lobbyInfo.GlobalSettings.Mods = args.GetRange(0,args.Count - 1).ToArray();
lobbyInfo.GlobalSettings.Map = args.Last();
SyncLobbyInfo();
return true;
}},
@@ -656,41 +538,34 @@ namespace OpenRA.Server
new ServerOrder("Chat", text).Serialize());
}
static void SendChat(Connection asConn, string text)
{
DispatchOrders(asConn, 0, new ServerOrder("Chat", text).Serialize());
}
static void SendDisconnected(Connection asConn)
{
DispatchOrders(asConn, 0, new ServerOrder("Disconnected", "").Serialize());
}
static void SendChat(Connection asConn, string text)
{
DispatchOrders(asConn, 0, new ServerOrder("Chat", text).Serialize());
}
static void InterpretServerOrder(Connection conn, ServerOrder so)
{
switch (so.Name)
{
case "Command":
{
if(GameStarted)
SendChatTo(conn, "Cannot change state when game started.");
else if (GetClient(conn).State == Session.ClientState.Ready && !(so.Data == "ready" || so.Data == "startgame") )
SendChatTo(conn, "Cannot change state when marked as ready.");
else if (!InterpretCommand(conn, so.Data))
{
if (GameStarted)
SendChatTo(conn, "Cannot change state when game started.");
else if (GetClient(conn).State == Session.ClientState.Ready && !(so.Data == "ready" || so.Data == "startgame"))
SendChatTo(conn, "Cannot change state when marked as ready.");
else if (!InterpretCommand(conn, so.Data))
{
Log.Write("server", "Bad server command: {0}", so.Data);
SendChatTo(conn, "Bad server command.");
};
}
break;
Log.Write("server", "Bad server command: {0}", so.Data);
SendChatTo(conn, "Bad server command.");
};
}
break;
case "Chat":
case "Chat":
case "TeamChat":
case "Disconnected":
if (E(e => e.OnChat(conn, so.Data, so.Name == "TeamChat")))
foreach (var c in conns.Except(conn).ToArray())
DispatchOrdersToClient(c, GetClient(conn).Index, 0, so.Serialize());
break;
foreach (var c in conns.Except(conn).ToArray())
DispatchOrdersToClient(c, GetClient(conn).Index, 0, so.Serialize());
break;
}
}
@@ -704,9 +579,6 @@ namespace OpenRA.Server
conns.Remove(toDrop);
SendChat(toDrop, "Connection Dropped");
if (GameStarted)
SendDisconnected(toDrop); /* Report disconnection */
lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex);
DispatchOrders( toDrop, toDrop.MostRecentFrame, new byte[] { 0xbf } );
@@ -717,8 +589,6 @@ namespace OpenRA.Server
static void SyncLobbyInfo()
{
E(e => e.OnLobbySync(lobbyInfo, GameStarted));
if (!GameStarted) /* don't do this while the game is running, it breaks things. */
DispatchOrders(null, 0,
new ServerOrder("SyncInfo", lobbyInfo.Serialize()).Serialize());
@@ -732,9 +602,6 @@ namespace OpenRA.Server
{
if (isBusy || !isInternetServer) return;
if (!E(e => e.OnPingMasterServer(lobbyInfo, GameStarted)))
return;
lastPing = Environment.TickCount;
isBusy = true;

View File

@@ -9,6 +9,7 @@
#endregion
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Graphics;
namespace OpenRA
@@ -127,7 +128,7 @@ namespace OpenRA
return shadowBits[SpecialShroudTiles[u ^ uSides][v]];
}
internal void Draw( WorldRenderer wr )
internal void Draw()
{
if (disabled)
return;
@@ -150,13 +151,13 @@ namespace OpenRA
var minx = clipRect.Left;
var maxx = clipRect.Right;
DrawShroud( wr, minx, miny, maxx, maxy, fogSprites, "fog" );
DrawShroud( wr, minx, miny, maxx, maxy, sprites, "shroud" );
DrawShroud( minx, miny, maxx, maxy, fogSprites, "fog" );
DrawShroud( minx, miny, maxx, maxy, sprites, "shroud" );
}
void DrawShroud( WorldRenderer wr, int minx, int miny, int maxx, int maxy, Sprite[,] s, string pal )
void DrawShroud( int minx, int miny, int maxx, int maxy, Sprite[,] s, string pal )
{
var shroudPalette = wr.GetPaletteIndex(pal);
var shroudPalette = Game.world.WorldRenderer.GetPaletteIndex(pal);
for (var j = miny; j < maxy; j++)
{

View File

@@ -48,49 +48,60 @@ namespace OpenRA
public static void SetListenerPosition(float2 position) { soundEngine.SetListenerPosition(position); }
static ISound Play(Player player, string name, bool headRelative, float2 pos, float volumeModifier)
public static void Play(string name)
{
if (player != null && player != player.World.LocalPlayer)
return null;
if (name == "" || name == null)
return null;
return;
return soundEngine.Play2D(sounds[name],
false, headRelative, pos,
InternalSoundVolume * volumeModifier);
var sound = sounds[name];
soundEngine.Play2D(sound, false, true, float2.Zero, SoundVolume);
}
public static void Play(string name, float2 pos)
{
if (name == "" || name == null)
return;
var sound = sounds[name];
soundEngine.Play2D(sound, false, false, pos, SoundVolume);
}
public static void PlayToPlayer(Player player, string name)
{
if( player == player.World.LocalPlayer )
Play( name );
}
public static void PlayToPlayer(Player player, string name, float2 pos)
{
if (player == player.World.LocalPlayer)
Play(name, pos);
}
public static ISound Play(string name) { return Play(null, name, true, float2.Zero, 1); }
public static ISound Play(string name, float2 pos) { return Play(null, name, false, pos, 1); }
public static ISound Play(string name, float volumeModifier) { return Play(null, name, true, float2.Zero, volumeModifier); }
public static ISound Play(string name, float2 pos, float volumeModifier) { return Play(null, name, false, pos, volumeModifier); }
public static ISound PlayToPlayer(Player player, string name) { return Play( player, name, true, float2.Zero, 1); }
public static ISound PlayToPlayer(Player player, string name, float2 pos) { return Play(player, name, false, pos, 1); }
public static void PlayVideo(byte[] raw)
{
rawSource = LoadSoundRaw(raw);
video = soundEngine.Play2D(rawSource, false, true, float2.Zero, InternalSoundVolume);
video = soundEngine.Play2D(rawSource, false, true, float2.Zero, SoundVolume);
}
public static void PlayVideo()
{
if (video != null)
soundEngine.PauseSound(video, false);
}
public static void PauseVideo()
{
if (video != null)
soundEngine.PauseSound(video, true);
}
public static void StopVideo()
{
if (video != null)
soundEngine.StopSound(video);
}
public static void Tick()
{
// Song finished
@@ -100,13 +111,13 @@ namespace OpenRA
OnMusicComplete();
}
}
static Action OnMusicComplete;
public static bool MusicPlaying { get; private set; }
public static void PlayMusic(string name)
{
PlayMusicThen(name, () => { });
PlayMusicThen(name, () => {});
}
public static void PlayMusicThen(string name, Action then)
{
@@ -121,13 +132,13 @@ namespace OpenRA
return;
}
StopMusic();
currentMusic = name;
MusicPlaying = true;
var sound = sounds[name];
music = soundEngine.Play2D(sound, false, true, float2.Zero, MusicVolume);
}
public static void PlayMusic()
{
if (music == null)
@@ -136,26 +147,20 @@ namespace OpenRA
soundEngine.PauseSound(music, false);
}
public static void StopSound(ISound sound)
{
if (sound != null)
soundEngine.StopSound(sound);
}
public static void StopMusic()
{
if (music != null)
soundEngine.StopSound(music);
MusicPlaying = false;
currentMusic = null;
}
public static void PauseMusic()
{
if (music == null)
return;
MusicPlaying = false;
soundEngine.PauseSound(music, true);
}
@@ -163,28 +168,16 @@ namespace OpenRA
public static float GlobalVolume
{
get { return soundEngine.Volume; }
set { soundEngine.Volume = value; }
set { soundEngine.Volume = value;}
}
static float soundVolumeModifier = 1.0f;
public static float SoundVolumeModifier
{
get { return soundVolumeModifier; }
set
{
soundVolumeModifier = value;
soundEngine.SetSoundVolume(InternalSoundVolume, music, video);
}
}
static float InternalSoundVolume { get { return SoundVolume * soundVolumeModifier; } }
public static float SoundVolume
{
get { return Game.Settings.Sound.SoundVolume; }
set
{
Game.Settings.Sound.SoundVolume = value;
soundEngine.SetSoundVolume(InternalSoundVolume, music, video);
soundEngine.SetSoundVolume(value, music, video);
}
}
@@ -198,7 +191,7 @@ namespace OpenRA
music.Volume = value;
}
}
public static float VideoVolume
{
get { return Game.Settings.Sound.VideoVolume; }
@@ -209,17 +202,17 @@ namespace OpenRA
video.Volume = value;
}
}
public static float MusicSeekPosition
{
get { return (music != null) ? music.SeekPosition : 0; }
get { return (music != null)? music.SeekPosition : 0; }
}
public static float VideoSeekPosition
{
get { return (video != null) ? video.SeekPosition : 0; }
get { return (video != null)? video.SeekPosition : 0; }
}
// Returns true if it played a phrase
public static bool PlayVoice(string phrase, Actor voicedUnit, string variant)
{
@@ -235,9 +228,9 @@ namespace OpenRA
var clip = vi.Pools.Value[phrase].GetNext();
if (clip == null)
return false;
var variantext = (vi.Variants.ContainsKey(variant) && !vi.DisableVariants.Contains(phrase)) ?
vi.Variants[variant][voicedUnit.ActorID % vi.Variants[variant].Length] : vi.DefaultVariant;
var variantext = (vi.Variants.ContainsKey(variant) && !vi.DisableVariants.Contains(phrase))?
vi.Variants[variant][voicedUnit.ActorID % vi.Variants.Count] : vi.DefaultVariant;
Play(clip + variantext);
return true;
}
@@ -256,9 +249,8 @@ namespace OpenRA
void SetSoundVolume(float volume, ISound music, ISound video);
}
interface ISoundSource { }
public interface ISound
interface ISoundSource {}
interface ISound
{
float Volume { get; set; }
float SeekPosition { get; }
@@ -291,7 +283,7 @@ namespace OpenRA
Log.Write("debug", "Failed generating OpenAL source {0}", i);
return;
}
sourcePool.Add(source, false);
}
}
@@ -343,10 +335,10 @@ namespace OpenRA
get { return volume; }
set { Al.alListenerf(Al.AL_GAIN, volume = value); }
}
public void PauseSound(ISound sound, bool paused)
{
int key = ((OpenAlSound)sound).source;
int key = ((OpenAlSound) sound).source;
int state;
Al.alGetSourcei(key, Al.AL_SOURCE_STATE, out state);
if (state == Al.AL_PLAYING && paused)
@@ -354,9 +346,9 @@ namespace OpenRA
else if (state == Al.AL_PAUSED && !paused)
Al.alSourcePlay(key);
}
public void SetAllSoundsPaused(bool paused)
{
{
foreach (int key in sourcePool.Keys)
{
int state;
@@ -365,35 +357,35 @@ namespace OpenRA
Al.alSourcePause(key);
else if (state == Al.AL_PAUSED && !paused)
Al.alSourcePlay(key);
}
}
public void SetSoundVolume(float volume, ISound music, ISound video)
{
var sounds = sourcePool.Select(s => s.Key).Where(b =>
{
var sounds = sourcePool.Select(s => s.Key).Where( b =>
{
int state;
Al.alGetSourcei(b, Al.AL_SOURCE_STATE, out state);
return ((state == Al.AL_PLAYING || state == Al.AL_PAUSED) &&
((music != null) ? b != ((OpenAlSound)music).source : true) &&
((video != null) ? b != ((OpenAlSound)video).source : true));
return ((state == Al.AL_PLAYING || state == Al.AL_PAUSED) &&
((music != null)? b != ((OpenAlSound) music).source : true) &&
((video != null)? b != ((OpenAlSound) video).source : true));
}).ToList();
foreach (var s in sounds)
{
Al.alSourcef(s, Al.AL_GAIN, volume);
}
}
public void StopSound(ISound sound)
{
int key = ((OpenAlSound)sound).source;
int key = ((OpenAlSound) sound).source;
int state;
Al.alGetSourcei(key, Al.AL_SOURCE_STATE, out state);
if (state == Al.AL_PLAYING || state == Al.AL_PAUSED)
Al.alSourceStop(key);
}
public void StopAllSounds()
{
foreach (int key in sourcePool.Keys)
@@ -407,7 +399,7 @@ namespace OpenRA
public void SetListenerPosition(float2 position)
{
var orientation = new[] { 0f, 0f, 1f, 0f, -1f, 0f };
var orientation = new [] { 0f, 0f, 1f, 0f, -1f, 0f };
Al.alListener3f(Al.AL_POSITION, position.X, position.Y, 50);
Al.alListenerfv(Al.AL_ORIENTATION, ref orientation[0]);
@@ -459,26 +451,26 @@ namespace OpenRA
public float Volume
{
get { return volume; }
set
set
{
if (source != -1)
Al.alSourcef(source, Al.AL_GAIN, volume = value);
Al.alSourcef(source, Al.AL_GAIN, volume = value);
}
}
public float SeekPosition
{
get
{
float pos;
Al.alGetSourcef(source, Al.AL_SAMPLE_OFFSET, out pos);
return pos / 22050f;
return pos/22050f;
}
}
public bool Playing
{
get
get
{
int state;
Al.alGetSourcei(source, Al.AL_SOURCE_STATE, out state);

View File

@@ -90,7 +90,7 @@ namespace OpenRA.Support
}
}
public class PerfSample : IDisposable
class PerfSample : IDisposable
{
readonly Stopwatch sw = new Stopwatch();
readonly string Item;

View File

@@ -139,9 +139,7 @@ namespace OpenRA
public static T CheckSyncUnchanged<T>( World world, Func<T> fn )
{
if( world == null ) return fn();
int sync = world.SyncHash();
bool prevInUnsyncedCode = inUnsyncedCode;
inUnsyncedCode = true;
try
{
@@ -149,9 +147,9 @@ namespace OpenRA
}
finally
{
inUnsyncedCode = prevInUnsyncedCode;
inUnsyncedCode = false;
if( sync != world.SyncHash() )
throw new InvalidOperationException( "CheckSyncUnchanged: sync-changing code may not run here" );
throw new InvalidOperationException( "Desync in DispatchMouseInput" );
}
}

View File

@@ -1,38 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRA.Traits
{
public abstract class CancelableActivity : IActivity
{
protected IActivity NextActivity { get; private set; }
protected bool IsCanceled { get; private set; }
public abstract IActivity Tick( Actor self );
protected virtual bool OnCancel( Actor self ) { return true; }
public void Cancel( Actor self )
{
IsCanceled = OnCancel( self );
if( IsCanceled )
NextActivity = null;
else if (NextActivity != null)
NextActivity.Cancel( self );
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public virtual IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
}

View File

@@ -9,9 +9,8 @@
#endregion
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Move
namespace OpenRA.Traits.Activities
{
public class Drag : IActivity
{

View File

@@ -12,13 +12,10 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
using OpenRA.Traits.Activities;
namespace OpenRA.Mods.RA.Move
namespace OpenRA.Traits.Activities
{
class Move : CancelableActivity
public class Move : CancelableActivity
{
int2? destination;
int nearEnough;
@@ -26,12 +23,24 @@ namespace OpenRA.Mods.RA.Move
Func<Actor, Mobile, List<int2>> getPath;
public Actor ignoreBuilding;
int ticksBeforePathing;
const int avgTicksBeforePathing = 5;
const int spreadTicksBeforePathing = 5;
Move()
{
ticksBeforePathing = avgTicksBeforePathing +
Game.world.SharedRandom.Next(-spreadTicksBeforePathing, spreadTicksBeforePathing);
}
// Scriptable move order
// Ignores lane bias and nearby units
public Move( int2 destination )
public Move( int2 destination )
: this()
{
this.getPath = (self,mobile) =>
self.World.WorldActor.Trait<PathFinder>().FindPath(
self.World.PathFinder.FindPath(
PathSearch.FromPoint( self.World, mobile.Info, mobile.toCell, destination, false )
.WithoutLaneBias());
this.destination = destination;
@@ -39,18 +48,20 @@ namespace OpenRA.Mods.RA.Move
}
public Move( int2 destination, int nearEnough )
: this()
{
this.getPath = (self,mobile) => self.World.WorldActor.Trait<PathFinder>().FindUnitPath( mobile.toCell, destination, self );
this.getPath = (self,mobile) => self.World.PathFinder.FindUnitPath( mobile.toCell, destination, self );
this.destination = destination;
this.nearEnough = nearEnough;
}
public Move(int2 destination, Actor ignoreBuilding)
: this()
{
this.getPath = (self,mobile) =>
self.World.WorldActor.Trait<PathFinder>().FindPath(
self.World.PathFinder.FindPath(
PathSearch.FromPoint( self.World, mobile.Info, mobile.toCell, destination, false )
.WithCustomBlocker( self.World.WorldActor.Trait<PathFinder>().AvoidUnitsNear( mobile.toCell, 4, self ))
.WithCustomBlocker( self.World.PathFinder.AvoidUnitsNear( mobile.toCell, 4, self ))
.WithIgnoredBuilding( ignoreBuilding ));
this.destination = destination;
@@ -59,8 +70,9 @@ namespace OpenRA.Mods.RA.Move
}
public Move( Actor target, int range )
: this()
{
this.getPath = (self,mobile) => self.World.WorldActor.Trait<PathFinder>().FindUnitPathToRange(
this.getPath = (self,mobile) => self.World.PathFinder.FindUnitPathToRange(
mobile.toCell, target.Location,
range, self );
this.destination = null;
@@ -68,8 +80,9 @@ namespace OpenRA.Mods.RA.Move
}
public Move(Target target, int range)
: this()
{
this.getPath = (self,mobile) => self.World.WorldActor.Trait<PathFinder>().FindUnitPathToRange(
this.getPath = (self,mobile) => self.World.PathFinder.FindUnitPathToRange(
mobile.toCell, Util.CellContaining(target.CenterLocation),
range, self);
this.destination = null;
@@ -77,6 +90,7 @@ namespace OpenRA.Mods.RA.Move
}
public Move(Func<List<int2>> getPath)
: this()
{
this.getPath = (_1,_2) => getPath();
this.destination = null;
@@ -111,9 +125,9 @@ namespace OpenRA.Mods.RA.Move
if( path == null )
{
if (mobile.ticksBeforePathing > 0)
if (ticksBeforePathing > 0)
{
--mobile.ticksBeforePathing;
--ticksBeforePathing;
return this;
}
@@ -210,12 +224,6 @@ namespace OpenRA.Mods.RA.Move
if (--waitTicksRemaining >= 0)
return null;
if (mobile.ticksBeforePathing > 0)
{
--mobile.ticksBeforePathing;
return null;
}
mobile.RemoveInfluence();
var newPath = EvalPath(self, mobile);
mobile.AddInfluence();
@@ -231,7 +239,7 @@ namespace OpenRA.Mods.RA.Move
return nextCell;
}
protected override bool OnCancel( Actor self )
protected override bool OnCancel()
{
path = new List<int2>();
return true;
@@ -290,7 +298,7 @@ namespace OpenRA.Mods.RA.Move
IActivity InnerTick( Actor self, Mobile mobile )
{
moveFraction += mobile.MovementSpeedForCell(self, mobile.toCell);
moveFraction += (int)mobile.MovementSpeedForCell(self, mobile.toCell);
if( moveFraction <= moveFractionTotal )
return this;

View File

@@ -8,9 +8,7 @@
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
namespace OpenRA.Traits.Activities
{
public class RemoveSelf : CancelableActivity
{

View File

@@ -9,9 +9,8 @@
#endregion
using System.Collections.Generic;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
namespace OpenRA.Traits.Activities
{
class Sell : IActivity
{

View File

@@ -9,9 +9,8 @@
#endregion
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Activities
namespace OpenRA.Traits.Activities
{
public class Turn : CancelableActivity
{

View File

@@ -8,8 +8,6 @@
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Traits
{
/* tag trait for "bases": mcv/fact */

View File

@@ -0,0 +1,102 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Traits.Activities;
namespace OpenRA.Traits
{
public class BuildingInfo : ITraitInfo
{
public readonly int Power = 0;
public readonly bool BaseNormal = true;
public readonly bool WaterBound = false;
public readonly int Adjacent = 2;
public readonly bool Capturable = false;
public readonly string Footprint = "x";
public readonly int2 Dimensions = new int2(1, 1);
public readonly bool Unsellable = false;
public readonly float RefundPercent = 0.5f;
public readonly string[] BuildSounds = {"placbldg.aud", "build5.aud"};
public readonly string[] SellSounds = {"cashturn.aud"};
public readonly string DamagedSound = "kaboom1.aud";
public readonly string DestroyedSound = "kaboom22.aud";
public object Create(ActorInitializer init) { return new Building(init); }
}
public class Building : INotifyDamage, IResolveOrder, IOccupySpace
{
readonly Actor self;
public readonly BuildingInfo Info;
[Sync]
readonly int2 topLeft;
readonly PowerManager PlayerPower;
public int2 PxPosition { get { return ( 2 * topLeft + Info.Dimensions ) * Game.CellSize / 2; } }
public Building(ActorInitializer init)
{
this.self = init.self;
this.topLeft = init.Get<LocationInit,int2>();
Info = self.Info.Traits.Get<BuildingInfo>();
PlayerPower = init.self.Owner.PlayerActor.Trait<PowerManager>();
}
public int GetPowerUsage()
{
if (Info.Power <= 0)
return Info.Power;
var health = self.TraitOrDefault<Health>();
return health != null ? (Info.Power * health.HP / health.MaxHP) : Info.Power;
}
public void Damaged(Actor self, AttackInfo e)
{
// Power plants lose power with damage
if (Info.Power > 0)
PlayerPower.UpdateActor(self, GetPowerUsage());
if (e.DamageState == DamageState.Dead)
{
self.World.WorldActor.Trait<ScreenShaker>().AddEffect(10, self.CenterLocation, 1);
Sound.Play(Info.DestroyedSound, self.CenterLocation);
}
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "Sell")
{
self.CancelActivity();
self.QueueActivity(new Sell());
}
}
public int2 TopLeft
{
get { return topLeft; }
}
public IEnumerable<int2> OccupiedCells()
{
return Footprint.UnpathableTiles( self.Info.Name, Info, TopLeft );
}
}
}

View File

@@ -8,9 +8,7 @@
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
namespace OpenRA.Traits
{
// allow a nonstandard sell/repair value to avoid
// buy-sell exploits like c&c's PROC.

View File

@@ -8,8 +8,8 @@
*/
#endregion
using System.Drawing;
using OpenRA.Graphics;
using System.Drawing;
using OpenRA.Traits.Activities;
namespace OpenRA.Traits
{
@@ -45,7 +45,7 @@ namespace OpenRA.Traits
this.c = c;
}
public void RenderAfterWorld(WorldRenderer wr, Actor self)
public void RenderAfterWorld(Actor self)
{
if (self.IsIdle) return;

View File

@@ -1,19 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
namespace OpenRA.Traits
{
public class EditorAppearanceInfo : TraitInfo<EditorAppearance>
{
public readonly bool RelativeToTopLeft = false;
}
public class EditorAppearance { }
}

View File

@@ -22,7 +22,6 @@ namespace OpenRA.Traits
public class HealthInfo : ITraitInfo
{
public readonly int HP = 0;
public readonly float Radius = 10;
public virtual object Create(ActorInitializer init) { return new Health(init, this); }
}
@@ -81,15 +80,15 @@ namespace OpenRA.Traits
var oldState = this.DamageState;
/* apply the damage modifiers, if we have any. */
var modifier = (float)self.TraitsImplementing<IDamageModifier>().Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
.Select(t => t.GetDamageModifier(attacker, warhead)).Product();
/* apply the damage modifiers, if we have any. */
var modifier = (float)self.TraitsImplementing<IDamageModifier>()
.Select(t => t.GetDamageModifier(warhead)).Product();
damage = (int)(damage * modifier);
hp -= damage;
foreach (var nd in self.TraitsImplementing<INotifyDamage>().Concat(self.Owner.PlayerActor.TraitsImplementing<INotifyDamage>()))
hp -= damage;
foreach (var nd in self.TraitsImplementing<INotifyDamage>())
nd.Damaged(self, new AttackInfo
{
Attacker = attacker,
@@ -97,9 +96,7 @@ namespace OpenRA.Traits
DamageState = this.DamageState,
PreviousDamageState = oldState,
DamageStateChanged = this.DamageState != oldState,
Warhead = warhead,
PreviousHealth = hp + damage < 0 ? 0 : hp + damage,
Health = hp
Warhead = warhead
});
if (hp <= 0)

View File

@@ -8,9 +8,7 @@
*/
#endregion
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
namespace OpenRA.Traits
{
public class LineBuildInfo : TraitInfo<LineBuild>
{

View File

@@ -17,9 +17,8 @@ using OpenRA.Traits.Activities;
using OpenRA.FileFormats;
using System.Diagnostics;
using OpenRA.Orders;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Move
namespace OpenRA.Traits
{
public class MobileInfo : ITraitInfo
{
@@ -40,7 +39,7 @@ namespace OpenRA.Mods.RA.Move
Dictionary<string,TerrainInfo> ret = new Dictionary<string, TerrainInfo>();
foreach (var t in y.NodesDict["TerrainSpeeds"].Nodes)
{
var speed = (decimal)FieldLoader.GetValue("speed", typeof(decimal),t.Value.Value);
var speed = (float)FieldLoader.GetValue("speed", typeof(float),t.Value.Value);
var cost = t.Value.NodesDict.ContainsKey("PathingCost") ? (int)FieldLoader.GetValue("cost", typeof(int), t.Value.NodesDict["PathingCost"].Value) : (int)(10000/speed);
ret.Add(t.Key, new TerrainInfo{Speed = speed, Cost = cost});
}
@@ -51,7 +50,7 @@ namespace OpenRA.Mods.RA.Move
public class TerrainInfo
{
public int Cost = int.MaxValue;
public decimal Speed = 0;
public float Speed = 0;
}
}
@@ -102,10 +101,6 @@ namespace OpenRA.Mods.RA.Move
}
UnitInfluence uim;
const int avgTicksBeforePathing = 5;
const int spreadTicksBeforePathing = 5;
internal int ticksBeforePathing = 0;
public Mobile(ActorInitializer init, MobileInfo info)
{
@@ -180,20 +175,16 @@ namespace OpenRA.Mods.RA.Move
return;
if( !order.Queued ) self.CancelActivity();
self.QueueActivity(new Move(currentLocation, 8));
self.QueueActivity(new Activities.Move(currentLocation, 8));
if (self.Owner == self.World.LocalPlayer)
self.World.AddFrameEndTask(w =>
{
if (self.Destroyed) return;
w.Add(new MoveFlash(self.World, order.TargetLocation));
var line = self.TraitOrDefault<DrawLineToTarget>();
if (line != null)
line.SetTarget(self, Target.FromCell(currentLocation), Color.Green);
});
ticksBeforePathing = avgTicksBeforePathing +
self.World.SharedRandom.Next( -spreadTicksBeforePathing, spreadTicksBeforePathing );
}
}
@@ -222,21 +213,39 @@ namespace OpenRA.Mods.RA.Move
public static bool CanEnterCell( World world, MobileInfo mi, int2 cell, Actor ignoreActor, bool checkTransientActors )
{
var bim = world.WorldActor.Trait<BuildingInfluence>();
var uim = world.WorldActor.Trait<UnitInfluence>();
return Mobile.CanEnterCell( mi, world, uim, cell, ignoreActor, checkTransientActors );
return Mobile.CanEnterCell( mi, world, uim, bim, cell, ignoreActor, checkTransientActors );
}
public bool CanEnterCell( int2 cell, Actor ignoreActor, bool checkTransientActors )
{
var bim = self.World.WorldActor.Trait<BuildingInfluence>();
var uim = self.World.WorldActor.Trait<UnitInfluence>();
return CanEnterCell( Info, self.World, uim, cell, ignoreActor, checkTransientActors );
return CanEnterCell( Info, self.World, uim, bim, cell, ignoreActor, checkTransientActors );
}
public static bool CanEnterCell( MobileInfo mobileInfo, World world, UnitInfluence uim, int2 cell, Actor ignoreActor, bool checkTransientActors )
public static bool CanEnterCell( MobileInfo mobileInfo, World world, UnitInfluence uim, BuildingInfluence bim, int2 cell, Actor ignoreActor, bool checkTransientActors )
{
if (MovementCostForCell(mobileInfo, world, cell) == int.MaxValue)
return false;
// Check for buildings
var building = bim.GetBuildingBlocking(cell);
if (building != null && building != ignoreActor)
{
if (mobileInfo.Crushes == null)
return false;
var crushable = building.TraitsImplementing<ICrushable>();
if (crushable.Count() == 0)
return false;
if (!crushable.Any(b => b.CrushClasses.Intersect(mobileInfo.Crushes).Any()))
return false;
}
// Check mobile actors
var blockingActors = uim.GetUnitsAt( cell ).Where( x => x != ignoreActor ).ToList();
if (checkTransientActors && blockingActors.Count > 0)
{
@@ -275,17 +284,18 @@ namespace OpenRA.Mods.RA.Move
return info.TerrainSpeeds[type].Cost;
}
public int MovementSpeedForCell(Actor self, int2 cell)
public float MovementSpeedForCell(Actor self, int2 cell)
{
var type = self.World.GetTerrainType(cell);
if (!Info.TerrainSpeeds.ContainsKey(type))
return 0;
decimal speed = Info.Speed * Info.TerrainSpeeds[type].Speed;
foreach( var t in self.TraitsImplementing<ISpeedModifier>() )
speed *= t.GetSpeedModifier();
return (int)(speed / 100);
var modifier = self
.TraitsImplementing<ISpeedModifier>()
.Select(t => t.GetSpeedModifier())
.Product();
return Info.Speed * Info.TerrainSpeeds[type].Speed * modifier / 100f;
}
public void AddInfluence()
@@ -333,7 +343,6 @@ namespace OpenRA.Mods.RA.Move
if (self.Owner == self.World.LocalPlayer)
self.World.AddFrameEndTask(w =>
{
if (self.Destroyed) return;
var line = self.TraitOrDefault<DrawLineToTarget>();
if (line != null)
line.SetTargetSilently(self, Target.FromCell(moveTo.Value), Color.Green);
@@ -373,12 +382,5 @@ namespace OpenRA.Mods.RA.Move
return true;
}
}
public IActivity MoveTo( int2 cell ) { return new Move( cell ); }
public IActivity MoveTo( int2 cell, int range ) { return new Move( cell, range ); }
public IActivity MoveTo( int2 cell, Actor ignoredActor ) { return new Move( cell, ignoredActor ); }
public IActivity MoveTo( Actor target, int range ) { return new Move( target, range ); }
public IActivity MoveTo( Target target, int range ) { return new Move( target, range ); }
public IActivity MoveTo( Func<List<int2>> pathFunc ) { return new Move( pathFunc ); }
}
}

View File

@@ -17,8 +17,7 @@ namespace OpenRA.Traits
public bool FastBuild = false;
public bool FastCharge = false;
public bool DisableShroud = false;
public bool PathDebug = false;
public bool UnitInfluenceDebug = false;
public bool PathDebug = false;
public object Create (ActorInitializer init) { return new DeveloperMode(this); }
}
@@ -31,21 +30,19 @@ namespace OpenRA.Traits
[Sync] public bool FastBuild;
[Sync] public bool DisableShroud;
[Sync] public bool PathDebug;
[Sync] public bool UnitInfluenceDebug;
public DeveloperMode(DeveloperModeInfo info)
{
Info = info;
FastBuild = Info.FastBuild;
FastCharge = Info.FastCharge;
DisableShroud = Info.DisableShroud;
PathDebug = Info.PathDebug;
UnitInfluenceDebug = info.UnitInfluenceDebug;
PathDebug = Info.PathDebug;
}
public void ResolveOrder (Actor self, Order order)
{
if (!self.World.LobbyInfo.GlobalSettings.AllowCheats) return;
if (!Game.LobbyInfo.GlobalSettings.AllowCheats) return;
switch(order.OrderString)
{
@@ -82,8 +79,9 @@ namespace OpenRA.Traits
break;
}
case "DevUnitDebug":
{
UnitInfluenceDebug ^= true;
{
if (self.World.LocalPlayer == self.Owner)
Game.Settings.Debug.ShowCollisions ^= true;
break;
}
case "DevGiveExploration":

View File

@@ -6,12 +6,14 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Collections.Generic;
using OpenRA.Traits;
#endregion
namespace OpenRA.Mods.RA.Buildings
using System;
using System.Linq;
using System.Collections.Generic;
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
public class PowerManagerInfo : ITraitInfo
{

View File

@@ -11,9 +11,8 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Traits;
namespace OpenRA.Mods.RA.Buildings
namespace OpenRA.Traits
{
public class TechTreeInfo : ITraitInfo
{

View File

@@ -1,42 +0,0 @@
using System.Collections.Generic;
namespace OpenRA.Traits
{
public class ScaleInfo : ITraitInfo
{
public readonly float Value = 1f; /* default */
public ScaleInfo() { } /* only because we have other ctors */
public object Create(ActorInitializer init) { return new Scale(init.self, this); }
}
public class Scale : IRenderModifier
{
Actor self;
public ScaleInfo Info { get; protected set; }
public Scale(Actor self, ScaleInfo info)
{
this.Info = info;
this.self = self;
}
public IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r)
{
var r2 = new List<Renderable>(r);
var r3 = new List<Renderable>();
for (int i = 0; i < r2.Count;i++)
{
var renderable = r2[i];
renderable.Scale = Info.Value;
r3.Add(renderable);
// yield return renderable;
}
return r3;
}
}
}

View File

@@ -10,6 +10,7 @@
using System.Drawing;
using OpenRA.Graphics;
using System.Linq;
namespace OpenRA.Traits
{
@@ -19,6 +20,7 @@ namespace OpenRA.Traits
public readonly int[] Bounds = null;
[VoiceReference]
public readonly string Voice = null;
public readonly float Radius = 10;
}
public class Selectable : IPostRenderSelection
@@ -27,7 +29,7 @@ namespace OpenRA.Traits
static readonly string[] pipStrings = { "pip-empty", "pip-green", "pip-yellow", "pip-red", "pip-gray" };
static readonly string[] tagStrings = { "", "tag-fake", "tag-primary" };
public void RenderAfterWorld (WorldRenderer wr, Actor self)
public void RenderAfterWorld (Actor self)
{
var bounds = self.GetBounds(true);
@@ -38,9 +40,9 @@ namespace OpenRA.Traits
DrawSelectionBox(self, xy, Xy, xY, XY, Color.White);
DrawHealthBar(self, xy, Xy);
DrawControlGroup(wr, self, xy);
DrawPips(wr, self, xY);
DrawTags(wr, self, new float2(.5f * (bounds.Left + bounds.Right), bounds.Top));
DrawControlGroup(self, xy);
DrawPips(self, xY);
DrawTags(self, new float2(.5f * (bounds.Left + bounds.Right), bounds.Top));
DrawUnitPath(self);
}
@@ -87,7 +89,7 @@ namespace OpenRA.Traits
Game.Renderer.LineRenderer.DrawLine(xy + new float2(0, -4), z + new float2(0, -4), healthColor2, healthColor2);
}
void DrawControlGroup(WorldRenderer wr, Actor self, float2 basePosition)
void DrawControlGroup(Actor self, float2 basePosition)
{
var group = self.World.Selection.GetControlGroupForActor(self);
if (group == null) return;
@@ -95,10 +97,10 @@ namespace OpenRA.Traits
var pipImages = new Animation("pips");
pipImages.PlayFetchIndex("groups", () => (int)group);
pipImages.Tick();
pipImages.Image.DrawAt(wr, basePosition + new float2(-8, 1), "chrome");
pipImages.Image.DrawAt(basePosition + new float2(-8, 1), "chrome");
}
void DrawPips(WorldRenderer wr, Actor self, float2 basePosition)
void DrawPips(Actor self, float2 basePosition)
{
if (self.Owner != self.World.LocalPlayer) return;
@@ -121,7 +123,7 @@ namespace OpenRA.Traits
}
var pipImages = new Animation("pips");
pipImages.PlayRepeating(pipStrings[(int)pip]);
pipImages.Image.DrawAt(wr, pipxyBase + pipxyOffset, "chrome");
pipImages.Image.DrawAt(pipxyBase + pipxyOffset, "chrome");
pipxyOffset += new float2(4, 0);
}
// Increment row
@@ -130,7 +132,7 @@ namespace OpenRA.Traits
}
}
void DrawTags(WorldRenderer wr, Actor self, float2 basePosition)
void DrawTags(Actor self, float2 basePosition)
{
if (self.Owner != self.World.LocalPlayer) return;
@@ -147,7 +149,7 @@ namespace OpenRA.Traits
var tagImages = new Animation("pips");
tagImages.PlayRepeating(tagStrings[(int)tag]);
tagImages.Image.DrawAt(wr, tagxyBase + tagxyOffset, "chrome");
tagImages.Image.DrawAt(tagxyBase + tagxyOffset, "chrome");
// Increment row
tagxyOffset.Y += 8;
@@ -157,7 +159,7 @@ namespace OpenRA.Traits
void DrawUnitPath(Actor self)
{
if (self.World.LocalPlayer == null ||!self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
if (!self.World.LocalPlayer.PlayerActor.Trait<DeveloperMode>().PathDebug) return;
var activity = self.GetCurrentActivity();
var mobile = self.TraitOrDefault<IMove>();

View File

@@ -0,0 +1,36 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System.Drawing;
using OpenRA.Graphics;
using System.Linq;
namespace OpenRA.Traits
{
public class TargetableInfo : ITraitInfo
{
public readonly string[] TargetTypes = {};
public virtual object Create( ActorInitializer init ) { return new Targetable(this); }
}
public class Targetable : ITargetable
{
TargetableInfo Info;
public Targetable(TargetableInfo info)
{
Info = info;
}
public string[] TargetTypes
{
get { return Info.TargetTypes;}
}
}
}

109
OpenRA.Game/Traits/TraitsInterfaces.cs Executable file → Normal file
View File

@@ -10,10 +10,9 @@
using System.Collections.Generic;
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.FileFormats;
namespace OpenRA.Traits
{
@@ -29,9 +28,7 @@ namespace OpenRA.Traits
public int Damage;
public DamageState DamageState;
public DamageState PreviousDamageState;
public bool DamageStateChanged;
public int PreviousHealth;
public int Health;
public bool DamageStateChanged;
}
public interface ITick { void Tick(Actor self); }
@@ -47,13 +44,12 @@ namespace OpenRA.Traits
int OrderPriority { get; }
bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor );
bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor );
}
public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
public interface IValidateOrder { bool OrderValidation(OrderManager orderManager, World world, int clientId, Order order);
}
}
public interface IResolveOrder { void ResolveOrder(Actor self, Order order); }
public interface IOrderCursor { string CursorForOrder(Actor self, Order order); }
public interface IOrderVoice { string VoicePhraseForOrder(Actor self, Order order); }
public interface ICustomUnitOrderGenerator : IOrderGenerator {};
public interface ITargetable { string[] TargetTypes { get; } }
public interface INotifySold { void Selling( Actor self ); void Sold( Actor self ); }
public interface INotifyDamage { void Damaged(Actor self, AttackInfo e); }
public interface INotifyBuildComplete { void BuildingComplete(Actor self); }
@@ -106,10 +102,9 @@ namespace OpenRA.Traits
public interface INotifyAttack { void Attacking(Actor self); }
public interface IRenderModifier { IEnumerable<Renderable> ModifyRender(Actor self, IEnumerable<Renderable> r); }
public interface IDamageModifier { float GetDamageModifier(Actor attacker, WarheadInfo warhead); }
public interface ISpeedModifier { decimal GetSpeedModifier(); }
public interface IDamageModifier { float GetDamageModifier( WarheadInfo warhead ); }
public interface ISpeedModifier { float GetSpeedModifier(); }
public interface IFirepowerModifier { float GetFirepowerModifier(); }
public interface IPalette { void InitPalette( WorldRenderer wr ); }
public interface IPaletteModifier { void AdjustPalette(Dictionary<string,Palette> b); }
public interface IPips { IEnumerable<PipType> GetPips(Actor self); }
public interface ITags { IEnumerable<TagType> GetTags(); }
@@ -147,37 +142,22 @@ namespace OpenRA.Traits
public readonly string Palette;
public readonly int Z;
public readonly int ZOffset;
public float Scale;
public Renderable(Sprite sprite, float2 pos, string palette, int z, int zOffset)
{
Sprite = sprite;
Pos = pos;
Palette = palette;
Z = z;
ZOffset = zOffset;
Scale = 1f; /* default */
}
public Renderable(Sprite sprite, float2 pos, string palette, int z, int zOffset, float scale)
{
Sprite = sprite;
Pos = pos;
Palette = palette;
Z = z;
ZOffset = zOffset;
Scale = scale; /* default */
}
public Renderable(Sprite sprite, float2 pos, string palette, int z, int zOffset)
{
Sprite = sprite;
Pos = pos;
Palette = palette;
Z = z;
ZOffset = zOffset;
}
public Renderable(Sprite sprite, float2 pos, string palette, int z)
: this(sprite, pos, palette, z, 0) { }
public Renderable(Sprite sprite, float2 pos, string palette, int z)
: this(sprite, pos, palette, z, 0) { }
public Renderable(Sprite sprite, float2 pos, string palette, int z, float scale)
: this(sprite, pos, palette, z, 0, scale) { }
public Renderable WithPalette(string newPalette) { return new Renderable(Sprite, Pos, newPalette, Z, ZOffset, Scale); }
public Renderable WithZOffset(int newOffset) { return new Renderable(Sprite, Pos, Palette, Z, newOffset, Scale); }
public Renderable WithPos(float2 newPos) { return new Renderable(Sprite, newPos, Palette, Z, ZOffset, Scale); }
public Renderable WithPalette(string newPalette) { return new Renderable(Sprite, Pos, newPalette, Z, ZOffset); }
public Renderable WithZOffset(int newOffset) { return new Renderable(Sprite, Pos, Palette, Z, newOffset); }
public Renderable WithPos(float2 newPos) { return new Renderable(Sprite, newPos, Palette, Z, ZOffset); }
}
public interface ITraitInfo { object Create(ActorInitializer init); }
@@ -200,17 +180,44 @@ namespace OpenRA.Traits
IEnumerable<float2> GetCurrentPath();
}
public interface IRenderOverlay { void Render( WorldRenderer wr ); }
public abstract class CancelableActivity : IActivity
{
protected IActivity NextActivity { get; private set; }
protected bool IsCanceled { get; private set; }
public abstract IActivity Tick( Actor self );
protected virtual bool OnCancel() { return true; }
public void Cancel( Actor self )
{
IsCanceled = OnCancel();
if( IsCanceled )
NextActivity = null;
else
NextActivity.Cancel( self );
}
public void Queue( IActivity activity )
{
if( NextActivity != null )
NextActivity.Queue( activity );
else
NextActivity = activity;
}
public virtual IEnumerable<float2> GetCurrentPath()
{
yield break;
}
}
public interface IRenderOverlay { void Render(); }
public interface INotifyIdle { void Idle(Actor self); }
public interface IBlocksBullets { }
public interface IPostRender { void RenderAfterWorld(WorldRenderer wr, Actor self); }
public interface IPostRenderSelection { void RenderAfterWorld(WorldRenderer wr, Actor self); }
public interface IPreRenderSelection { void RenderBeforeWorld(WorldRenderer wr, Actor self); }
public interface ITraitNotSynced{} // Traits marked with NotSynced arent sync-checked
public interface IPostRenderSelection { void RenderAfterWorld(Actor self); }
public interface IPreRenderSelection { void RenderBeforeWorld(Actor self); }
public struct Target // a target: either an actor, or a fixed location.
{
@@ -237,10 +244,4 @@ namespace OpenRA.Traits
public Actor Actor { get { return IsActor ? actor : null; } }
public bool IsActor { get { return actor != null && !actor.Destroyed; } }
}
public interface ITargetable
{
string[] TargetTypes { get; }
IEnumerable<int2> TargetableCells( Actor self );
}
}

View File

@@ -99,13 +99,7 @@ namespace OpenRA.Traits
public static Renderable Centered(Actor self, Sprite s, float2 location)
{
var pal = self.Owner == null ? "player0" : self.Owner.Palette;
var scale = self.TraitOrDefault<Scale>();
var scaleModifier = 1f;
if (scale != null)
scaleModifier = scale.Info.Value;
var loc = location - 0.5f * s.size * scaleModifier;
var loc = location - 0.5f * s.size;
return new Renderable(s, loc.Round(), pal, (int)self.CenterLocation.Y);
}

View File

@@ -1,31 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2010 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using OpenRA.Network;
namespace OpenRA.Traits
{
public class ValidateOrderInfo : TraitInfo<ValidateOrder> { }
public class ValidateOrder : IValidateOrder
{
public bool OrderValidation(OrderManager orderManager, World world, int clientId, Order order)
{
// Drop exploiting orders
if (order.Subject != null && order.Subject.Owner.ClientIndex != clientId)
{
Game.Debug("Detected exploit order from {0}: {1}".F(clientId, order.OrderString));
return false;
}
return true;
}
}
}

23
OpenRA.Game/Traits/Valued.cs Executable file
View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRA.Traits
{
public class ValuedInfo : TraitInfo<Valued>
{
public readonly int Cost = 0;
}
public class TooltipInfo : TraitInfo<Tooltip>
{
public readonly string Description = "";
public readonly string Name = "";
public readonly string Icon = null;
public readonly string[] AlternateName = { };
}
public class Valued { }
public class Tooltip { }
}

View File

@@ -6,17 +6,16 @@
* as published by the Free Software Foundation. For more information,
* see LICENSE.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Traits;
#endregion
namespace OpenRA.Mods.RA.Buildings
using System;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using System.Collections.Generic;
namespace OpenRA.Traits
{
class BibLayerInfo : ITraitInfo
{
@@ -72,9 +71,11 @@ namespace OpenRA.Mods.RA.Buildings
}
}
public void Render( WorldRenderer wr )
{
var cliprect = Game.viewport.ShroudBounds( world );
public void Render()
{
var cliprect = Game.viewport.ShroudBounds().HasValue
? Rectangle.Intersect(Game.viewport.ShroudBounds().Value, world.Map.Bounds) : world.Map.Bounds;
cliprect = Rectangle.Intersect(Game.viewport.ViewBounds(), cliprect);
foreach (var kv in tiles)
{
@@ -83,12 +84,12 @@ namespace OpenRA.Mods.RA.Buildings
if (world.LocalPlayer != null && !world.LocalPlayer.Shroud.IsExplored(kv.Key))
continue;
bibSprites[kv.Value.type - 1][kv.Value.image].DrawAt( wr,
bibSprites[kv.Value.type - 1][kv.Value.image].DrawAt(
Game.CellSize * kv.Key, "terrain");
}
}
}
public class BibInfo : TraitInfo<Bib> { }
class BibInfo : TraitInfo<Bib> { }
public class Bib { }
}

View File

@@ -8,9 +8,10 @@
*/
#endregion
using OpenRA.Traits;
using OpenRA.FileFormats;
using OpenRA.GameRules;
namespace OpenRA.Mods.RA.Buildings
namespace OpenRA.Traits
{
public class BuildingInfluenceInfo : ITraitInfo
{
@@ -19,26 +20,32 @@ namespace OpenRA.Mods.RA.Buildings
public class BuildingInfluence
{
bool[,] blocked;
Actor[,] influence;
Map map;
public BuildingInfluence( World world )
{
map = world.Map;
blocked = new bool[map.MapSize.X, map.MapSize.Y];
influence = new Actor[map.MapSize.X, map.MapSize.Y];
world.ActorAdded +=
a => { if (a.HasTrait<Building>())
a => { if (a.HasTrait<Building>())
ChangeInfluence(a, a.Trait<Building>(), true); };
world.ActorRemoved +=
a => { if (a.HasTrait<Building>())
a => { if (a.HasTrait<Building>())
ChangeInfluence(a, a.Trait<Building>(), false); };
}
void ChangeInfluence( Actor a, Building building, bool isAdd )
{
foreach( var u in FootprintUtils.Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location ) )
foreach( var u in Footprint.UnpathableTiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location ) )
if( map.IsInMap( u ) )
blocked[ u.X, u.Y ] = isAdd;
foreach( var u in Footprint.Tiles( a.Info.Name, a.Info.Traits.Get<BuildingInfo>(), a.Location ) )
if( map.IsInMap( u ) )
influence[ u.X, u.Y ] = isAdd ? a : null;
}
@@ -48,5 +55,21 @@ namespace OpenRA.Mods.RA.Buildings
if (!map.IsInMap(cell)) return null;
return influence[cell.X, cell.Y];
}
}
}
public Actor GetBuildingBlocking(int2 cell)
{
if (!map.IsInMap(cell) || !blocked[cell.X, cell.Y]) return null;
return influence[cell.X, cell.Y];
}
public bool CanMoveHere(int2 cell)
{
return map.IsInMap(cell) && !blocked[cell.X, cell.Y];
}
public bool CanMoveHere(int2 cell, Actor toIgnore)
{
return map.IsInMap(cell) &&
(!blocked[cell.X, cell.Y] || influence[cell.X, cell.Y] == toIgnore);
}
}}

View File

@@ -9,34 +9,13 @@
#endregion
using OpenRA.FileFormats;
using OpenRA.Graphics;
namespace OpenRA.Traits
{
public class PlayerColorPaletteInfo : ITraitInfo
public class PlayerColorPaletteInfo : TraitInfo<PlayerColorPalette>
{
public readonly string BasePalette = null;
public readonly string BaseName = "player";
public readonly PaletteFormat PaletteFormat = PaletteFormat.ra;
public object Create( ActorInitializer init ) { return new PlayerColorPalette( init.self.Owner, this ); }
}
public class PlayerColorPalette : IPalette
{
readonly Player owner;
readonly PlayerColorPaletteInfo info;
public PlayerColorPalette( Player owner, PlayerColorPaletteInfo info )
{
this.owner = owner;
this.info = info;
}
public void InitPalette( WorldRenderer wr )
{
var paletteName = "{0}{1}".F( info.BaseName, owner.Index );
var newpal = new Palette(wr.GetPalette(info.BasePalette),
new PlayerColorRemap(owner.Color, owner.Color2, info.PaletteFormat));
wr.AddPalette(paletteName, newpal);
}
}
public class PlayerColorPalette {}
}

View File

@@ -24,9 +24,11 @@ namespace OpenRA.Traits
public ResourceType[] resourceTypes;
CellContents[,] content;
public void Render( WorldRenderer wr )
public void Render()
{
var cliprect = Game.viewport.ShroudBounds( world );
var cliprect = Game.viewport.ShroudBounds().HasValue
? Rectangle.Intersect(Game.viewport.ShroudBounds().Value, world.Map.Bounds) : world.Map.Bounds;
cliprect = Rectangle.Intersect(Game.viewport.ViewBounds(), cliprect);
var minx = cliprect.Left;
@@ -36,16 +38,13 @@ namespace OpenRA.Traits
var maxy = cliprect.Bottom;
foreach( var rt in world.WorldActor.TraitsImplementing<ResourceType>() )
rt.info.PaletteIndex = wr.GetPaletteIndex(rt.info.Palette);
ShroudRenderer shroud = null;
if( world.LocalPlayer != null )
shroud = world.LocalPlayer.Shroud;
rt.info.PaletteIndex = world.WorldRenderer.GetPaletteIndex(rt.info.Palette);
for (int x = minx; x < maxx; x++)
for (int y = miny; y < maxy; y++)
{
if (shroud != null && !shroud.IsExplored(new int2(x, y)))
if (world.LocalPlayer != null &&
!world.LocalPlayer.Shroud.IsExplored(new int2(x, y)))
continue;
var c = content[x, y];
@@ -71,7 +70,7 @@ namespace OpenRA.Traits
for (int y = map.YOffset; y < map.YOffset + map.Height; y++)
{
// Todo: Valid terrain should be specified in the resource
if (!AllowResourceAt(new int2(x,y)))
if (!w.IsCellBuildable(new int2(x,y), false))
continue;
content[x, y].type = resourceTypes.FirstOrDefault(
@@ -89,14 +88,6 @@ namespace OpenRA.Traits
}
}
public bool AllowResourceAt( int2 a )
{
if( !world.Map.IsInMap( a.X, a.Y ) ) return false;
if( !world.GetTerrainInfo( a ).Buildable ) return false;
if( world.WorldActor.Trait<UnitInfluence>().AnyUnitsAt( a ) ) return false;
return true;
}
Sprite[] ChooseContent(ResourceType t)
{
return t.info.Sprites[world.SharedRandom.Next(t.info.Sprites.Length)];

View File

@@ -12,6 +12,9 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats;
using OpenRA.GameRules;
using OpenRA.Traits;
namespace OpenRA.Traits
{
@@ -119,14 +122,19 @@ namespace OpenRA.Traits
public static IEnumerable<int2> GetVisOrigins(Actor a)
{
var ios = a.TraitOrDefault<IOccupySpace>();
if (ios != null)
if (a.Info.Traits.Contains<BuildingInfo>())
{
var cells = ios.OccupiedCells();
if (cells.Any()) return cells;
var bi = a.Info.Traits.Get<BuildingInfo>();
return Footprint.Tiles(a.Info.Name, bi, a.Location);
}
else
{
var mobile = a.TraitOrDefault<Mobile>();
if (mobile != null)
return new[] { mobile.fromCell, mobile.toCell };
else
return new[] { (1f / Game.CellSize * a.CenterLocation).ToInt2() };
}
return new[] { (1f / Game.CellSize * a.CenterLocation).ToInt2() };
}
void RemoveActor(Actor a)

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