Compare commits
5 Commits
release-20
...
playtest-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae29941d52 | ||
|
|
e224fadbeb | ||
|
|
1cccef5434 | ||
|
|
319da4c5ae | ||
|
|
94fc260293 |
3
AUTHORS
3
AUTHORS
@@ -6,5 +6,4 @@ The OpenRA developers are:
|
||||
* Matthew Bowra-Dean
|
||||
* Paul Chote
|
||||
* Alli Witheford
|
||||
* Joakim Lindberg
|
||||
* Andrew Riedi
|
||||
* Joakim Lindberg
|
||||
4
HACKING
4
HACKING
@@ -68,7 +68,7 @@ to flush the renderer (if you want to see anything).
|
||||
UserSettings stores the data loaded from settings.ini (or defaults). Eventually we need to be
|
||||
able to save values changed in game into settings.ini (not yet implemented)
|
||||
|
||||
Bugs: There is a list of known bugs and features at http://bugs.open-ra.org/ .
|
||||
Bugs: There is a list of known bugs and features at http://red-bull.ijw.co.nz:3690/OpenRA .
|
||||
|
||||
We also have a website at http://www.open-ra.org/ .
|
||||
|
||||
@@ -76,7 +76,7 @@ Our IRC channel is #openra on irc.freenode.net .
|
||||
|
||||
As far as using git, get your own repository on github. You probably want to set up the gitbot
|
||||
to spam irc when you make commits (its nice to know). Push your changes into your git
|
||||
repository, and it will/might :P be merged into http://github.com/OpenRA/OpenRA .
|
||||
repository, and it will/might :P be merged into chrisforbes/OpenRA .
|
||||
See http://help.github.com/ for working with GitHub and see http://progit.org/ for working
|
||||
with Git.
|
||||
|
||||
|
||||
7
INSTALL
7
INSTALL
@@ -37,11 +37,7 @@ These need to be copied into the mods/cnc/packages/ directory.
|
||||
If you have a case-sensitive filesystem you must change the filenames to
|
||||
lower case.
|
||||
|
||||
The files can be downloaded from:
|
||||
http://open-ra.org/get-dependency.php?file=ra-packages for the Red Alert files and
|
||||
http://open-ra.org/get-dependency.php?file=cnc-packages for the Command & Conquer files.
|
||||
|
||||
Alternatively:
|
||||
Red Alert and C&C have been released by EA Games as freeware. They can be
|
||||
downloaded from http://www.commandandconquer.com/classic
|
||||
Unfortunately the installer is 16-bit and so won’t run on 64-bit operating
|
||||
@@ -59,7 +55,8 @@ WINDOWS:
|
||||
* .NET Framework >= 3.5-SP1
|
||||
(http://www.microsoft.com/downloads/details.aspx?FamilyID=AB99342F-5D1A-413D-8319-81DA479AB0D7&displaylang=en)
|
||||
* Tao Framework >= 2.1.0
|
||||
This is now bundled with OpenRA, copy the files in thirdparty/Tao to the game root directory.
|
||||
(http://sourceforge.net/projects/taoframework/)
|
||||
(required libs: Tao.OpenGL, Tao.Cg, Tao.Platform.Windows)
|
||||
* OpenAL >= 1.1
|
||||
(http://connect.creativelabs.com/openal/Downloads/oalinst.zip)
|
||||
* Cg Toolkit >= 2.2
|
||||
|
||||
82
Makefile
82
Makefile
@@ -1,7 +1,7 @@
|
||||
CSC = gmcs
|
||||
CSFLAGS = -nologo -warn:4 -debug:+ -debug:full -optimize- -codepage:utf8 -unsafe
|
||||
DEFINE = DEBUG;TRACE
|
||||
PROGRAMS = fileformats rcg rgl rnull game ra cnc seqed editor ralint filex tsbuild utility winlaunch
|
||||
PROGRAMS =fileformats gl game ra cnc seqed editor ralint filex tsbuild
|
||||
prefix = /usr/local
|
||||
datarootdir = $(prefix)/share
|
||||
datadir = $(datarootdir)
|
||||
@@ -16,32 +16,17 @@ COMMON_LIBS = System.dll System.Core.dll System.Drawing.dll System.Xml.dll
|
||||
fileformats_SRCS = $(shell find OpenRA.FileFormats/ -iname '*.cs')
|
||||
fileformats_TARGET = OpenRA.FileFormats.dll
|
||||
fileformats_KIND = library
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll System.Windows.Forms.dll thirdparty/ICSharpCode.SharpZipLib.dll
|
||||
fileformats_LIBS = $(COMMON_LIBS) thirdparty/Tao/Tao.Sdl.dll thirdparty/WindowsBase.dll
|
||||
|
||||
rcg_SRCS = $(shell find OpenRA.Renderer.Cg/ -iname '*.cs')
|
||||
rcg_TARGET = OpenRA.Renderer.Cg.dll
|
||||
rcg_KIND = library
|
||||
rcg_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rcg_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(rcg_DEPS) $(game_TARGET)
|
||||
gl_SRCS = $(shell find OpenRA.Gl/ -iname '*.cs')
|
||||
gl_TARGET = OpenRA.Gl.dll
|
||||
gl_KIND = library
|
||||
gl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
gl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(gl_DEPS) $(game_TARGET)
|
||||
|
||||
rgl_SRCS = $(shell find OpenRA.Renderer.Gl/ -iname '*.cs')
|
||||
rgl_TARGET = OpenRA.Renderer.Gl.dll
|
||||
rgl_KIND = library
|
||||
rgl_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rgl_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
thirdparty/Tao/Tao.Cg.dll thirdparty/Tao/Tao.OpenGl.dll thirdparty/Tao/Tao.Sdl.dll \
|
||||
$(rgl_DEPS) $(game_TARGET)
|
||||
|
||||
rnull_SRCS = $(shell find OpenRA.Renderer.Null/ -iname '*.cs')
|
||||
rnull_TARGET = OpenRA.Renderer.Null.dll
|
||||
rnull_KIND = library
|
||||
rnull_DEPS = $(fileformats_TARGET) $(game_TARGET)
|
||||
rnull_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll \
|
||||
$(rnull_DEPS) $(game_TARGET)
|
||||
|
||||
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
|
||||
game_SRCS = $(shell find OpenRA.Game/ -iname '*.cs')
|
||||
game_TARGET = OpenRA.Game.exe
|
||||
game_KIND = winexe
|
||||
game_DEPS = $(fileformats_TARGET)
|
||||
@@ -77,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)
|
||||
|
||||
@@ -94,37 +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)
|
||||
|
||||
winlaunch_SRCS = $(shell find OpenRA.Launcher/ -iname '*.cs')
|
||||
winlaunch_TARGET = OpenRA.Launcher.exe
|
||||
winlaunch_KIND = winexe
|
||||
winlaunch_DEPS =
|
||||
winlaunch_LIBS = $(COMMON_LIBS) System.Windows.Forms.dll
|
||||
winlaunch_EXTRA = -resource:OpenRA.Launcher.MainForm.resources \
|
||||
-resource:OpenRA.Launcher.InstallPackagesDialog.resources \
|
||||
-resource:OpenRA.Launcher.ConfigureModsDialog.resources
|
||||
|
||||
# -platform:x86
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: clean all game tool default mods mod_ra mod_cnc install uninstall editor_res editor tsbuild ralint seqed filex utility winlaunch
|
||||
core: game editor
|
||||
package: game editor utility
|
||||
all: game tools
|
||||
tools: editor ralint seqed filex tsbuild utility winlaunch
|
||||
game: $(fileformats_TARGET) $(rcg_TARGET) $(rgl_TARGET) $(rnull_TARGET) $(game_TARGET) $(ra_TARGET) $(cnc_TARGET)
|
||||
.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)
|
||||
|
||||
clean:
|
||||
@-rm *.exe *.dll *.mdb mods/**/*.dll mods/**/*.mdb *.resources
|
||||
|
||||
distclean: clean
|
||||
|
||||
CORE = fileformats rcg rgl rnull game editor utility winlaunch
|
||||
CORE = fileformats gl game editor
|
||||
|
||||
install: all
|
||||
@-echo "Installing OpenRA to $(INSTALL_DIR)"
|
||||
@@ -156,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
|
||||
@@ -166,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."
|
||||
@@ -198,16 +164,8 @@ filex: $(filex_TARGET)
|
||||
tsbuild: OpenRA.TilesetBuilder.Form1.resources $(tsbuild_TARGET)
|
||||
OpenRA.TilesetBuilder.Form1.resources:
|
||||
resgen2 OpenRA.TilesetBuilder/Form1.resx OpenRA.TilesetBuilder.Form1.resources 1> /dev/null
|
||||
|
||||
utility: $(utility_TARGET)
|
||||
winlaunch: OpenRA.Launcher.MainForm.resources OpenRA.Launcher.InstallPackagesDialog.resources \
|
||||
OpenRA.Launcher.ConfigureModsDialog.resources $(winlaunch_TARGET)
|
||||
OpenRA.Launcher.MainForm.resources:
|
||||
resgen2 OpenRA.Launcher/MainForm.resx OpenRA.Launcher.MainForm.resources 1> /dev/null
|
||||
OpenRA.Launcher.InstallPackagesDialog.resources:
|
||||
resgen2 OpenRA.Launcher/InstallPackagesDialog.resx OpenRA.Launcher.InstallPackagesDialog.resources 1> /dev/null
|
||||
OpenRA.Launcher.ConfigureModsDialog.resources:
|
||||
resgen2 OpenRA.Launcher/ConfigureModsDialog.resx OpenRA.Launcher.ConfigureModsDialog.resources 1> /dev/null
|
||||
tools: editor ralint seqed filex tsbuild
|
||||
all: game tools
|
||||
|
||||
fixheader: packaging/fixheader.cs
|
||||
@$(CSC) packaging/fixheader.cs $(CSFLAGS) -out:fixheader.exe -t:exe $(COMMON_LIBS:%=-r:%)
|
||||
|
||||
@@ -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
877
OpenRA.Editor/Form1.Designer.cs
generated
Executable file → Normal 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
18
OpenRA.Editor/Form1.cs
Executable file → Normal 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
6
OpenRA.Editor/Form1.resx
Executable file → Normal 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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -13,6 +13,8 @@
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ApplicationIcon>OpenRA.Editor.Icon.ico</ApplicationIcon>
|
||||
<StartupObject>
|
||||
</StartupObject>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
45
OpenRA.FileFormats/CompressedPackage.cs
Normal file
45
OpenRA.FileFormats/CompressedPackage.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
#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.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class CompressedPackage : IFolder
|
||||
{
|
||||
readonly uint[] hashes;
|
||||
readonly Stream s;
|
||||
readonly ZipPackage pkg;
|
||||
|
||||
public CompressedPackage(string filename)
|
||||
{
|
||||
s = FileSystem.Open(filename);
|
||||
pkg = (ZipPackage)ZipPackage.Open(s, FileMode.Open);
|
||||
hashes = pkg.GetParts()
|
||||
.Select(p => PackageEntry.HashFilename(p.Uri.LocalPath)).ToArray();
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return pkg.GetPart(new Uri(filename)).GetStream(FileMode.Open);
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes() { return hashes; }
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return hashes.Contains(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1,274 +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.
|
||||
*
|
||||
* This file is based on the blast routines (version 1.1 by Mark Adler)
|
||||
* included in zlib/contrib
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public static class Blast
|
||||
{
|
||||
public static readonly int MAXBITS = 13; // maximum code length
|
||||
public static readonly int MAXWIN = 4096; // maximum window size
|
||||
|
||||
static byte[] litlen = new byte[] {
|
||||
11, 124, 8, 7, 28, 7, 188, 13, 76, 4,
|
||||
10, 8, 12, 10, 12, 10, 8, 23, 8, 9,
|
||||
7, 6, 7, 8, 7, 6, 55, 8, 23, 24,
|
||||
12, 11, 7, 9, 11, 12, 6, 7, 22, 5,
|
||||
7, 24, 6, 11, 9, 6, 7, 22, 7, 11,
|
||||
38, 7, 9, 8, 25, 11, 8, 11, 9, 12,
|
||||
8, 12, 5, 38, 5, 38, 5, 11, 7, 5,
|
||||
6, 21, 6, 10, 53, 8, 7, 24, 10, 27,
|
||||
44, 253, 253, 253, 252, 252, 252, 13, 12, 45,
|
||||
12, 45, 12, 61, 12, 45, 44, 173
|
||||
};
|
||||
|
||||
// bit lengths of length codes 0..15
|
||||
static byte[] lenlen = new byte[] { 2, 35, 36, 53, 38, 23 };
|
||||
|
||||
// bit lengths of distance codes 0..63
|
||||
static byte[] distlen = new byte[] { 2, 20, 53, 230, 247, 151, 248 };
|
||||
|
||||
// base for length codes
|
||||
static short[] lengthbase = new short[] {
|
||||
3, 2, 4, 5, 6, 7, 8, 9, 10, 12,
|
||||
16, 24, 40, 72, 136, 264
|
||||
};
|
||||
|
||||
// extra bits for length codes
|
||||
static byte[] extra = new byte[] {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
|
||||
3, 4, 5, 6, 7, 8
|
||||
};
|
||||
|
||||
static Huffman litcode = new Huffman(litlen, litlen.Length, 256);
|
||||
static Huffman lencode = new Huffman(lenlen, lenlen.Length, 16);
|
||||
static Huffman distcode = new Huffman(distlen, distlen.Length, 64);
|
||||
|
||||
// Decode PKWare Compression Library stream.
|
||||
public static byte[] Decompress(byte[] src)
|
||||
{
|
||||
BitReader br = new BitReader(src);
|
||||
|
||||
// Are literals coded?
|
||||
int coded = br.ReadBits(8);
|
||||
|
||||
if (coded < 0 || coded > 1)
|
||||
throw new NotImplementedException("Invalid datastream");
|
||||
bool EncodedLiterals = (coded == 1);
|
||||
|
||||
// log2(dictionary size) - 6
|
||||
int dict = br.ReadBits(8);
|
||||
if (dict < 4 || dict > 6)
|
||||
throw new InvalidDataException("Invalid dictionary size");
|
||||
|
||||
// output state
|
||||
ushort next = 0; // index of next write location in out[]
|
||||
bool first = true; // true to check distances (for first 4K)
|
||||
byte[] outBuffer = new byte[MAXWIN]; // output buffer and sliding window
|
||||
var ms = new MemoryStream();
|
||||
|
||||
// decode literals and length/distance pairs
|
||||
do
|
||||
{
|
||||
// length/distance pair
|
||||
if (br.ReadBits(1) == 1)
|
||||
{
|
||||
// Length
|
||||
int symbol = Decode(lencode, br);
|
||||
int len = lengthbase[symbol] + br.ReadBits(extra[symbol]);
|
||||
if (len == 519) // Magic number for "done"
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
// Distance
|
||||
symbol = len == 2 ? 2 : dict;
|
||||
int dist = Decode(distcode, br) << symbol;
|
||||
dist += br.ReadBits(symbol);
|
||||
dist++;
|
||||
|
||||
if (first && dist > next)
|
||||
throw new InvalidDataException("Attempt to jump before data");
|
||||
|
||||
// copy length bytes from distance bytes back
|
||||
do
|
||||
{
|
||||
int dest = next;
|
||||
int source = dest - dist;
|
||||
|
||||
int copy = MAXWIN;
|
||||
if (next < dist)
|
||||
{
|
||||
source += copy;
|
||||
copy = dist;
|
||||
}
|
||||
|
||||
copy -= next;
|
||||
if (copy > len)
|
||||
copy = len;
|
||||
|
||||
len -= copy;
|
||||
next += (ushort)copy;
|
||||
Array.Copy(outBuffer, source, outBuffer, dest, copy);
|
||||
|
||||
// Flush window to outstream
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
}
|
||||
} while (len != 0);
|
||||
}
|
||||
else // literal value
|
||||
{
|
||||
int symbol = EncodedLiterals ? Decode(litcode, br) : br.ReadBits(8);
|
||||
outBuffer[next++] = (byte)symbol;
|
||||
if (next == MAXWIN)
|
||||
{
|
||||
for (int i = 0; i < next; i++)
|
||||
ms.WriteByte(outBuffer[i]);
|
||||
next = 0;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
// Decode a code using huffman table h.
|
||||
private static int Decode(Huffman h, BitReader br)
|
||||
{
|
||||
int code = 0; // len bits being decoded
|
||||
int first = 0; // first code of length len
|
||||
int index = 0; // index of first code of length len in symbol table
|
||||
short next = 1;
|
||||
while (true)
|
||||
{
|
||||
code |= br.ReadBits(1) ^ 1; // invert code
|
||||
int count = h.Count[next++];
|
||||
if (code < first + count)
|
||||
return h.Symbol[index + (code - first)];
|
||||
|
||||
index += count;
|
||||
first += count;
|
||||
first <<= 1;
|
||||
code <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BitReader
|
||||
{
|
||||
readonly byte[] src;
|
||||
int offset = 0;
|
||||
int bitBuffer = 0;
|
||||
int bitCount = 0;
|
||||
|
||||
public BitReader(byte[] src)
|
||||
{
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
public int ReadBits(int count)
|
||||
{
|
||||
int ret = 0;
|
||||
int filled = 0;
|
||||
while (filled < count)
|
||||
{
|
||||
if (bitCount == 0)
|
||||
{
|
||||
bitBuffer = src[offset++];
|
||||
bitCount = 8;
|
||||
}
|
||||
|
||||
ret |= (bitBuffer & 1) << filled;
|
||||
bitBuffer >>= 1;
|
||||
bitCount--;
|
||||
filled++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a list of repeated code lengths rep[0..n-1], where each byte is a
|
||||
* count (high four bits + 1) and a code length (low four bits), generate the
|
||||
* list of code lengths. This compaction reduces the size of the object code.
|
||||
* Then given the list of code lengths length[0..n-1] representing a canonical
|
||||
* Huffman code for n symbols, construct the tables required to decode those
|
||||
* codes. Those tables are the number of codes of each length, and the symbols
|
||||
* sorted by length, retaining their original order within each length.
|
||||
*/
|
||||
class Huffman
|
||||
{
|
||||
public short[] Count; // number of symbols of each length
|
||||
public short[] Symbol; // canonically ordered symbols
|
||||
|
||||
public Huffman(byte[] rep, int n, short SymbolCount)
|
||||
{
|
||||
short[] length = new short[256]; // code lengths
|
||||
int s = 0; // current symbol
|
||||
|
||||
// convert compact repeat counts into symbol bit length list
|
||||
foreach (byte code in rep)
|
||||
{
|
||||
int num = (code >> 4) + 1; // Number of codes (top four bits plus 1)
|
||||
byte len = (byte)(code & 15); // Code length (low four bits)
|
||||
do
|
||||
{
|
||||
length[s++] = len;
|
||||
} while (--num > 0);
|
||||
}
|
||||
n = s;
|
||||
|
||||
// count number of codes of each length
|
||||
Count = new short[Blast.MAXBITS + 1];
|
||||
for (int i = 0; i < n; i++)
|
||||
Count[length[i]]++;
|
||||
|
||||
// no codes!
|
||||
if (Count[0] == n)
|
||||
return;
|
||||
|
||||
// check for an over-subscribed or incomplete set of lengths
|
||||
int left = 1; // one possible code of zero length
|
||||
for (int len = 1; len <= Blast.MAXBITS; len++)
|
||||
{
|
||||
left <<= 1;
|
||||
// one more bit, double codes left
|
||||
left -= Count[len];
|
||||
// deduct count from possible codes
|
||||
if (left < 0)
|
||||
throw new InvalidDataException ("over subscribed code set");
|
||||
}
|
||||
|
||||
// generate offsets into symbol table for each length for sorting
|
||||
short[] offs = new short[Blast.MAXBITS + 1];
|
||||
for (int len = 1; len < Blast.MAXBITS; len++)
|
||||
offs[len + 1] = (short)(offs[len] + Count[len]);
|
||||
|
||||
// put symbols in table sorted by length, by symbol order within each length
|
||||
Symbol = new short[SymbolCount];
|
||||
for (short i = 0; i < n; i++)
|
||||
if (length[i] != 0)
|
||||
Symbol[offs[length[i]]++] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
@@ -34,22 +33,19 @@ namespace OpenRA.FileFormats
|
||||
}
|
||||
}
|
||||
|
||||
static int order = 0;
|
||||
|
||||
static IFolder OpenPackage(string filename)
|
||||
{
|
||||
if (filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new MixFile(filename, order++);
|
||||
else if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new ZipFile(filename, order++);
|
||||
else if (filename.EndsWith(".Z", StringComparison.InvariantCultureIgnoreCase))
|
||||
return new InstallShieldPackage(filename, order++);
|
||||
if (filename.EndsWith(".mix"))
|
||||
return new Package(filename);
|
||||
else if (filename.EndsWith(".zip"))
|
||||
return new CompressedPackage(filename);
|
||||
else
|
||||
return new Folder(filename, order++);
|
||||
return new Folder(filename);
|
||||
}
|
||||
|
||||
public static void Mount(string name)
|
||||
{
|
||||
name = name.ToLowerInvariant();
|
||||
var optional = name.StartsWith("~");
|
||||
if (optional) name = name.Substring(1);
|
||||
|
||||
@@ -68,16 +64,6 @@ namespace OpenRA.FileFormats
|
||||
allFiles = new Cache<uint, List<IFolder>>( _ => new List<IFolder>() );
|
||||
}
|
||||
|
||||
public static bool Unmount(IFolder mount)
|
||||
{
|
||||
return (mountedFolders.RemoveAll(f => f == mount) > 0);
|
||||
}
|
||||
|
||||
public static void Mount(IFolder mount)
|
||||
{
|
||||
if (!mountedFolders.Contains(mount)) mountedFolders.Add(mount);
|
||||
}
|
||||
|
||||
public static void LoadFromManifest( Manifest manifest )
|
||||
{
|
||||
UnmountAll();
|
||||
@@ -87,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;
|
||||
}
|
||||
|
||||
@@ -107,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 );
|
||||
}
|
||||
@@ -1,121 +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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class InstallShieldPackage : IFolder
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index = new Dictionary<uint, PackageEntry>();
|
||||
readonly Stream s;
|
||||
readonly long dataStart = 255;
|
||||
int priority;
|
||||
|
||||
public InstallShieldPackage(string filename, int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
s = FileSystem.Open(filename);
|
||||
|
||||
// Parse package header
|
||||
BinaryReader reader = new BinaryReader(s);
|
||||
uint signature = reader.ReadUInt32();
|
||||
if (signature != 0x8C655D13)
|
||||
throw new InvalidDataException("Not an Installshield package");
|
||||
|
||||
reader.ReadBytes(8);
|
||||
/*var FileCount = */reader.ReadUInt16();
|
||||
reader.ReadBytes(4);
|
||||
/*var ArchiveSize = */reader.ReadUInt32();
|
||||
reader.ReadBytes(19);
|
||||
var TOCAddress = reader.ReadInt32();
|
||||
reader.ReadBytes(4);
|
||||
var DirCount = reader.ReadUInt16();
|
||||
|
||||
// Parse the directory list
|
||||
s.Seek(TOCAddress, SeekOrigin.Begin);
|
||||
BinaryReader TOCreader = new BinaryReader(s);
|
||||
for (var i = 0; i < DirCount; i++)
|
||||
ParseDirectory(TOCreader);
|
||||
}
|
||||
|
||||
void ParseDirectory(BinaryReader reader)
|
||||
{
|
||||
// Parse directory header
|
||||
var FileCount = reader.ReadUInt16();
|
||||
var ChunkSize = reader.ReadUInt16();
|
||||
var NameLength = reader.ReadUInt16();
|
||||
reader.ReadChars(NameLength); //var DirName = new String(reader.ReadChars(NameLength));
|
||||
|
||||
// Skip to the end of the chunk
|
||||
reader.ReadBytes(ChunkSize - NameLength - 6);
|
||||
|
||||
// Parse files
|
||||
for (var i = 0; i < FileCount; i++)
|
||||
ParseFile(reader);
|
||||
}
|
||||
|
||||
uint AccumulatedData = 0;
|
||||
void ParseFile(BinaryReader reader)
|
||||
{
|
||||
reader.ReadBytes(7);
|
||||
var CompressedSize = reader.ReadUInt32();
|
||||
reader.ReadBytes(12);
|
||||
var ChunkSize = reader.ReadUInt16();
|
||||
reader.ReadBytes(4);
|
||||
var NameLength = reader.ReadByte();
|
||||
var FileName = new String(reader.ReadChars(NameLength));
|
||||
|
||||
var hash = PackageEntry.HashFilename(FileName);
|
||||
index.Add(hash, new PackageEntry(hash,AccumulatedData, CompressedSize));
|
||||
AccumulatedData += CompressedSize;
|
||||
|
||||
// Skip to the end of the chunk
|
||||
reader.ReadBytes(ChunkSize - NameLength - 30);
|
||||
}
|
||||
|
||||
public Stream GetContent(uint hash)
|
||||
{
|
||||
PackageEntry e;
|
||||
if (!index.TryGetValue(hash, out e))
|
||||
return null;
|
||||
|
||||
s.Seek( dataStart + e.Offset, SeekOrigin.Begin );
|
||||
byte[] data = new byte[ e.Length ];
|
||||
s.Read( data, 0, (int)e.Length );
|
||||
|
||||
return new MemoryStream(Blast.Decompress(data));
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return GetContent(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
return index.Keys;
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return index.ContainsKey(PackageEntry.HashFilename(filename));
|
||||
}
|
||||
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 2000 + priority; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using SZipFile = ICSharpCode.SharpZipLib.Zip.ZipFile;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.FileFormats
|
||||
{
|
||||
public class ZipFile : IFolder
|
||||
{
|
||||
readonly SZipFile pkg;
|
||||
int priority;
|
||||
|
||||
public ZipFile(string filename, int priority)
|
||||
{
|
||||
this.priority = priority;
|
||||
pkg = new SZipFile(File.OpenRead(filename));
|
||||
}
|
||||
|
||||
public Stream GetContent(string filename)
|
||||
{
|
||||
return pkg.GetInputStream(pkg.GetEntry(filename));
|
||||
}
|
||||
|
||||
public IEnumerable<uint> AllFileHashes()
|
||||
{
|
||||
foreach(ZipEntry entry in pkg)
|
||||
yield return PackageEntry.HashFilename(entry.Name);
|
||||
}
|
||||
|
||||
public bool Exists(string filename)
|
||||
{
|
||||
return pkg.GetEntry(filename) != null;
|
||||
}
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get { return 500 + priority; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,12 +33,14 @@ namespace OpenRA.FileFormats.Graphics
|
||||
IIndexBuffer CreateIndexBuffer( int length );
|
||||
ITexture CreateTexture( Bitmap bitmap );
|
||||
ITexture CreateTexture();
|
||||
IShader CreateShader( string name );
|
||||
IShader CreateShader( Stream stream );
|
||||
|
||||
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 );
|
||||
|
||||
@@ -18,15 +18,15 @@ namespace OpenRA.FileFormats
|
||||
public class Manifest
|
||||
{
|
||||
public readonly string[]
|
||||
Mods, Folders, Packages, Rules, ServerTraits,
|
||||
Folders, Packages, Rules,
|
||||
Sequences, Cursors, Chrome, Assemblies, ChromeLayout,
|
||||
Weapons, Voices, Music, Movies, TileSets;
|
||||
|
||||
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);
|
||||
@@ -35,7 +35,6 @@ namespace OpenRA.FileFormats
|
||||
Folders = YamlList(yaml, "Folders");
|
||||
Packages = YamlList(yaml, "Packages");
|
||||
Rules = YamlList(yaml, "Rules");
|
||||
ServerTraits = YamlList(yaml, "ServerTraits");
|
||||
Sequences = YamlList(yaml, "Sequences");
|
||||
Cursors = YamlList(yaml, "Cursors");
|
||||
Chrome = YamlList(yaml, "Chrome");
|
||||
|
||||
@@ -17,10 +17,10 @@ namespace OpenRA.FileFormats
|
||||
{
|
||||
public class MapStub
|
||||
{
|
||||
public IFolder Container { 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,15 +37,14 @@ 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 container)
|
||||
|
||||
public MapStub(IFolder package)
|
||||
{
|
||||
Container = container;
|
||||
var yaml = MiniYaml.FromStream(Container.GetContent("map.yaml"));
|
||||
Package = package;
|
||||
var yaml = MiniYaml.FromStream(Package.GetContent("map.yaml"));
|
||||
FieldLoader.Load( this, new MiniYaml( null, yaml ) );
|
||||
|
||||
Uid = Container.GetContent("map.uid").ReadAllText();
|
||||
Uid = Package.GetContent("map.uid").ReadAllText();
|
||||
}
|
||||
|
||||
static object LoadWaypoints( MiniYaml y )
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<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>
|
||||
@@ -54,22 +53,20 @@
|
||||
<Reference Include="WindowsBase">
|
||||
<RequiredTargetFramework>3.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\thirdparty\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Evaluator.cs" />
|
||||
<Compile Include="Exts.cs" />
|
||||
<Compile Include="FieldLoader.cs" />
|
||||
<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" />
|
||||
<Compile Include="Palette.cs" />
|
||||
<Compile Include="PlayerColorRemap.cs" />
|
||||
<Compile Include="Primitives\DisposableAction.cs" />
|
||||
@@ -101,14 +98,8 @@
|
||||
<Compile Include="Map\MapStub.cs" />
|
||||
<Compile Include="Map\SmudgeReference.cs" />
|
||||
<Compile Include="Map\PlayerReference.cs" />
|
||||
<Compile Include="CompressedPackage.cs" />
|
||||
<Compile Include="Graphics\VqaReader.cs" />
|
||||
<Compile Include="Filesystem\MixFile.cs" />
|
||||
<Compile Include="Filesystem\FileSystem.cs" />
|
||||
<Compile Include="Filesystem\Folder.cs" />
|
||||
<Compile Include="Filesystem\PackageWriter.cs" />
|
||||
<Compile Include="Filesystem\InstallShieldPackage.cs" />
|
||||
<Compile Include="FileFormats\Blast.cs" />
|
||||
<Compile Include="Filesystem\ZipFile.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
@@ -118,7 +109,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<ItemGroup>
|
||||
<Folder Include="Filesystem\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -20,20 +20,17 @@ namespace OpenRA.FileFormats
|
||||
Stream GetContent(string filename);
|
||||
bool Exists(string filename);
|
||||
IEnumerable<uint> AllFileHashes();
|
||||
int Priority { get; }
|
||||
}
|
||||
|
||||
public class MixFile : IFolder
|
||||
public class Package : IFolder
|
||||
{
|
||||
readonly Dictionary<uint, PackageEntry> index;
|
||||
readonly bool isRmix, isEncrypted;
|
||||
readonly long dataStart;
|
||||
readonly Stream s;
|
||||
int priority;
|
||||
|
||||
public MixFile(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]
|
||||
@@ -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
31
OpenRA.FileFormats/PlayerColorRemap.cs
Executable file → Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ); }
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
|
||||
@@ -61,18 +61,35 @@ 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;
|
||||
});
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
if (currentActivity == null)
|
||||
foreach (var ni in TraitsImplementing<INotifyIdle>())
|
||||
ni.TickIdle(this);
|
||||
var wasIdle = currentActivity is Idle;
|
||||
while (currentActivity != null)
|
||||
{
|
||||
var a = currentActivity;
|
||||
|
||||
var sw = new Stopwatch();
|
||||
currentActivity = a.Tick(this) ?? new Idle();
|
||||
var dt = sw.ElapsedTime();
|
||||
if(dt > Game.Settings.Debug.LongTickThreshold)
|
||||
Log.Write("perf", "[{2}] Activity: {0} ({1:0.000} ms)", a, dt * 1000, Game.LocalTick);
|
||||
|
||||
if (a == currentActivity) break;
|
||||
|
||||
currentActivity = Util.RunActivity( this, currentActivity );
|
||||
if (currentActivity is Idle)
|
||||
{
|
||||
if (!wasIdle)
|
||||
foreach (var ni in TraitsImplementing<INotifyIdle>())
|
||||
ni.Idle(this);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsIdle
|
||||
@@ -93,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)
|
||||
@@ -114,14 +125,7 @@ namespace OpenRA
|
||||
return new RectangleF(loc.X, loc.Y, size.X, size.Y);
|
||||
}
|
||||
|
||||
public bool IsInWorld { get; internal set; }
|
||||
|
||||
public void QueueActivity( bool queued, IActivity nextActivity )
|
||||
{
|
||||
if( !queued )
|
||||
CancelActivity();
|
||||
QueueActivity( nextActivity );
|
||||
}
|
||||
public bool IsInWorld { get; internal set; }
|
||||
|
||||
public void QueueActivity( IActivity nextActivity )
|
||||
{
|
||||
@@ -190,8 +194,6 @@ namespace OpenRA
|
||||
{
|
||||
World.AddFrameEndTask( w =>
|
||||
{
|
||||
if (Destroyed) return;
|
||||
|
||||
World.Remove( this );
|
||||
World.traitDict.RemoveActor( this );
|
||||
Destroyed = true;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Support;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
|
||||
398
OpenRA.Game/Game.cs
Executable file → Normal file
398
OpenRA.Game/Game.cs
Executable file → Normal 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,36 +30,45 @@ 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;
|
||||
|
||||
internal static OrderManager orderManager;
|
||||
static Server.Server server;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static void JoinServer(string host, int port)
|
||||
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()
|
||||
@@ -71,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));
|
||||
}
|
||||
|
||||
@@ -112,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
|
||||
@@ -186,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 );
|
||||
@@ -213,29 +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 );
|
||||
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);
|
||||
// TODO: unhardcode this
|
||||
modData.WidgetLoader.LoadWidget( new Dictionary<string,object>(), Widget.RootWidget, "PERF_BG" );
|
||||
|
||||
Game.BeforeGameStart += () => Widget.OpenWindow("INGAME_ROOT");
|
||||
|
||||
Game.ConnectionStateChanged += () =>
|
||||
{
|
||||
Widget.CloseWindow();
|
||||
switch( Game.orderManager.Connection.ConnectionState )
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
modData.WidgetLoader.LoadWidget( Widget.RootWidget, "PERF_BG" );
|
||||
Widget.OpenWindow("MAINMENU_BG");
|
||||
Game.orderManager.LastTickTime = Environment.TickCount;
|
||||
|
||||
ResetTimer();
|
||||
}
|
||||
|
||||
@@ -243,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 != null)
|
||||
server.Shutdown();
|
||||
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
CreateAndJoinServer( Settings, map );
|
||||
else
|
||||
JoinServer(host, port);
|
||||
}
|
||||
|
||||
public static void CreateAndJoinServer(Settings settings, string map)
|
||||
{
|
||||
server = new Server.Server(modData, settings, map);
|
||||
JoinServer(IPAddress.Loopback.ToString(), settings.Server.ListenPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
5
OpenRA.Mods.RA/Buildings/FootprintUtils.cs → OpenRA.Game/GameRules/Footprint.cs
Executable file → Normal file
5
OpenRA.Mods.RA/Buildings/FootprintUtils.cs → OpenRA.Game/GameRules/Footprint.cs
Executable file → Normal 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 )
|
||||
{
|
||||
@@ -27,10 +27,9 @@ namespace OpenRA
|
||||
|
||||
public static void LoadRules(Manifest m, Map map)
|
||||
{
|
||||
// Added support to extend the list of rules (add it to m.LocalRules)
|
||||
Info = LoadYamlRules(m.Rules, map.Rules, (k, y) => new ActorInfo(k.Key.ToLowerInvariant(), k.Value, y));
|
||||
Weapons = LoadYamlRules(m.Weapons, map.Weapons, (k, _) => new WeaponInfo(k.Key.ToLowerInvariant(), k.Value));
|
||||
Voices = LoadYamlRules(m.Voices, map.Voices, (k, _) => new VoiceInfo(k.Value));
|
||||
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));
|
||||
Movies = LoadYamlRules(m.Movies, new List<MiniYamlNode>(), (k, v) => k.Value.Value);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.FileFormats.Graphics;
|
||||
using OpenRA.Server;
|
||||
|
||||
namespace OpenRA.GameRules
|
||||
{
|
||||
@@ -31,18 +30,17 @@ namespace OpenRA.GameRules
|
||||
|
||||
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 string Renderer = "Gl";
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -68,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;
|
||||
@@ -112,12 +107,12 @@ namespace OpenRA.GameRules
|
||||
|
||||
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)
|
||||
@@ -129,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;
|
||||
@@ -139,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);
|
||||
}
|
||||
|
||||
@@ -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) ));
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
|
||||
Sprite[] LoadCursors(string filename)
|
||||
{
|
||||
{
|
||||
try
|
||||
{
|
||||
var shp = new Dune2ShpReader(FileSystem.OpenWithExts(filename, exts));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -46,10 +46,10 @@ namespace OpenRA.Graphics
|
||||
|
||||
public Renderer()
|
||||
{
|
||||
SpriteShader = device.CreateShader("world-shp");
|
||||
LineShader = device.CreateShader("world-line");
|
||||
RgbaSpriteShader = device.CreateShader("chrome-rgba");
|
||||
WorldSpriteShader = device.CreateShader("chrome-shp");
|
||||
SpriteShader = device.CreateShader(FileSystem.Open("shaders/world-shp.fx"));
|
||||
LineShader = device.CreateShader(FileSystem.Open("shaders/line.fx"));
|
||||
RgbaSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-rgba.fx"));
|
||||
WorldSpriteShader = device.CreateShader(FileSystem.Open("shaders/chrome-shp.fx"));
|
||||
|
||||
SpriteRenderer = new SpriteRenderer( this, SpriteShader );
|
||||
RgbaSpriteRenderer = new SpriteRenderer( this, RgbaSpriteShader );
|
||||
@@ -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,14 +135,14 @@ namespace OpenRA.Graphics
|
||||
internal static void Initialize( OpenRA.FileFormats.Graphics.WindowMode windowMode )
|
||||
{
|
||||
var resolution = GetResolution( windowMode );
|
||||
device = CreateDevice( Assembly.LoadFile( Path.GetFullPath( "OpenRA.Renderer.{0}.dll".F(Game.Settings.Graphics.Renderer) ) ), 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)
|
||||
{
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var desktopResolution = Screen.PrimaryScreen.Bounds.Size;
|
||||
var customSize = (windowmode == WindowMode.Windowed) ? Game.Settings.Graphics.WindowedSize : Game.Settings.Graphics.FullscreenSize;
|
||||
|
||||
|
||||
if (customSize.X > 0 && customSize.Y > 0)
|
||||
{
|
||||
desktopResolution.Width = customSize.X;
|
||||
|
||||
@@ -21,13 +21,15 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
static Dictionary<string, Dictionary<string, Sequence>> units;
|
||||
|
||||
public static void Initialize(string[] sequenceFiles, List<MiniYamlNode> sequenceNodes)
|
||||
public static void Initialize(string[] sequenceFiles)
|
||||
{
|
||||
units = new Dictionary<string, Dictionary<string, Sequence>>();
|
||||
if (sequenceFiles.Length == 0)
|
||||
return;
|
||||
|
||||
var sequences = sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(sequenceNodes, MiniYaml.Merge);
|
||||
var sequences = sequenceFiles
|
||||
.Select(s => MiniYaml.FromFile(s))
|
||||
.Aggregate(MiniYaml.Merge);
|
||||
|
||||
foreach (var s in sequences)
|
||||
LoadSequencesForUnit(s.Key, s.Value);
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
54
OpenRA.Game/Graphics/Viewport.cs
Executable file → Normal 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()
|
||||
|
||||
@@ -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>() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 };
|
||||
71
OpenRA.Game/Map.cs
Normal file → Executable file
71
OpenRA.Game/Map.cs
Normal file → Executable file
@@ -19,31 +19,34 @@ 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>();
|
||||
|
||||
// Rules overrides
|
||||
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
|
||||
|
||||
// Rules overrides
|
||||
public List<MiniYamlNode> Rules = new List<MiniYamlNode>();
|
||||
|
||||
// Sequences overrides
|
||||
public List<MiniYamlNode> Sequences = new List<MiniYamlNode>();
|
||||
|
||||
// Weapon overrides
|
||||
public List<MiniYamlNode> Weapons = new List<MiniYamlNode>();
|
||||
|
||||
// Voices overrides
|
||||
public List<MiniYamlNode> Voices = new List<MiniYamlNode>();
|
||||
|
||||
// Binary map data
|
||||
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;
|
||||
@@ -52,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()
|
||||
@@ -89,16 +95,21 @@ namespace OpenRA
|
||||
public int2 Location = int2.Zero;
|
||||
public string Owner = null;
|
||||
}
|
||||
|
||||
public Map(MapStub stub) : this(stub.Container) {}
|
||||
|
||||
public Map(IFolder package)
|
||||
: base(package)
|
||||
{
|
||||
var yaml = new MiniYaml( null, MiniYaml.FromStream( Container.GetContent( "map.yaml" ) ) );
|
||||
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.
|
||||
@@ -187,23 +198,13 @@ namespace OpenRA
|
||||
// Rules
|
||||
Rules = yaml.NodesDict["Rules"].Nodes;
|
||||
|
||||
// Sequences
|
||||
Sequences = (yaml.NodesDict.ContainsKey("Sequences")) ? yaml.NodesDict["Sequences"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
// Weapons
|
||||
Weapons = (yaml.NodesDict.ContainsKey("Weapons")) ? yaml.NodesDict["Weapons"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
// Voices
|
||||
Voices = (yaml.NodesDict.ContainsKey("Voices")) ? yaml.NodesDict["Voices"].Nodes : new List<MiniYamlNode>();
|
||||
|
||||
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
|
||||
Container = new Folder(filepath, 0);
|
||||
MapFormat = 3;
|
||||
|
||||
var root = new List<MiniYamlNode>();
|
||||
@@ -226,10 +227,7 @@ namespace OpenRA
|
||||
|
||||
root.Add( new MiniYamlNode( "Waypoints", MiniYaml.FromDictionary<string, int2>( Waypoints ) ) );
|
||||
root.Add( new MiniYamlNode( "Smudges", MiniYaml.FromList<SmudgeReference>( Smudges ) ) );
|
||||
root.Add(new MiniYamlNode("Rules", null, Rules));
|
||||
root.Add(new MiniYamlNode("Sequences", null, Sequences));
|
||||
root.Add(new MiniYamlNode("Weapons", null, Weapons));
|
||||
root.Add(new MiniYamlNode("Voices", null, Voices));
|
||||
root.Add( new MiniYamlNode( "Rules", null, Rules ) );
|
||||
|
||||
SaveBinaryData(Path.Combine(filepath, "map.bin"));
|
||||
root.WriteToFile(Path.Combine(filepath, "map.yaml"));
|
||||
@@ -254,7 +252,7 @@ namespace OpenRA
|
||||
|
||||
public void LoadBinaryData()
|
||||
{
|
||||
using (var dataStream = Container.GetContent("map.bin"))
|
||||
using (var dataStream = Package.GetContent("map.bin"))
|
||||
{
|
||||
if (ReadByte(dataStream) != 1)
|
||||
throw new InvalidDataException("Unknown binary map format");
|
||||
@@ -316,12 +314,17 @@ 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
|
||||
// Read the relevant data into a buffer
|
||||
var data = Container.GetContent("map.yaml").ReadAllBytes()
|
||||
.Concat(Container.GetContent("map.bin").ReadAllBytes()).ToArray();
|
||||
var data = Package.GetContent("map.yaml").ReadAllBytes()
|
||||
.Concat(Package.GetContent("map.bin").ReadAllBytes()).ToArray();
|
||||
|
||||
// Take the SHA1
|
||||
using (var csp = SHA1.Create())
|
||||
|
||||
@@ -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,13 +79,10 @@ namespace OpenRA
|
||||
.Where(p => Directory.Exists(p))
|
||||
.SelectMany(p => Directory.GetDirectories(p)).ToList();
|
||||
|
||||
return paths.Select(p => new MapStub(new Folder(p, int.MaxValue))).ToDictionary(m => m.Uid);
|
||||
return paths.Select(p => new MapStub(new Folder(p))).ToDictionary(m => m.Uid);
|
||||
}
|
||||
|
||||
string cachedTheatre = null;
|
||||
bool previousMapHadSequences = true;
|
||||
IFolder previousMapMount = null;
|
||||
|
||||
public Map PrepareMap(string uid)
|
||||
{
|
||||
LoadScreen.Display();
|
||||
@@ -63,32 +90,16 @@ namespace OpenRA
|
||||
if (!AvailableMaps.ContainsKey(uid))
|
||||
throw new InvalidDataException("Invalid map uid: {0}".F(uid));
|
||||
|
||||
var map = new Map(AvailableMaps[uid]);
|
||||
|
||||
// unload the previous map mount if we have one
|
||||
if (previousMapMount != null) FileSystem.Unmount(previousMapMount);
|
||||
|
||||
// Adds the map its container to the FileSystem
|
||||
// allowing the map to use custom assets
|
||||
// Container should have the lowest priority of all (ie int max)
|
||||
FileSystem.Mount(map.Container);
|
||||
|
||||
// Store a reference so we can unload it next time
|
||||
previousMapMount = map.Container;
|
||||
|
||||
var map = new Map(AvailableMaps[uid].Package);
|
||||
|
||||
Rules.LoadRules(Manifest, map);
|
||||
|
||||
if (map.Theater != cachedTheatre
|
||||
|| previousMapHadSequences || map.Sequences.Count > 0)
|
||||
if (map.Theater != cachedTheatre)
|
||||
{
|
||||
SpriteSheetBuilder.Initialize( Rules.TileSets[map.Tileset] );
|
||||
SequenceProvider.Initialize(Manifest.Sequences);
|
||||
CursorProvider.Initialize(Manifest.Cursors);
|
||||
SequenceProvider.Initialize(Manifest.Sequences, map.Sequences);
|
||||
cachedTheatre = map.Theater;
|
||||
}
|
||||
|
||||
previousMapHadSequences = map.Sequences.Count > 0;
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 } ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,20 +37,22 @@ namespace OpenRA
|
||||
this.Queued = queued;
|
||||
}
|
||||
|
||||
public Order(string orderString, Actor subject, bool queued)
|
||||
: this(orderString, subject, null, int2.Zero, null, queued) { }
|
||||
public Order(string orderString, Actor subject, Actor targetActor, bool queued)
|
||||
: this(orderString, subject, targetActor, int2.Zero, null, queued) { }
|
||||
public Order(string orderString, Actor subject)
|
||||
: this(orderString, subject, null, int2.Zero, null, false) { }
|
||||
public Order(string orderString, Actor subject, Actor targetActor)
|
||||
: this(orderString, subject, targetActor, int2.Zero, null, false) { }
|
||||
public Order(string orderString, Actor subject, int2 targetLocation)
|
||||
: this(orderString, subject, null, targetLocation, null, false) { }
|
||||
public Order(string orderString, Actor subject, int2 targetLocation, bool queued)
|
||||
: this(orderString, subject, null, targetLocation, null, queued) { }
|
||||
public Order(string orderString, Actor subject, string targetString, bool queued)
|
||||
: this(orderString, subject, null, int2.Zero, targetString, queued) { }
|
||||
public Order(string orderString, Actor subject, Actor targetActor, int2 targetLocation, bool queued)
|
||||
: this(orderString, subject, targetActor, targetLocation, null, queued) { }
|
||||
public Order(string orderString, Actor subject, Actor targetActor, string targetString, bool queued)
|
||||
: this(orderString, subject, targetActor, int2.Zero, targetString, queued) { }
|
||||
public Order(string orderString, Actor subject, int2 targetLocation, string targetString, bool queued)
|
||||
: this(orderString, subject, null, targetLocation, targetString, queued) { }
|
||||
public Order(string orderString, Actor subject, string targetString)
|
||||
: this(orderString, subject, null, int2.Zero, targetString, false) { }
|
||||
public Order(string orderString, Actor subject, Actor targetActor, int2 targetLocation)
|
||||
: this(orderString, subject, targetActor, targetLocation, null, false) { }
|
||||
public Order(string orderString, Actor subject, Actor targetActor, string targetString)
|
||||
: this(orderString, subject, targetActor, int2.Zero, targetString, false) { }
|
||||
public Order(string orderString, Actor subject, int2 targetLocation, string targetString)
|
||||
: this(orderString, subject, null, targetLocation, targetString, false) { }
|
||||
|
||||
public byte[] Serialize()
|
||||
{
|
||||
@@ -118,7 +120,7 @@ namespace OpenRA
|
||||
var name = r.ReadString();
|
||||
var data = r.ReadString();
|
||||
|
||||
return new Order( name, null, data, false ) { IsImmediate = true };
|
||||
return new Order( name, null, data ) { IsImmediate = true };
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -128,9 +130,9 @@ namespace OpenRA
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
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);
|
||||
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.Info.Name , TargetLocation, TargetString, IsImmediate, Player.PlayerName);
|
||||
}
|
||||
|
||||
static uint UIntFromActor(Actor a)
|
||||
@@ -162,32 +164,32 @@ namespace OpenRA
|
||||
// Now that Orders are resolved by individual Actors, these are weird; you unpack orders manually, but not pack them.
|
||||
public static Order Chat(string text)
|
||||
{
|
||||
return new Order("Chat", null, text, false) { IsImmediate = true };
|
||||
return new Order("Chat", null, text) { IsImmediate = true };
|
||||
}
|
||||
|
||||
public static Order TeamChat(string text)
|
||||
{
|
||||
return new Order("TeamChat", null, text, false) { IsImmediate = true };
|
||||
return new Order("TeamChat", null, text) { IsImmediate = true };
|
||||
}
|
||||
|
||||
public static Order Command(string text)
|
||||
{
|
||||
return new Order("Command", null, text, false) { IsImmediate = true };
|
||||
return new Order("Command", null, text) { IsImmediate = true };
|
||||
}
|
||||
|
||||
public static Order StartProduction(Actor subject, string item, int count)
|
||||
{
|
||||
return new Order("StartProduction", subject, new int2( count, 0 ), item, false );
|
||||
return new Order("StartProduction", subject, new int2( count, 0 ), item );
|
||||
}
|
||||
|
||||
public static Order PauseProduction(Actor subject, string item, bool pause)
|
||||
{
|
||||
return new Order("PauseProduction", subject, new int2( pause ? 1 : 0, 0 ), item, false);
|
||||
return new Order("PauseProduction", subject, new int2( pause ? 1 : 0, 0 ), item);
|
||||
}
|
||||
|
||||
public static Order CancelProduction(Actor subject, string item, int count)
|
||||
{
|
||||
return new Order("CancelProduction", subject, new int2( count, 0 ), item, false);
|
||||
return new Order("CancelProduction", subject, new int2( count, 0 ), item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,10 +30,10 @@ 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>())
|
||||
{
|
||||
var sync = Sync.CalculateSyncHash(a.Trait);
|
||||
if (sync != 0)
|
||||
|
||||
@@ -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
|
||||
@@ -16,137 +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)
|
||||
{
|
||||
if (!world.WorldActor.TraitsImplementing<IValidateOrder>().All(vo =>
|
||||
vo.OrderValidation(orderManager, world, clientId, order)))
|
||||
return;
|
||||
}
|
||||
/* todo: find the interactive player. */
|
||||
return world.players.Values.FirstOrDefault(p => p.ClientIndex == id);
|
||||
}
|
||||
|
||||
switch (order.OrderString)
|
||||
public static void ProcessOrder( 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;
|
||||
}
|
||||
|
||||
switch( order.OrderString )
|
||||
{
|
||||
case "Chat":
|
||||
{
|
||||
var client = FindClientById(clientId);
|
||||
if (client != null)
|
||||
{
|
||||
var client = orderManager.LobbyInfo.ClientWithIndex(clientId);
|
||||
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 (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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -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;
|
||||
|
||||
@@ -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,7 +210,8 @@
|
||||
<Compile Include="Traits\ActorStance.cs" />
|
||||
<Compile Include="Traits\Armor.cs" />
|
||||
<Compile Include="Graphics\CursorProvider.cs" />
|
||||
<Compile Include="Server\TraitInterfaces.cs" />
|
||||
<Compile Include="Traits\Player\TechTree.cs" />
|
||||
<Compile Include="Traits\Player\PowerManager.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRA.FileFormats\OpenRA.FileFormats.csproj">
|
||||
@@ -201,21 +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="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>
|
||||
@@ -239,9 +252,6 @@
|
||||
<ItemGroup>
|
||||
<Content Include="OpenRA.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="ServerTraits\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
|
||||
@@ -10,82 +10,41 @@
|
||||
|
||||
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;
|
||||
readonly MouseButton expectedButton;
|
||||
|
||||
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor, MouseButton button)
|
||||
{
|
||||
this.subjects = subjects;
|
||||
this.order = order;
|
||||
this.cursor = cursor;
|
||||
expectedButton = button;
|
||||
}
|
||||
|
||||
public GenericSelectTarget(IEnumerable<Actor> subjects, string order, string cursor)
|
||||
: this(subjects, order, cursor, MouseButton.Left)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GenericSelectTarget(Actor subject, string order, string cursor)
|
||||
: this(new Actor[] { subject }, order, cursor)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public GenericSelectTarget(Actor subject, string order, string cursor, MouseButton button)
|
||||
: this(new Actor[] { subject }, order, cursor, button)
|
||||
{
|
||||
|
||||
this.subject = subject;
|
||||
this.order = order;
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
|
||||
{
|
||||
if (mi.Button != expectedButton)
|
||||
if (mi.Button == MouseButton.Right)
|
||||
world.CancelInputMode();
|
||||
return OrderInner(world, xy, mi);
|
||||
}
|
||||
|
||||
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
|
||||
{
|
||||
if (mi.Button == expectedButton && 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, false);
|
||||
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"; }
|
||||
}
|
||||
@@ -97,9 +56,6 @@ namespace OpenRA.Orders
|
||||
public GenericSelectTargetWithBuilding(Actor subject, string order, string cursor)
|
||||
: base(subject, order, cursor) { }
|
||||
|
||||
public GenericSelectTargetWithBuilding(Actor subject, string order, string cursor, MouseButton button)
|
||||
: base(subject, order, cursor, button) { }
|
||||
|
||||
public override void Tick(World world)
|
||||
{
|
||||
var hasStructure = world.Queries.OwnedBy[world.LocalPlayer]
|
||||
@@ -110,4 +66,5 @@ namespace OpenRA.Orders
|
||||
world.CancelInputMode();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,125 +6,80 @@
|
||||
* 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()), false)
|
||||
;
|
||||
|
||||
foreach (var o in orders)
|
||||
yield return CheckSameOrder(o.iot, o.trait.IssueOrder(o.self, o.iot, o.target, mi.Modifiers.HasModifier(Modifiers.Shift)));
|
||||
}
|
||||
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 )
|
||||
{
|
||||
bool useSelect = false;
|
||||
|
||||
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();
|
||||
|
||||
|
||||
if (mi.Modifiers.HasModifier(Modifiers.Shift) || !world.Selection.Actors.Any())
|
||||
if (underCursor != null)
|
||||
useSelect = true;
|
||||
|
||||
.FirstOrDefault();
|
||||
|
||||
if( mi.Modifiers.HasModifier( Modifiers.Shift ) || !world.Selection.Actors.Any() )
|
||||
if( underCursor != null )
|
||||
return "select";
|
||||
|
||||
var orders = world.Selection.Actors
|
||||
.Select(a => OrderForUnit(a, xy, mi, underCursor))
|
||||
.Where(o => o != null)
|
||||
.ToArray();
|
||||
|
||||
if( orders.Length == 0 ) return (useSelect) ? "select" : "default";
|
||||
if( orders.Length == 0 ) return "default";
|
||||
|
||||
return orders[0].cursor ?? ((useSelect) ? "select" : "default");
|
||||
return orders[ 0 ].cursor ?? "default";
|
||||
}
|
||||
|
||||
static UnitOrderResult OrderForUnit( Actor self, int2 xy, MouseInput mi, Actor underCursor )
|
||||
@@ -157,9 +112,9 @@ namespace OpenRA.Orders
|
||||
|
||||
string cursor = null;
|
||||
if( underCursor != null )
|
||||
if (o.Order.CanTargetUnit(self, underCursor, mi.Modifiers.HasModifier(Modifiers.Ctrl), mi.Modifiers.HasModifier(Modifiers.Alt), mi.Modifiers.HasModifier(Modifiers.Shift), ref cursor))
|
||||
if( o.Order.CanTargetUnit( self, underCursor, mi.Modifiers.HasModifier( Modifiers.Ctrl ), mi.Modifiers.HasModifier( Modifiers.Alt ), ref cursor ) )
|
||||
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromActor( underCursor ) );
|
||||
if (o.Order.CanTargetLocation(self, xy, actorsAt, mi.Modifiers.HasModifier(Modifiers.Ctrl), mi.Modifiers.HasModifier(Modifiers.Alt), mi.Modifiers.HasModifier(Modifiers.Shift), ref cursor))
|
||||
if( o.Order.CanTargetLocation( self, xy, actorsAt, mi.Modifiers.HasModifier( Modifiers.Ctrl ), mi.Modifiers.HasModifier( Modifiers.Alt ), ref cursor ) )
|
||||
return new UnitOrderResult( self, o.Order, o.Trait, cursor, Target.FromCell( xy ) );
|
||||
}
|
||||
}
|
||||
|
||||
56
OpenRA.Mods.RA/Move/PathFinder.cs → OpenRA.Game/PathFinder.cs
Executable file → Normal file
56
OpenRA.Mods.RA/Move/PathFinder.cs → OpenRA.Game/PathFinder.cs
Executable file → Normal 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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ using System.Net.Sockets;
|
||||
|
||||
namespace OpenRA.Server
|
||||
{
|
||||
public class Connection
|
||||
class Connection
|
||||
{
|
||||
public Socket socket;
|
||||
public List<byte> data = new List<byte>();
|
||||
@@ -35,7 +35,7 @@ namespace OpenRA.Server
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
bool ReadDataInner( Server server )
|
||||
bool ReadDataInner()
|
||||
{
|
||||
var rx = new byte[1024];
|
||||
var len = 0;
|
||||
@@ -49,7 +49,7 @@ namespace OpenRA.Server
|
||||
else
|
||||
{
|
||||
if (len == 0)
|
||||
server.DropClient(this, null);
|
||||
Server.DropClient(this, null);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace OpenRA.Server
|
||||
catch (SocketException e)
|
||||
{
|
||||
if (e.SocketErrorCode == SocketError.WouldBlock) break;
|
||||
server.DropClient(this, e);
|
||||
Server.DropClient(this, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -65,9 +65,9 @@ namespace OpenRA.Server
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ReadData( Server server )
|
||||
public void ReadData()
|
||||
{
|
||||
if (ReadDataInner(server))
|
||||
if (ReadDataInner())
|
||||
while (data.Count >= ExpectLength)
|
||||
{
|
||||
var bytes = PopBytes(ExpectLength);
|
||||
@@ -82,16 +82,16 @@ namespace OpenRA.Server
|
||||
|
||||
case ReceiveState.Data:
|
||||
{
|
||||
server.DispatchOrders(this, Frame, bytes);
|
||||
Server.DispatchOrders(this, Frame, bytes);
|
||||
MostRecentFrame = Frame;
|
||||
ExpectLength = 8;
|
||||
State = ReceiveState.Header;
|
||||
|
||||
server.UpdateInFlightFrames(this);
|
||||
Server.UpdateInFlightFrames(this);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
public enum ReceiveState { Header, Data };
|
||||
enum ReceiveState { Header, Data };
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -23,54 +23,51 @@ using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Server
|
||||
{
|
||||
public class Server
|
||||
static class Server
|
||||
{
|
||||
public List<Connection> conns = new List<Connection>();
|
||||
TcpListener listener = null;
|
||||
Dictionary<int, List<Connection>> inFlightFrames
|
||||
static List<Connection> conns = new List<Connection>();
|
||||
static TcpListener listener = null;
|
||||
static Dictionary<int, List<Connection>> inFlightFrames
|
||||
= new Dictionary<int, List<Connection>>();
|
||||
|
||||
TypeDictionary ServerTraits = new TypeDictionary();
|
||||
public Session lobbyInfo;
|
||||
public bool GameStarted = false;
|
||||
public string Name;
|
||||
int randomSeed;
|
||||
static Session lobbyInfo;
|
||||
static bool GameStarted = false;
|
||||
static string Name;
|
||||
static int ExternalPort;
|
||||
static int randomSeed;
|
||||
|
||||
public ModData ModData;
|
||||
public Map Map;
|
||||
const int DownloadChunkInterval = 20000;
|
||||
const int DownloadChunkSize = 16384;
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
conns.Clear();
|
||||
GameStarted = false;
|
||||
foreach (var t in ServerTraits.WithInterface<INotifyServerShutdown>())
|
||||
t.ServerShutdown(this);
|
||||
|
||||
try { listener.Stop(); }
|
||||
catch { }
|
||||
}
|
||||
|
||||
public Server(ModData modData, Settings settings, string map)
|
||||
const int MasterPingInterval = 60 * 3; // 3 minutes. server has a 5 minute TTL for games, so give ourselves a bit
|
||||
// of leeway.
|
||||
static int lastPing = 0;
|
||||
static bool isInternetServer;
|
||||
static string masterServerUrl;
|
||||
static bool isInitialPing;
|
||||
static ModData ModData;
|
||||
static Map Map;
|
||||
|
||||
public static void ServerMain(ModData modData, Settings settings, string map)
|
||||
{
|
||||
Log.AddChannel("server", "server.log");
|
||||
|
||||
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;
|
||||
|
||||
foreach (var trait in modData.Manifest.ServerTraits)
|
||||
ServerTraits.Add( modData.ObjectCreator.CreateObject<ServerTrait>(trait) );
|
||||
|
||||
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;
|
||||
|
||||
foreach (var t in ServerTraits.WithInterface<INotifyServerStart>())
|
||||
t.ServerStarted(this);
|
||||
|
||||
LoadMap(); // populates the Session's slots, too.
|
||||
|
||||
Log.Write("server", "Initial mods: ");
|
||||
foreach( var m in lobbyInfo.GlobalSettings.Mods )
|
||||
Log.Write("server","- {0}", m);
|
||||
@@ -88,21 +85,24 @@ namespace OpenRA.Server
|
||||
|
||||
new Thread( _ =>
|
||||
{
|
||||
var timeout = ServerTraits.WithInterface<ITick>().Min(t => t.TickTimeout);
|
||||
for( ; ; )
|
||||
{
|
||||
var checkRead = new ArrayList();
|
||||
checkRead.Add( listener.Server );
|
||||
foreach( var c in conns ) checkRead.Add( c.socket );
|
||||
|
||||
Socket.Select( checkRead, null, null, timeout );
|
||||
Socket.Select( checkRead, null, null, MasterPingInterval * 10000 );
|
||||
|
||||
foreach( Socket s in checkRead )
|
||||
if( s == listener.Server ) AcceptConnection();
|
||||
else if (conns.Count > 0) conns.Single( c => c.socket == s ).ReadData( this );
|
||||
else conns.Single( c => c.socket == s ).ReadData();
|
||||
|
||||
foreach (var t in ServerTraits.WithInterface<ITick>())
|
||||
t.Tick(this);
|
||||
if (Environment.TickCount - lastPing > MasterPingInterval * 1000)
|
||||
PingMasterServer();
|
||||
else
|
||||
lock (masterServerMessages)
|
||||
while (masterServerMessages.Count > 0)
|
||||
SendChat(null, masterServerMessages.Dequeue());
|
||||
|
||||
if (conns.Count() == 0)
|
||||
{
|
||||
@@ -112,38 +112,65 @@ namespace OpenRA.Server
|
||||
}
|
||||
}
|
||||
} ) { IsBackground = true }.Start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
static Session.Slot MakeSlotFromPlayerReference(PlayerReference pr)
|
||||
{
|
||||
if (!pr.Playable) return null;
|
||||
return new Session.Slot
|
||||
{
|
||||
MapPlayer = pr.Name,
|
||||
Bot = null, /* todo: allow the map to specify a bot class? */
|
||||
Closed = false,
|
||||
};
|
||||
}
|
||||
|
||||
static void LoadMap()
|
||||
{
|
||||
Map = new Map(ModData.AvailableMaps[lobbyInfo.GlobalSettings.Map].Package);
|
||||
lobbyInfo.Slots = Map.Players
|
||||
.Select(p => MakeSlotFromPlayerReference(p.Value))
|
||||
.Where(s => s != null)
|
||||
.Select((s, i) => { s.Index = i; return s; })
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
int ChooseFreePlayerIndex()
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
void AcceptConnection()
|
||||
static int ChooseFreeSlot()
|
||||
{
|
||||
Socket newSocket = null;
|
||||
return lobbyInfo.Slots.First(s => !s.Closed && s.Bot == null
|
||||
&& !lobbyInfo.Clients.Any( c => c.Slot == s.Index )).Index;
|
||||
}
|
||||
|
||||
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 };
|
||||
static void AcceptConnection()
|
||||
{
|
||||
var newConn = new Connection { socket = listener.AcceptSocket() };
|
||||
try
|
||||
{
|
||||
if (GameStarted)
|
||||
@@ -163,13 +190,32 @@ namespace OpenRA.Server
|
||||
newConn.socket.Send(BitConverter.GetBytes(newConn.PlayerIndex));
|
||||
conns.Add(newConn);
|
||||
|
||||
foreach (var t in ServerTraits.WithInterface<IClientJoined>())
|
||||
t.ClientJoined(this, newConn);
|
||||
var defaults = new GameRules.PlayerSettings();
|
||||
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);
|
||||
|
||||
SendChat(newConn, "has joined the game.");
|
||||
|
||||
SyncLobbyInfo();
|
||||
}
|
||||
catch (Exception e) { DropClient(newConn, e); }
|
||||
}
|
||||
|
||||
public void UpdateInFlightFrames(Connection conn)
|
||||
public static void UpdateInFlightFrames(Connection conn)
|
||||
{
|
||||
if (conn.Frame != 0)
|
||||
{
|
||||
@@ -185,7 +231,7 @@ namespace OpenRA.Server
|
||||
}
|
||||
}
|
||||
|
||||
void DispatchOrdersToClient(Connection c, int client, int frame, byte[] data)
|
||||
static void DispatchOrdersToClient(Connection c, int client, int frame, byte[] data)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -199,7 +245,7 @@ namespace OpenRA.Server
|
||||
catch( Exception e ) { DropClient( c, e ); }
|
||||
}
|
||||
|
||||
public void DispatchOrders(Connection conn, int frame, byte[] data)
|
||||
public static void DispatchOrders(Connection conn, int frame, byte[] data)
|
||||
{
|
||||
if (frame == 0 && conn != null)
|
||||
InterpretServerOrders(conn, data);
|
||||
@@ -211,7 +257,7 @@ namespace OpenRA.Server
|
||||
}
|
||||
}
|
||||
|
||||
void InterpretServerOrders(Connection conn, byte[] data)
|
||||
static void InterpretServerOrders(Connection conn, byte[] data)
|
||||
{
|
||||
var ms = new MemoryStream(data);
|
||||
var br = new BinaryReader(ms);
|
||||
@@ -228,43 +274,294 @@ namespace OpenRA.Server
|
||||
catch (EndOfStreamException) { }
|
||||
catch (NotImplementedException) { }
|
||||
}
|
||||
|
||||
public void SendChatTo(Connection conn, string text)
|
||||
|
||||
static bool InterpretCommand(Connection conn, string cmd)
|
||||
{
|
||||
var dict = new Dictionary<string, Func<string, bool>>
|
||||
{
|
||||
{ "ready",
|
||||
s =>
|
||||
{
|
||||
// if we're downloading, we can't ready up.
|
||||
|
||||
var client = GetClient(conn);
|
||||
if (client.State == Session.ClientState.NotReady)
|
||||
client.State = Session.ClientState.Ready;
|
||||
else if (client.State == Session.ClientState.Ready)
|
||||
client.State = Session.ClientState.NotReady;
|
||||
|
||||
Log.Write("server", "Player @{0} is {1}",
|
||||
conn.socket.RemoteEndPoint, client.State);
|
||||
|
||||
SyncLobbyInfo();
|
||||
|
||||
if (conns.Count > 0 && conns.All(c => GetClient(c).State == Session.ClientState.Ready))
|
||||
InterpretCommand(conn, "startgame");
|
||||
|
||||
return true;
|
||||
}},
|
||||
{ "startgame",
|
||||
s =>
|
||||
{
|
||||
GameStarted = true;
|
||||
foreach( var c in conns )
|
||||
foreach( var d in conns )
|
||||
DispatchOrdersToClient( c, d.PlayerIndex, 0x7FFFFFFF, new byte[] { 0xBF } );
|
||||
|
||||
DispatchOrders(null, 0,
|
||||
new ServerOrder("StartGame", "").Serialize());
|
||||
|
||||
PingMasterServer();
|
||||
return true;
|
||||
}},
|
||||
{ "name",
|
||||
s =>
|
||||
{
|
||||
Log.Write("server", "Player@{0} is now known as {1}", conn.socket.RemoteEndPoint, s);
|
||||
GetClient(conn).Name = s;
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "lag",
|
||||
s =>
|
||||
{
|
||||
int lag;
|
||||
if (!int.TryParse(s, out lag)) { Log.Write("server", "Invalid order lag: {0}", s); return false; }
|
||||
|
||||
Log.Write("server", "Order lag is now {0} frames.", lag);
|
||||
|
||||
lobbyInfo.GlobalSettings.OrderLatency = lag;
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "race",
|
||||
s =>
|
||||
{
|
||||
GetClient(conn).Country = s;
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "team",
|
||||
s =>
|
||||
{
|
||||
int team;
|
||||
if (!int.TryParse(s, out team)) { Log.Write("server", "Invalid team: {0}", s ); return false; }
|
||||
|
||||
GetClient(conn).Team = team;
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "spawn",
|
||||
s =>
|
||||
{
|
||||
int spawnPoint;
|
||||
if (!int.TryParse(s, out spawnPoint) || spawnPoint < 0 || spawnPoint > 8) //TODO: SET properly!
|
||||
{
|
||||
Log.Write("server", "Invalid spawn point: {0}", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lobbyInfo.Clients.Where( c => c != GetClient(conn) ).Any( c => (c.SpawnPoint == spawnPoint) && (c.SpawnPoint != 0) ))
|
||||
{
|
||||
SendChatTo( conn, "You can't be at the same spawn point as another player" );
|
||||
return true;
|
||||
}
|
||||
|
||||
GetClient(conn).SpawnPoint = spawnPoint;
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "color",
|
||||
s =>
|
||||
{
|
||||
var c = s.Split(',').Select(cc => int.Parse(cc)).ToArray();
|
||||
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;
|
||||
}},
|
||||
{ "slot",
|
||||
s =>
|
||||
{
|
||||
int slot;
|
||||
if (!int.TryParse(s, out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null || slotData.Closed || slotData.Bot != null
|
||||
|| lobbyInfo.Clients.Any( c => c.Slot == slot ))
|
||||
return false;
|
||||
|
||||
GetClient(conn).Slot = slot;
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "slot_close",
|
||||
s =>
|
||||
{
|
||||
int slot;
|
||||
if (!int.TryParse(s, out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null)
|
||||
return false;
|
||||
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can alter slots" );
|
||||
return true;
|
||||
}
|
||||
|
||||
slotData.Closed = true;
|
||||
slotData.Bot = null;
|
||||
|
||||
/* kick any player that's in the slot */
|
||||
var occupant = lobbyInfo.Clients.FirstOrDefault( c => c.Slot == slotData.Index );
|
||||
if (occupant != null)
|
||||
{
|
||||
var occupantConn = conns.FirstOrDefault( c => c.PlayerIndex == occupant.Index );
|
||||
if (occupantConn != null)
|
||||
DropClient( occupantConn, new Exception() );
|
||||
}
|
||||
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "slot_open",
|
||||
s =>
|
||||
{
|
||||
int slot;
|
||||
if (!int.TryParse(s, out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null)
|
||||
return false;
|
||||
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can alter slots" );
|
||||
return true;
|
||||
}
|
||||
|
||||
slotData.Closed = false;
|
||||
slotData.Bot = null;
|
||||
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "slot_bot",
|
||||
s =>
|
||||
{
|
||||
var parts = s.Split(' ');
|
||||
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
SendChatTo( conn, "Malformed slot_bot command" );
|
||||
return true;
|
||||
}
|
||||
|
||||
int slot;
|
||||
if (!int.TryParse(parts[0], out slot)) { Log.Write("server", "Invalid slot: {0}", s ); return false; }
|
||||
|
||||
var slotData = lobbyInfo.Slots.FirstOrDefault( x => x.Index == slot );
|
||||
if (slotData == null)
|
||||
return false;
|
||||
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can alter slots" );
|
||||
return true;
|
||||
}
|
||||
|
||||
slotData.Bot = parts[1];
|
||||
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
{ "map",
|
||||
s =>
|
||||
{
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can change the map" );
|
||||
return true;
|
||||
}
|
||||
lobbyInfo.GlobalSettings.Map = s;
|
||||
LoadMap();
|
||||
|
||||
foreach(var client in lobbyInfo.Clients)
|
||||
{
|
||||
client.SpawnPoint = 0;
|
||||
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;
|
||||
}},
|
||||
{ "lockteams",
|
||||
s =>
|
||||
{
|
||||
if (conn.PlayerIndex != 0)
|
||||
{
|
||||
SendChatTo( conn, "Only the host can set that option" );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool.TryParse(s, out lobbyInfo.GlobalSettings.LockTeams);
|
||||
SyncLobbyInfo();
|
||||
return true;
|
||||
}},
|
||||
};
|
||||
|
||||
var cmdName = cmd.Split(' ').First();
|
||||
var cmdValue = string.Join(" ", cmd.Split(' ').Skip(1).ToArray());
|
||||
|
||||
Func<string,bool> a;
|
||||
if (!dict.TryGetValue(cmdName, out a))
|
||||
return false;
|
||||
|
||||
Log.Write("server", "Client {0} sent server command: {1}", conn.PlayerIndex, cmd );
|
||||
return a(cmdValue);
|
||||
}
|
||||
|
||||
static void SendChatTo(Connection conn, string text)
|
||||
{
|
||||
DispatchOrdersToClient(conn, 0, 0,
|
||||
new ServerOrder("Chat", text).Serialize());
|
||||
}
|
||||
|
||||
public void SendChat(Connection asConn, string text)
|
||||
{
|
||||
DispatchOrders(asConn, 0, new ServerOrder("Chat", text).Serialize());
|
||||
}
|
||||
static void SendChat(Connection asConn, string text)
|
||||
{
|
||||
DispatchOrders(asConn, 0, new ServerOrder("Chat", text).Serialize());
|
||||
}
|
||||
|
||||
public void SendDisconnected(Connection asConn)
|
||||
{
|
||||
DispatchOrders(asConn, 0, new ServerOrder("Disconnected", "").Serialize());
|
||||
}
|
||||
|
||||
void InterpretServerOrder(Connection conn, ServerOrder so)
|
||||
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))
|
||||
{
|
||||
bool handled = false;
|
||||
foreach (var t in ServerTraits.WithInterface<IInterpretCommand>())
|
||||
if ((handled = t.InterpretCommand(this, conn, GetClient(conn), so.Data)))
|
||||
break;
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
Log.Write("server", "Unknown server command: {0}", so.Data);
|
||||
SendChatTo(conn, "Unknown server command: {0}".F(so.Data));
|
||||
}
|
||||
}
|
||||
break;
|
||||
Log.Write("server", "Bad server command: {0}", so.Data);
|
||||
SendChatTo(conn, "Bad server command.");
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case "Chat":
|
||||
case "Chat":
|
||||
case "TeamChat":
|
||||
foreach (var c in conns.Except(conn).ToArray())
|
||||
DispatchOrdersToClient(c, GetClient(conn).Index, 0, so.Serialize());
|
||||
@@ -272,19 +569,16 @@ namespace OpenRA.Server
|
||||
}
|
||||
}
|
||||
|
||||
public Session.Client GetClient(Connection conn)
|
||||
static Session.Client GetClient(Connection conn)
|
||||
{
|
||||
return lobbyInfo.Clients.First(c => c.Index == conn.PlayerIndex);
|
||||
}
|
||||
|
||||
public void DropClient(Connection toDrop, Exception e)
|
||||
public static void DropClient(Connection toDrop, Exception e)
|
||||
{
|
||||
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 } );
|
||||
@@ -293,28 +587,60 @@ namespace OpenRA.Server
|
||||
SyncLobbyInfo();
|
||||
}
|
||||
|
||||
public void SyncLobbyInfo()
|
||||
static void SyncLobbyInfo()
|
||||
{
|
||||
if (!GameStarted) /* don't do this while the game is running, it breaks things. */
|
||||
DispatchOrders(null, 0,
|
||||
new ServerOrder("SyncInfo", lobbyInfo.Serialize()).Serialize());
|
||||
|
||||
foreach (var t in ServerTraits.WithInterface<INotifySyncLobbyInfo>())
|
||||
t.LobbyInfoSynced(this);
|
||||
PingMasterServer();
|
||||
}
|
||||
|
||||
public void StartGame()
|
||||
|
||||
static volatile bool isBusy;
|
||||
static Queue<string> masterServerMessages = new Queue<string>();
|
||||
static void PingMasterServer()
|
||||
{
|
||||
GameStarted = true;
|
||||
foreach( var c in conns )
|
||||
foreach( var d in conns )
|
||||
DispatchOrdersToClient( c, d.PlayerIndex, 0x7FFFFFFF, new byte[] { 0xBF } );
|
||||
if (isBusy || !isInternetServer) return;
|
||||
|
||||
DispatchOrders(null, 0,
|
||||
new ServerOrder("StartGame", "").Serialize());
|
||||
lastPing = Environment.TickCount;
|
||||
isBusy = true;
|
||||
|
||||
foreach (var t in ServerTraits.WithInterface<IStartGame>())
|
||||
t.GameStarted(this);
|
||||
Action a = () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = "ping.php?port={0}&name={1}&state={2}&players={3}&mods={4}&map={5}";
|
||||
if (isInitialPing) url += "&new=1";
|
||||
|
||||
using (var wc = new WebClient())
|
||||
{
|
||||
wc.DownloadData(
|
||||
masterServerUrl + url.F(
|
||||
ExternalPort, Uri.EscapeUriString(Name),
|
||||
GameStarted ? 2 : 1, // todo: post-game states, etc.
|
||||
lobbyInfo.Clients.Count,
|
||||
string.Join(",", lobbyInfo.GlobalSettings.Mods),
|
||||
lobbyInfo.GlobalSettings.Map));
|
||||
|
||||
if (isInitialPing)
|
||||
{
|
||||
isInitialPing = false;
|
||||
lock (masterServerMessages)
|
||||
masterServerMessages.Enqueue("Master server communication established.");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log.Write("server", ex.ToString());
|
||||
lock( masterServerMessages )
|
||||
masterServerMessages.Enqueue( "Master server communication failed." );
|
||||
}
|
||||
|
||||
isBusy = false;
|
||||
};
|
||||
|
||||
a.BeginInvoke(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +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;
|
||||
using OpenRA.Network;
|
||||
|
||||
namespace OpenRA.Server
|
||||
{
|
||||
// Returns true if order is handled
|
||||
public interface IInterpretCommand { bool InterpretCommand(Server server, Connection conn, Session.Client client, string cmd); }
|
||||
public interface INotifySyncLobbyInfo { void LobbyInfoSynced(Server server); }
|
||||
public interface INotifyServerStart { void ServerStarted(Server server); }
|
||||
public interface INotifyServerShutdown { void ServerShutdown(Server server); }
|
||||
public interface IStartGame { void GameStarted(Server server); }
|
||||
public interface IClientJoined { void ClientJoined(Server server, Connection conn); }
|
||||
public interface ITick
|
||||
{
|
||||
void Tick(Server server);
|
||||
int TickTimeout { get; }
|
||||
}
|
||||
|
||||
public abstract class ServerTrait {}
|
||||
|
||||
public class DebugServerTrait : ServerTrait, IInterpretCommand, IStartGame, INotifySyncLobbyInfo, INotifyServerStart, INotifyServerShutdown
|
||||
{
|
||||
public bool InterpretCommand(Server server, Connection conn, Session.Client client, string cmd)
|
||||
{
|
||||
Console.WriteLine("Server received command from player {1}: {0}",cmd, conn.PlayerIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void GameStarted(Server server)
|
||||
{
|
||||
Console.WriteLine("GameStarted()");
|
||||
}
|
||||
|
||||
public void LobbyInfoSynced(Server server)
|
||||
{
|
||||
Console.WriteLine("LobbyInfoSynced()");
|
||||
}
|
||||
|
||||
public void ServerStarted(Server server)
|
||||
{
|
||||
Console.WriteLine("ServerStarted()");
|
||||
}
|
||||
|
||||
public void ServerShutdown(Server server)
|
||||
{
|
||||
Console.WriteLine("ServerShutdown()");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace OpenRA.Support
|
||||
}
|
||||
}
|
||||
|
||||
public class PerfSample : IDisposable
|
||||
class PerfSample : IDisposable
|
||||
{
|
||||
readonly Stopwatch sw = new Stopwatch();
|
||||
readonly string Item;
|
||||
|
||||
@@ -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" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
OpenRA.Mods.RA/Move/Drag.cs → OpenRA.Game/Traits/Activities/Drag.cs
Executable file → Normal file
3
OpenRA.Mods.RA/Move/Drag.cs → OpenRA.Game/Traits/Activities/Drag.cs
Executable file → Normal 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
|
||||
{
|
||||
@@ -12,6 +12,6 @@ namespace OpenRA.Traits.Activities
|
||||
{
|
||||
public class Idle : CancelableActivity
|
||||
{
|
||||
public override IActivity Tick(Actor self) { return NextActivity ?? this; }
|
||||
public override IActivity Tick(Actor self) { return NextActivity; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,17 +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.PathFinder.AvoidUnitsNear( mobile.toCell, 4, self ))
|
||||
.WithIgnoredBuilding( ignoreBuilding ));
|
||||
|
||||
this.destination = destination;
|
||||
@@ -58,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;
|
||||
@@ -67,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;
|
||||
@@ -76,6 +90,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
}
|
||||
|
||||
public Move(Func<List<int2>> getPath)
|
||||
: this()
|
||||
{
|
||||
this.getPath = (_1,_2) => getPath();
|
||||
this.destination = null;
|
||||
@@ -110,9 +125,9 @@ namespace OpenRA.Mods.RA.Move
|
||||
|
||||
if( path == null )
|
||||
{
|
||||
if (mobile.ticksBeforePathing > 0)
|
||||
if (ticksBeforePathing > 0)
|
||||
{
|
||||
--mobile.ticksBeforePathing;
|
||||
--ticksBeforePathing;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -137,7 +152,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
if( firstFacing != mobile.Facing )
|
||||
{
|
||||
path.Add( nextCell.Value );
|
||||
return Util.SequenceActivities( new Turn( firstFacing ), this );
|
||||
return Util.SequenceActivities( new Turn( firstFacing ), this ).Tick( self );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -150,7 +165,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
mobile.Facing,
|
||||
0 );
|
||||
|
||||
return move;
|
||||
return move.Tick( self );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,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();
|
||||
@@ -230,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;
|
||||
@@ -289,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;
|
||||
|
||||
4
OpenRA.Mods.RA/Activities/RemoveSelf.cs → OpenRA.Game/Traits/Activities/RemoveSelf.cs
Executable file → Normal file
4
OpenRA.Mods.RA/Activities/RemoveSelf.cs → OpenRA.Game/Traits/Activities/RemoveSelf.cs
Executable file → Normal file
@@ -8,9 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Activities
|
||||
namespace OpenRA.Traits.Activities
|
||||
{
|
||||
public class RemoveSelf : CancelableActivity
|
||||
{
|
||||
3
OpenRA.Mods.RA/Buildings/Sell.cs → OpenRA.Game/Traits/Activities/Sell.cs
Executable file → Normal file
3
OpenRA.Mods.RA/Buildings/Sell.cs → OpenRA.Game/Traits/Activities/Sell.cs
Executable file → Normal 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
|
||||
{
|
||||
@@ -9,9 +9,8 @@
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Activities
|
||||
namespace OpenRA.Traits.Activities
|
||||
{
|
||||
public class Turn : CancelableActivity
|
||||
{
|
||||
9
OpenRA.Game/Traits/EditorAppearance.cs → OpenRA.Game/Traits/BaseBuilding.cs
Normal file → Executable file
9
OpenRA.Game/Traits/EditorAppearance.cs → OpenRA.Game/Traits/BaseBuilding.cs
Normal file → Executable file
@@ -10,10 +10,7 @@
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
public class EditorAppearanceInfo : TraitInfo<EditorAppearance>
|
||||
{
|
||||
public readonly bool RelativeToTopLeft = false;
|
||||
}
|
||||
|
||||
public class EditorAppearance { }
|
||||
/* tag trait for "bases": mcv/fact */
|
||||
public class BaseBuildingInfo : TraitInfo<BaseBuilding> { }
|
||||
public class BaseBuilding { }
|
||||
}
|
||||
102
OpenRA.Game/Traits/Building.cs
Normal file
102
OpenRA.Game/Traits/Building.cs
Normal 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
4
OpenRA.Mods.RA/Buildings/CustomSellValue.cs → OpenRA.Game/Traits/CustomSellValue.cs
Executable file → Normal file
4
OpenRA.Mods.RA/Buildings/CustomSellValue.cs → OpenRA.Game/Traits/CustomSellValue.cs
Executable file → Normal 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.
|
||||
@@ -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;
|
||||
|
||||
@@ -57,11 +57,9 @@ namespace OpenRA.Traits
|
||||
return;
|
||||
|
||||
var p = target.CenterLocation;
|
||||
var move = self.TraitOrDefault<IMove>();
|
||||
var origin = move != null ? self.CenterLocation - new float2(0, move.Altitude) : self.CenterLocation;
|
||||
|
||||
Game.Renderer.LineRenderer.DrawLine(origin, p, c, c);
|
||||
for (bool b = false; !b; p = origin, b = true)
|
||||
Game.Renderer.LineRenderer.DrawLine(self.CenterLocation, p, c, c);
|
||||
for (bool b = false; !b; p = self.CenterLocation, b = true)
|
||||
{
|
||||
Game.Renderer.LineRenderer.DrawLine(p + new float2(-1, -1), p + new float2(-1, 1), c, c);
|
||||
Game.Renderer.LineRenderer.DrawLine(p + new float2(-1, 1), p + new float2(1, 1), c, c);
|
||||
|
||||
@@ -6,18 +6,22 @@
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
* see LICENSE.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Traits.Activities;
|
||||
using OpenRA.GameRules;
|
||||
using OpenRA.FileFormats;
|
||||
|
||||
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); }
|
||||
}
|
||||
|
||||
@@ -76,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,
|
||||
@@ -92,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)
|
||||
|
||||
4
OpenRA.Mods.RA/Buildings/LineBuild.cs → OpenRA.Game/Traits/LineBuild.cs
Executable file → Normal file
4
OpenRA.Mods.RA/Buildings/LineBuild.cs → OpenRA.Game/Traits/LineBuild.cs
Executable file → Normal file
@@ -8,9 +8,7 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.RA.Buildings
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
public class LineBuildInfo : TraitInfo<LineBuild>
|
||||
{
|
||||
131
OpenRA.Mods.RA/Move/Mobile.cs → OpenRA.Game/Traits/Mobile.cs
Executable file → Normal file
131
OpenRA.Mods.RA/Move/Mobile.cs → OpenRA.Game/Traits/Mobile.cs
Executable file → Normal file
@@ -13,14 +13,12 @@ using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Mods.RA.Activities;
|
||||
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
|
||||
{
|
||||
@@ -41,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});
|
||||
}
|
||||
@@ -52,7 +50,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
public class TerrainInfo
|
||||
{
|
||||
public int Cost = int.MaxValue;
|
||||
public decimal Speed = 0;
|
||||
public float Speed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,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)
|
||||
{
|
||||
@@ -119,6 +113,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
{
|
||||
this.__fromCell = this.__toCell = init.Get<LocationInit,int2>();
|
||||
this.PxPosition = Util.CenterOfCell( fromCell );
|
||||
AddInfluence();
|
||||
}
|
||||
|
||||
this.Facing = init.Contains<FacingInit>() ? init.Get<FacingInit,int>() : info.InitialFacing;
|
||||
@@ -141,12 +136,12 @@ namespace OpenRA.Mods.RA.Move
|
||||
public IEnumerable<IOrderTargeter> Orders { get { yield return new MoveOrderTargeter( Info ); } }
|
||||
|
||||
// Note: Returns a valid order even if the unit can't move to the target
|
||||
public Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued )
|
||||
public Order IssueOrder( Actor self, IOrderTargeter order, Target target )
|
||||
{
|
||||
if( order is MoveOrderTargeter )
|
||||
{
|
||||
if( Info.OnRails ) return null;
|
||||
return new Order( "Move", self, Util.CellContaining( target.CenterLocation ), queued );
|
||||
return new Order( "Move", self, Util.CellContaining( target.CenterLocation ), false );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -170,46 +165,27 @@ namespace OpenRA.Mods.RA.Move
|
||||
// Couldn't find a cell
|
||||
return target;
|
||||
}
|
||||
|
||||
protected void PerformMove(Actor self, int2 targetLocation, bool queued)
|
||||
{
|
||||
var ph = new QueuedActivity(
|
||||
(qa) =>
|
||||
{
|
||||
int2 currentLocation = NearestMoveableCell(targetLocation);
|
||||
|
||||
if (!CanEnterCell(currentLocation))
|
||||
{
|
||||
if (queued) self.CancelActivity();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!queued) self.CancelActivity();
|
||||
|
||||
ticksBeforePathing = avgTicksBeforePathing + self.World.SharedRandom.Next(-spreadTicksBeforePathing, spreadTicksBeforePathing);
|
||||
|
||||
qa.Insert(new Move(currentLocation, 8));
|
||||
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
self.World.AddFrameEndTask(
|
||||
w =>
|
||||
{
|
||||
if (self.Destroyed) return;
|
||||
w.Add(new MoveFlash(self.World, targetLocation));
|
||||
var line = self.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTarget(self, Target.FromCell(currentLocation),
|
||||
Color.Green);
|
||||
});
|
||||
});
|
||||
|
||||
self.QueueActivity(queued ? ph : ph.Run(self));
|
||||
}
|
||||
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString == "Move")
|
||||
PerformMove(self, order.TargetLocation, order.Queued && !self.IsIdle);
|
||||
{
|
||||
int2 currentLocation = NearestMoveableCell(order.TargetLocation);
|
||||
if (!CanEnterCell(currentLocation))
|
||||
return;
|
||||
|
||||
if( !order.Queued ) self.CancelActivity();
|
||||
self.QueueActivity(new Activities.Move(currentLocation, 8));
|
||||
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
w.Add(new MoveFlash(self.World, order.TargetLocation));
|
||||
var line = self.TraitOrDefault<DrawLineToTarget>();
|
||||
if (line != null)
|
||||
line.SetTarget(self, Target.FromCell(currentLocation), Color.Green);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public string VoicePhraseForOrder(Actor self, Order order)
|
||||
@@ -237,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)
|
||||
{
|
||||
@@ -290,29 +284,28 @@ 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()
|
||||
{
|
||||
if( self.IsInWorld )
|
||||
uim.Add( self, this );
|
||||
uim.Add( self, this );
|
||||
}
|
||||
|
||||
public void RemoveInfluence()
|
||||
{
|
||||
if( self.IsInWorld )
|
||||
uim.Remove( self, this );
|
||||
uim.Remove( self, this );
|
||||
}
|
||||
|
||||
public void OnNudge(Actor self, Actor nudger)
|
||||
@@ -350,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);
|
||||
@@ -376,28 +368,19 @@ namespace OpenRA.Mods.RA.Move
|
||||
|
||||
public string OrderID { get { return "Move"; } }
|
||||
public int OrderPriority { get { return 4; } }
|
||||
public bool IsQueued { get; protected set; }
|
||||
public bool CanTargetUnit(Actor self, Actor target, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
|
||||
|
||||
public bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, bool forceQueued, ref string cursor)
|
||||
public bool CanTargetLocation( Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceMove, ref string cursor )
|
||||
{
|
||||
IsQueued = forceQueued;
|
||||
|
||||
cursor = "move";
|
||||
if( self.World.LocalPlayer.Shroud.IsVisible( location ) && !self.Trait<Mobile>().CanEnterCell( location ) )
|
||||
cursor = "move-blocked";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public IActivity ScriptedMove( int2 cell ) { return new Move( cell ); }
|
||||
public IActivity MoveTo( int2 cell, int nearEnough ) { return new Move( cell, nearEnough ); }
|
||||
public IActivity MoveTo( int2 cell, Actor ignoredActor ) { return new Move( cell, ignoredActor ); }
|
||||
public IActivity MoveWithinRange( Actor target, int range ) { return new Move( target, range ); }
|
||||
public IActivity MoveWithinRange( Target target, int range ) { return new Move( target, range ); }
|
||||
public IActivity MoveTo( Func<List<int2>> pathFunc ) { return new Move( pathFunc ); }
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
public class DeveloperModeInfo : ITraitInfo
|
||||
@@ -18,9 +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 UnlimitedPower;
|
||||
public bool PathDebug = false;
|
||||
|
||||
public object Create (ActorInitializer init) { return new DeveloperMode(this); }
|
||||
}
|
||||
@@ -33,23 +30,19 @@ namespace OpenRA.Traits
|
||||
[Sync] public bool FastBuild;
|
||||
[Sync] public bool DisableShroud;
|
||||
[Sync] public bool PathDebug;
|
||||
[Sync] public bool UnitInfluenceDebug;
|
||||
[Sync] public bool UnlimitedPower;
|
||||
|
||||
|
||||
public DeveloperMode(DeveloperModeInfo info)
|
||||
{
|
||||
Info = info;
|
||||
FastBuild = Info.FastBuild;
|
||||
FastCharge = Info.FastCharge;
|
||||
DisableShroud = Info.DisableShroud;
|
||||
PathDebug = Info.PathDebug;
|
||||
UnitInfluenceDebug = info.UnitInfluenceDebug;
|
||||
UnlimitedPower = info.UnlimitedPower;
|
||||
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)
|
||||
{
|
||||
@@ -86,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":
|
||||
@@ -95,11 +89,6 @@ namespace OpenRA.Traits
|
||||
if (self.World.LocalPlayer == self.Owner)
|
||||
self.World.WorldActor.Trait<Shroud>().ExploreAll(self.World);
|
||||
break;
|
||||
}
|
||||
case "DevUnlimitedPower":
|
||||
{
|
||||
UnlimitedPower ^= true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
|
||||
39
OpenRA.Mods.RA/Buildings/PowerManager.cs → OpenRA.Game/Traits/Player/PowerManager.cs
Executable file → Normal file
39
OpenRA.Mods.RA/Buildings/PowerManager.cs → OpenRA.Game/Traits/Player/PowerManager.cs
Executable file → Normal file
@@ -6,14 +6,16 @@
|
||||
* 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, ITraitPrerequisite<DeveloperModeInfo>
|
||||
public class PowerManagerInfo : ITraitInfo
|
||||
{
|
||||
public readonly int AdviceInterval = 250;
|
||||
public object Create(ActorInitializer init) { return new PowerManager(init, this); }
|
||||
@@ -22,8 +24,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
public class PowerManager : ITick
|
||||
{
|
||||
PowerManagerInfo Info;
|
||||
Player Player;
|
||||
DeveloperMode devMode;
|
||||
Player Player;
|
||||
|
||||
Dictionary<Actor, int> PowerDrain = new Dictionary<Actor, int>();
|
||||
[Sync] int totalProvided;
|
||||
@@ -38,10 +39,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
Player = init.self.Owner;
|
||||
|
||||
init.world.ActorAdded += ActorAdded;
|
||||
init.world.ActorRemoved += ActorRemoved;
|
||||
|
||||
devMode = init.self.Trait<DeveloperMode>();
|
||||
wasHackEnabled = devMode.UnlimitedPower;
|
||||
init.world.ActorRemoved += ActorRemoved;
|
||||
}
|
||||
|
||||
void ActorAdded(Actor a)
|
||||
@@ -71,10 +69,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
totalProvided += p;
|
||||
else
|
||||
totalDrained -= p;
|
||||
}
|
||||
|
||||
if (devMode.UnlimitedPower)
|
||||
totalProvided = 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateActor(Actor a, int newPower)
|
||||
@@ -87,17 +82,9 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
}
|
||||
|
||||
int nextPowerAdviceTime = 0;
|
||||
bool wasLowPower = false;
|
||||
bool wasHackEnabled;
|
||||
|
||||
bool wasLowPower = false;
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (wasHackEnabled != devMode.UnlimitedPower)
|
||||
{
|
||||
UpdateTotals();
|
||||
wasHackEnabled = devMode.UnlimitedPower;
|
||||
}
|
||||
|
||||
{
|
||||
var lowPower = totalProvided < totalDrained;
|
||||
if (lowPower && !wasLowPower)
|
||||
nextPowerAdviceTime = 0;
|
||||
@@ -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
|
||||
{
|
||||
@@ -1,40 +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(this); }
|
||||
}
|
||||
|
||||
public class Scale : IRenderModifier
|
||||
{
|
||||
public ScaleInfo Info { get; protected set; }
|
||||
|
||||
public Scale(ScaleInfo info)
|
||||
{
|
||||
this.Info = info;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
#endregion
|
||||
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
@@ -20,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
|
||||
@@ -28,27 +29,20 @@ 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);
|
||||
Color selectionColor = Color.White;
|
||||
|
||||
var xy = new float2(bounds.Left, bounds.Top);
|
||||
var Xy = new float2(bounds.Right, bounds.Top);
|
||||
var xY = new float2(bounds.Left, bounds.Bottom);
|
||||
var XY = new float2(bounds.Right, bounds.Bottom);
|
||||
|
||||
var colorResults = self.TraitsImplementing<ISelectionColorModifier>().Select(t => t.GetSelectionColorModifier(self, selectionColor)).Where(
|
||||
c => c.ToArgb() != selectionColor.ToArgb());
|
||||
|
||||
if (colorResults.Any())
|
||||
selectionColor = colorResults.First();
|
||||
|
||||
DrawSelectionBox(self, xy, Xy, xY, XY, selectionColor);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -95,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;
|
||||
@@ -103,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;
|
||||
|
||||
@@ -129,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
|
||||
@@ -138,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;
|
||||
|
||||
@@ -155,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;
|
||||
@@ -165,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>();
|
||||
|
||||
36
OpenRA.Game/Traits/Targetable.cs
Normal file
36
OpenRA.Game/Traits/Targetable.cs
Normal 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;}
|
||||
}
|
||||
}
|
||||
}
|
||||
121
OpenRA.Game/Traits/TraitsInterfaces.cs
Executable file → Normal file
121
OpenRA.Game/Traits/TraitsInterfaces.cs
Executable file → Normal 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); }
|
||||
@@ -39,22 +36,20 @@ namespace OpenRA.Traits
|
||||
public interface IIssueOrder
|
||||
{
|
||||
IEnumerable<IOrderTargeter> Orders { get; }
|
||||
Order IssueOrder( Actor self, IOrderTargeter order, Target target, bool queued );
|
||||
Order IssueOrder( Actor self, IOrderTargeter order, Target target );
|
||||
}
|
||||
public interface IOrderTargeter
|
||||
{
|
||||
string OrderID { get; }
|
||||
int OrderPriority { get; }
|
||||
bool CanTargetUnit( Actor self, Actor target, bool forceAttack, bool forceMove, bool forceQueue, ref string cursor );
|
||||
bool CanTargetLocation(Actor self, int2 location, List<Actor> actorsAtLocation, bool forceAttack, bool forceQueue, bool forceMove, ref string cursor);
|
||||
bool IsQueued { 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); }
|
||||
@@ -105,13 +100,11 @@ namespace OpenRA.Traits
|
||||
}
|
||||
}
|
||||
|
||||
public interface INotifyAttack { void Attacking(Actor self, Target target); }
|
||||
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 ISelectionColorModifier { Color GetSelectionColorModifier(Actor self, Color defaultColor); }
|
||||
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(); }
|
||||
@@ -149,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); }
|
||||
@@ -202,15 +180,44 @@ namespace OpenRA.Traits
|
||||
IEnumerable<float2> GetCurrentPath();
|
||||
}
|
||||
|
||||
public interface IRenderOverlay { void Render( WorldRenderer wr ); }
|
||||
public interface INotifyIdle { void TickIdle(Actor self); }
|
||||
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 IPostRenderSelection { void RenderAfterWorld(Actor self); }
|
||||
public interface IPreRenderSelection { void RenderBeforeWorld(Actor self); }
|
||||
|
||||
public struct Target // a target: either an actor, or a fixed location.
|
||||
{
|
||||
@@ -218,7 +225,7 @@ namespace OpenRA.Traits
|
||||
float2 pos;
|
||||
bool valid;
|
||||
|
||||
public static Target FromActor(Actor a) { return new Target { actor = a, valid = (a != null) }; }
|
||||
public static Target FromActor(Actor a) { return new Target { actor = a, valid = true }; }
|
||||
public static Target FromPos(float2 p) { return new Target { pos = p, valid = true }; }
|
||||
public static Target FromCell(int2 c) { return new Target { pos = Util.CenterOfCell(c), valid = true }; }
|
||||
public static Target FromOrder(Order o)
|
||||
@@ -237,12 +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 );
|
||||
}
|
||||
|
||||
public interface INotifyKeyPress { bool KeyPressed(Actor self, KeyInput e); }
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Support;
|
||||
|
||||
namespace OpenRA.Traits
|
||||
{
|
||||
@@ -100,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);
|
||||
}
|
||||
|
||||
@@ -116,24 +109,6 @@ namespace OpenRA.Traits
|
||||
(next, a) => { a.Queue( next ); return a; });
|
||||
}
|
||||
|
||||
public static IActivity RunActivity( Actor self, IActivity act )
|
||||
{
|
||||
while( act != null )
|
||||
{
|
||||
var prev = act;
|
||||
|
||||
var sw = new Stopwatch();
|
||||
act = act.Tick( self );
|
||||
var dt = sw.ElapsedTime();
|
||||
if(dt > Game.Settings.Debug.LongTickThreshold)
|
||||
Log.Write("perf", "[{2}] Activity: {0} ({1:0.000} ms)", prev, dt * 1000, Game.LocalTick);
|
||||
|
||||
if( prev == act )
|
||||
break;
|
||||
}
|
||||
return act;
|
||||
}
|
||||
|
||||
public static Color ArrayToColor(int[] x) { return Color.FromArgb(x[0], x[1], x[2]); }
|
||||
|
||||
public static int2 CellContaining(float2 pos) { return (1f / Game.CellSize * pos).ToInt2(); }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user