<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://springrts-wiki.p2004a.com/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zerver</id>
	<title>Spring - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://springrts-wiki.p2004a.com/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zerver"/>
	<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/wiki/Special:Contributions/Zerver"/>
	<updated>2026-11-08T18:05:06Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.11</generator>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17238</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17238"/>
		<updated>2013-09-01T16:49:01Z</updated>

		<summary type="html">&lt;p&gt;Zerver: Add deprecation info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{deprecated}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Deprecated! Spring MT has been renamed to RTSMP and is no longer part of the Spring project.&amp;lt;/span&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the other Spring releases. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers will send you a chat message with instructions.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; for streamlined access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows complete&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe 94.11 MT + 94.11 installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip both executables in the install folder of the official release.&lt;br /&gt;
&lt;br /&gt;
:Windows [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z 94.11].&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux32 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux32/spring_94.1_minimal-portable-linux32-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux64/spring_94.1_minimal-portable-linux64-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:OSX64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/osx64/spring_94.1_MacOSX-10.6-SnowLeopard.zip portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;Please note this server REQUIRES Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Installation instructions: http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17236</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17236"/>
		<updated>2013-04-28T21:41:22Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the other Spring releases. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers will send you a chat message with instructions.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; for streamlined access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows complete&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe 94.11 MT + 94.11 installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip both executables in the install folder of the official release.&lt;br /&gt;
&lt;br /&gt;
:Windows [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z 94.11].&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux32 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux32/spring_94.1_minimal-portable-linux32-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux64/spring_94.1_minimal-portable-linux64-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:OSX64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/osx64/spring_94.1_MacOSX-10.6-SnowLeopard.zip portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;Please note this server REQUIRES Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Installation instructions: http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17235</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17235"/>
		<updated>2013-04-28T21:40:01Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* On which servers can I play Spring MT? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the other Spring releases. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers will send you a chat message with instructions.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows complete&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe 94.11 MT + 94.11 installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip both executables in the install folder of the official release.&lt;br /&gt;
&lt;br /&gt;
:Windows [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z 94.11].&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux32 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux32/spring_94.1_minimal-portable-linux32-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux64/spring_94.1_minimal-portable-linux64-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:OSX64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/osx64/spring_94.1_MacOSX-10.6-SnowLeopard.zip portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;Please note this server REQUIRES Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Installation instructions: http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17234</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17234"/>
		<updated>2013-04-28T21:38:36Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it on my autohost? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the other Spring releases. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows complete&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe 94.11 MT + 94.11 installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip both executables in the install folder of the official release.&lt;br /&gt;
&lt;br /&gt;
:Windows [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z 94.11].&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux32 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux32/spring_94.1_minimal-portable-linux32-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux64/spring_94.1_minimal-portable-linux64-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:OSX64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/osx64/spring_94.1_MacOSX-10.6-SnowLeopard.zip portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;Please note this server REQUIRES Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Installation instructions: http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17233</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17233"/>
		<updated>2013-04-22T20:58:30Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* What is Spring MT? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the other Spring releases. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows complete&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe 94.11 MT + 94.11 installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip both executables in the install folder of the official release.&lt;br /&gt;
&lt;br /&gt;
:Windows [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z 94.11].&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux32 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux32/spring_94.1_minimal-portable-linux32-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux64/spring_94.1_minimal-portable-linux64-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:OSX64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/osx64/spring_94.1_MacOSX-10.6-SnowLeopard.zip portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17232</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17232"/>
		<updated>2013-04-22T20:57:03Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows complete&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe 94.11 MT + 94.11 installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip both executables in the install folder of the official release.&lt;br /&gt;
&lt;br /&gt;
:Windows [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z 94.11].&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux32 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux32/spring_94.1_minimal-portable-linux32-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux64/spring_94.1_minimal-portable-linux64-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:OSX64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/osx64/spring_94.1_MacOSX-10.6-SnowLeopard.zip portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17231</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17231"/>
		<updated>2013-04-22T17:33:22Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */ shuffle links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows complete&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe 94.11 MT + 94.11 installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip both executables the install folder of the official release.&lt;br /&gt;
&lt;br /&gt;
:Windows [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z 94.11].&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux32 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux32/spring_94.1_minimal-portable-linux32-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:Linux64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/linux64/spring_94.1_minimal-portable-linux64-static.7z portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:OSX64 [http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip 94.11 MT], [http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip 94.11]. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Requires a [http://springrts.com/dl/buildbot/default/master/94.1/osx64/spring_94.1_MacOSX-10.6-SnowLeopard.zip portable] installation&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17230</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17230"/>
		<updated>2013-04-22T10:25:57Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Spring MT */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
The Spring MT 94.11 release is&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17228</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17228"/>
		<updated>2013-04-21T15:44:54Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Why is this unofficial? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== Why is this unofficial? ===&lt;br /&gt;
The code base is somewhat complex, making it hard to maintain for developers who have only rudimentary multithreading skills.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, possibly producing some negative effects. There is an increased risk of threading bugs that may cause a desync. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17227</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17227"/>
		<updated>2013-04-17T20:36:52Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;text-decoration:blink; color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17226</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17226"/>
		<updated>2013-04-13T22:10:46Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17225</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17225"/>
		<updated>2013-04-13T21:03:35Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/zerver/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17224</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17224"/>
		<updated>2013-04-08T16:28:20Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it on my autohost? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17223</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17223"/>
		<updated>2013-04-08T16:27:54Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
:[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17222</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17222"/>
		<updated>2013-04-08T01:15:35Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Complete 94.11 MT + 94.11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Unzip to the install folder of the official release. &amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Linux and OSX may require a portable installation.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;94.11 MT (ASIM APATH GML)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;94.11 (ASIM GML OMP)&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17221</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17221"/>
		<updated>2013-04-05T10:03:00Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it on my autohost? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows 94.11 MT + 94.11 full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;94.11 MT (ASIM APATH GML) executables&#039;&#039;&#039; (unzip to the install folder of the official release)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;94.11 (ASIM GML OMP) executables&#039;&#039;&#039; (unzip to the install folder of the official release)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dedicated server&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17220</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17220"/>
		<updated>2013-04-05T10:01:17Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows 94.11 MT + 94.11 full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows 94.11 MT + 94.11 portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;94.11 MT (ASIM APATH GML) executables&#039;&#039;&#039; (unzip to the install folder of the official release)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;94.11 (ASIM GML OMP) executables&#039;&#039;&#039; (unzip to the install folder of the official release)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17219</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17219"/>
		<updated>2013-04-05T00:19:54Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it on my autohost? */ osx dedicated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.1 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-dedicated.zip OSX64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17218</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17218"/>
		<updated>2013-04-05T00:18:24Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */ osx&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.1 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/osx64/%7bMTsim2%7d94.1-19-g1f3d930_MacOSX-10.6-SnowLeopard_spring-mt.zip OSX64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/osx64/%7bMTsim3%7d94.1-16-ge49de6c_MacOSX-10.6-SnowLeopard_spring.zip OSX64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17217</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17217"/>
		<updated>2013-04-04T22:51:22Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* What is Spring MT? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses multithreaded asynchronous simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.1 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github Spring MT 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github Spring 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17216</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17216"/>
		<updated>2013-04-04T22:49:22Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Should I use MT even if I don&amp;#039;t want to play on MT servers? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses asynchronous multithreaded simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring 94.11 (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.1 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github Spring MT 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github Spring 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17215</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17215"/>
		<updated>2013-04-04T22:30:29Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses asynchronous multithreaded simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.1 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github Spring MT 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github Spring 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17214</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17214"/>
		<updated>2013-04-04T22:29:50Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Spring MT */ 94.11&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.11 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.1&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses asynchronous multithreaded simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9411&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/spring_94.1-19-g1f3d930_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.0 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt.7z Windows 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/win32/%7bMTsim3%7d94.1-16-ge49de6c_spring.7z Windows 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux32-static.7z Linux32 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux32/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux32-static.7z Linux32 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-mt-linux64-static.7z Linux64 94.11 MT]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim3/94.1-16-ge49de6c/linux64/%7bMTsim3%7d94.1-16-ge49de6c_spring-linux64-static.7z Linux64 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/1f3d930a716bb0260e8d12b7d80b8f8f0299a908 Github Spring MT 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/e49de6c299860728208ee60c2092c2131cae1363 Github Spring 94.11]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/win32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux32/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux32-static.7z Linux32 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.1-19-g1f3d930/linux64/%7bMTsim2%7d94.1-19-g1f3d930_spring-dedicated-linux64-static.7z Linux64 dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9411&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.11. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17213</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17213"/>
		<updated>2013-03-24T18:19:56Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Where can I get the source code? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.01 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.0&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses asynchronous multithreaded simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9401&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/spring_94.0-5-g67f92b3.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/spring_94.0-5-g67f92b3_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.0 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-win32-executables Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-linux32-executables Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-linux64-executables Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-osx64-executables OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Source code&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/67f92b36cf99c9374fb8f6a1b989bc86e7b50e74 Github Spring MT 94.01]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/5a59047e6bb2c85fcb3ed11b9379c28276832370 Github Spring 94.01]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/%7bMTsim2%7d94.0-5-g67f92b3_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9401&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.01. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17212</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17212"/>
		<updated>2013-03-24T18:16:19Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* How do I install it? */ source code&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.01 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.0&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses asynchronous multithreaded simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9401&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/spring_94.0-5-g67f92b3.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/spring_94.0-5-g67f92b3_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.0 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-win32-executables Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-linux32-executables Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-linux64-executables Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-osx64-executables OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Where can I get the source code? ===&lt;br /&gt;
[https://github.com/spring/spring/tree/67f92b36cf99c9374fb8f6a1b989bc86e7b50e74 Github Spring MT 94.01]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[https://github.com/spring/spring/tree/5a59047e6bb2c85fcb3ed11b9379c28276832370 Github Spring 94.01]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/%7bMTsim2%7d94.0-5-g67f92b3_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9401&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.01. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17211</id>
		<title>Spring MT</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_MT&amp;diff=17211"/>
		<updated>2013-03-24T17:24:21Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Spring MT */ update 94.01&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring MT ==&lt;br /&gt;
Unofficial 94.01 release,&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;compatible with Spring 94.0&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== What is Spring MT? ===&lt;br /&gt;
Spring MT is an independent engine that uses asynchronous multithreaded simulation (MT ASIM) to a much higher degree than the official Spring release. It also uses asynchronous pathfinding (APATH). This typically translates into significantly higher performance, depending on your hardware.&lt;br /&gt;
&lt;br /&gt;
=== What hardware do I need? ===&lt;br /&gt;
You need &#039;&#039;&#039;three physical cores&#039;&#039;&#039; to get any real benefit. A quad core or better is recommended.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Image:Spring_MT_core_layout.gif|666px]]&lt;br /&gt;
=== How much faster is it? ===&lt;br /&gt;
Typically &#039;&#039;&#039;more than 100% faster&#039;&#039;&#039; with a quad core. Benchmarked using Core I7 2600K, BA7.72, DeltaSiegeDry, Default pathfinder, 4x &amp;quot;give all&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== How can it be faster? ===&lt;br /&gt;
The simulation will run on several CPU cores, and the pathfinder may also run on a separate core.&lt;br /&gt;
&lt;br /&gt;
=== How does Spring / Spring MT play together? ===&lt;br /&gt;
Spring MT includes Spring, and uses automatic engine type detection to make it sync-compatible.&lt;br /&gt;
&lt;br /&gt;
=== On which servers can I play Spring MT? ===&lt;br /&gt;
Look for servers that have &amp;quot;Spring MT&amp;quot; or &amp;quot;MT&amp;quot; in the description. These servers may have protected access and will send you a chat message with instructions how to join.&lt;br /&gt;
&lt;br /&gt;
=== What is the downside? ===&lt;br /&gt;
The simulation may work slightly differently, producing some negative effects. This is also experimental stuff and may have crashbugs or desyncs. The Default pathfinder is recommended because the QTPFS pathfinder tends to kill the performance of Spring MT.&lt;br /&gt;
&lt;br /&gt;
=== Should I use MT even if I don&#039;t want to play on MT servers? ===&lt;br /&gt;
You can give it a try, the included Spring (non-MT) version also has automatic CPU affinity setup that may give you some more performance.&lt;br /&gt;
&lt;br /&gt;
=== How do I install it? ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:#FF0000&amp;quot;&amp;gt;Note: After installation, join lobby chat room &#039;&#039;&#039;#SpringMT9401&#039;&#039;&#039; to get access to MT autohosts.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/spring_94.0-5-g67f92b3.exe Windows full installer]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/spring_94.0-5-g67f92b3_portable.7z Windows portable]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Executables only&#039;&#039;&#039; (unzip to 94.0 install folder)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-win32-executables Windows]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-linux32-executables Linux32]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-linux64-executables Linux64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://springfiles.com/spring/spring-base/spring-mt-osx64-executables OSX64]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== How do I install it on my autohost? ===&lt;br /&gt;
[http://springrts.com/dl/buildbot/default/MTsim2/94.0-5-g67f92b3/win32/%7bMTsim2%7d94.0-5-g67f92b3_spring-dedicated.7z Windows dedicated server]&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.conf&#039;&#039;&#039; set masterChannel:SpringMT9401&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &#039;&#039;&#039;spads.pl&#039;&#039;&#039;, search for &amp;quot;sub cbJoinBattleRequest&amp;quot; and insert these lines of code immediately after the second line (the one that starts with &amp;quot;my&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (!exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel} || &lt;br /&gt;
      !exists $lobby-&amp;gt;{channels}-&amp;gt;{$masterChannel}-&amp;gt;{$user}) {&lt;br /&gt;
    my $mtmsg = &amp;quot;This server requires Spring MT 94.01. &amp;quot;.&lt;br /&gt;
      &amp;quot;Install http://springrts.com/wiki/Spring_MT&amp;quot;;&lt;br /&gt;
    sayPrivate($user,$mtmsg);&lt;br /&gt;
    queueLobbyCommand([&#039;JOINBATTLEDENY&#039;,$user,$mtmsg]);&lt;br /&gt;
    return;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Consider disabling spads auto update to avoid the changes being overwritten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=File:Spring_MT_core_layout.gif&amp;diff=22089</id>
		<title>File:Spring MT core layout.gif</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=File:Spring_MT_core_layout.gif&amp;diff=22089"/>
		<updated>2013-03-24T17:16:14Z</updated>

		<summary type="html">&lt;p&gt;Zerver: CPU core layout for Spring MT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CPU core layout for Spring MT&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Modrules.lua&amp;diff=14449</id>
		<title>Modrules.lua</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Modrules.lua&amp;diff=14449"/>
		<updated>2013-03-22T23:25:26Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* system */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Location==&lt;br /&gt;
&amp;lt;code&amp;gt;modrules.lua&amp;lt;/code&amp;gt; is a file in the &amp;lt;code&amp;gt;Gamedata/&amp;lt;/code&amp;gt; directory of a Spring game. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
This file controls various global parameters of the game, for example how fast units gain experience, what unit types can be transported, how fine grained the LOS system is, etc.&lt;br /&gt;
&lt;br /&gt;
==Source==&lt;br /&gt;
The engine source code which parses the data from this file is viewable here:&lt;br /&gt;
&lt;br /&gt;
* {{sourcelink|file=rts/Sim/Misc/ModInfo.cpp}}&lt;br /&gt;
&lt;br /&gt;
==Details==&lt;br /&gt;
&amp;lt;code&amp;gt;Modrules.lua&amp;lt;/code&amp;gt; is divided into several sub-tables containing tags specific to each section, as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===capture===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = energyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much of the original energy cost it requires to capture something.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===construction===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = constructionDecay&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Do uncompleted building frames begin to decay if no builder is working on them?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = constructionDecayTime&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 6.66&lt;br /&gt;
|description = The time in seconds before abandoned building frames begin to decay.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = constructionDecaySpeed&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.03&lt;br /&gt;
|description = How fast build progress decays for abandoned building frames. Note that the rate is inversely proportional to the {{xtaglink|Units-UnitDefs|buildtime}} i.e. a building with a larger {{xtaglink|Units-UnitDefs|buildtime}} will decay more slowly for a given value of this tag than a building with a shorter {{xtaglink|Units-UnitDefs|buildtime}}.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===experience===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = experienceMult&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Controls the amount of experience gained by units engaging in combat. The formulae used are: &lt;br /&gt;
::&amp;lt;code&amp;gt;xp for damage = 0.1 * experienceMult * damage / target_HP * target_power / attacker_power&amp;lt;/code&amp;gt; &lt;br /&gt;
::&amp;lt;code&amp;gt;xp for kill = 0.1 * experienceMult * target_power / attacker_power&amp;lt;/code&amp;gt;. &lt;br /&gt;
: Where {{xtaglink|Units-UnitDefs|power}} can be set by the UnitDef tag.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = powerScale&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Controls how gaining experience changes the relative {{xtaglink|Units-UnitDefs|power}} of the unit. The formula used is &amp;lt;code&amp;gt;Power multiplier = powerScale * (1 + xp / (xp + 1))&amp;lt;/code&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = healthScale&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.7&lt;br /&gt;
|description = Controls how gaining experience increases the {{xtaglink|Units-UnitDefs|maxDamage}} (total hitpoints) of the unit. The formula used is &amp;lt;code&amp;gt;Health multiplier = healthScale * (1 + xp / (xp + 1))&amp;lt;/code&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = reloadScale&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.4&lt;br /&gt;
|description = Controls how gaining experience decreases the {{xtaglink|Units-UnitDefs|reloadTime}} of the unit&#039;s weapons. The formula used is &amp;lt;code&amp;gt;Rate of fire multiplier = reloadScale * (1 + xp / (xp + 1))&amp;lt;/code&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===featureLOS===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = featureVisibility&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 3&lt;br /&gt;
|description = Controls the visibility of features. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - no default LOS for features, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Gaia features always visible, &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - allyteam &amp;amp; Gaia features always visible, or &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - all features always visible.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===fireAtDead===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = fireAtKilled&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Will units continue to target and fire on enemies which are running their &amp;lt;code&amp;gt;Killed()&amp;lt;/code&amp;gt; animation? (See [[Animation-LuaCallins#Generic]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = fireAtCrashing&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Will units continue to target and fire on enemy aircraft which are in the &#039;crashing&#039; state? (See [[Lua_SyncedCtrl#Unit_Control]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===flankingBonus===&lt;br /&gt;
For a deeper explanation of the flanking system, see [[Units:FlankingBonus]].&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = defaultMode&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = The default {{xtaglink|Units-UnitDefs|flankingBonusMode}} for units. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No flanking bonus. Mode &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; builds up the ability to move over time, and swings to face attacks, but does not respect the way the unit is facing. Mode &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; also can swing, but moves with the unit as it turns. Mode &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; stays with the unit as it turns and otherwise doesn&#039;t move, the ideal mode to simulate something such as tank armour. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====los====&lt;br /&gt;
{{tag&lt;br /&gt;
|name = losMipLevel&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = Controls the resolution of the LOS calculations. A higher value means lower resolution but increased performance. An increase by one level means half the resolution of the LOS map in both x and y direction. Must be between &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; inclusive.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = losMul&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Multiplies all unit&#039;s {{xtaglink|Units-UnitDefs|sightDistance}} by this value. Generally speaking you should always use the default.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = airMipLevel&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 2&lt;br /&gt;
|description = Controls the resolution of the LOS vs. aircraft calculations. A higher value means lower resolution but increased performance. An increase by one level means half the resolution of the air-LOS map in both x and y direction. Must be between &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt; inclusive.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = airLosMul&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Multiplies all unit&#039;s {{xtaglink|Units-UnitDefs|airSightDistance}} by this value. Generally speaking you should always use the default.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===movement===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowAirPlanesToLeaveMap&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Are (gunship) aircraft allowed to fly outside the bounds of the map?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowAircraftToHitGround&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|special = {{new|90.0}}&lt;br /&gt;
|description = Are aircraft allowed to hit the ground whilst manoeuvring?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowPushingEnemyUnits&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|83.0}}&lt;br /&gt;
|description = Can enemy ground units push each other during collisions?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowCrushingAlliedUnits&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|85.0}}&lt;br /&gt;
|description = Can allied ground units crush each other during collisions? Units still have to be explicitly set as crushable using the &amp;lt;code&amp;gt;crushable&amp;lt;/code&amp;gt; parameter of [[Lua_SyncedCtrl#Unit_Control|Spring.SetUnitBlocking]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowUnitCollisionDamage&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|85.0}}&lt;br /&gt;
|description = Do unit-unit (skidding) collisions cause damage?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowUnitCollisionOverlap&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|special = {{new|89.0}}&lt;br /&gt;
|description = Can mobile units collision volumes overlap one another? Allows unit movement like [http://www.youtube.com/watch?v=mRtePUdVk2o this (video)] at the cost of more &#039;clumping&#039;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowGroundUnitGravity&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|special = {{new|92.0}}&lt;br /&gt;
|description = Allows fast moving mobile units to &#039;catch air&#039; as they move over terrain.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowHoverUnitStrafing&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true if using QTPFS pathfinder&lt;br /&gt;
|special = {{new|92.0}}&lt;br /&gt;
|description = Allows hovercraft units to slide in turns.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = useClassicGroundMoveType&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|89.0}}&lt;br /&gt;
|description = A ticket back to unit movement circa 2009: no reversing, no {{xtaglink|Units-UnitDefs|turninplace|false}}, no smooth collision handling, no nothing. For comparison of pathfinding code.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===nanospray===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allow_team_colors&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Are players allowed to use teamcolour nanospray? Set by the &amp;lt;code&amp;gt;TeamNanoSpray&amp;lt;/code&amp;gt; key in the [[Springrc|config file]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===paralyze===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = paralyzeOnMaxHealth&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Are units paralyzed when the level of emp is greater than their current health or their maximum health?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===reclaim===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = multiReclaim&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 0&lt;br /&gt;
|description = Can multiple units reclaim a feature or only one? &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; implies the latter, all other values the former.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = reclaimMethod&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = Controls how features are reclaimed. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - gradual reclaim, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - all reclaimed at end, any other positive value &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; - reclaim in &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; chunks.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = unitMethod&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = Controls how units are reclaimed. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - gradual reclaim, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - all reclaimed at end, any other positive value &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; - reclaim in &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; chunks.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = featureEnergyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much energy should reclaiming a feature cost? Multiplier against the fraction of the features&#039; {{xtaglink|Units-FeatureDefs|metal}} content reclaimed.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = unitEnergyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much energy should reclaiming a unit cost? Multiplier against the fraction of the unit&#039;s {{xtaglink|Units-UnitDefs|buildCostEnergy}} reclaimed. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = unitEfficiency&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = How much metal should reclaiming a unit return? Multiplier against the unit&#039;s {{xtaglink|Units-UnitDefs|buildCostMetal}}.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowEnemies&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Can enemy units be reclaimed?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowAllies&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Can allied units be reclaimed?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===repair===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = energyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much of the original energy cost it requires to repair something.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===resurrect===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = energyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.5&lt;br /&gt;
|description = How much of the original energy cost it requires to resurrect something.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===sensors===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = requireSonarUnderWater&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; then when underwater, units only get LOS if they also have sonar.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===system===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = luaThreadingModel&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 2&lt;br /&gt;
|description = Controls if and how the game supports Asynchronous Simulation, a more detailed explanation can be found [[Asynchronous_Simulation#Lua_Threading_Models|here]]. Can be: &lt;br /&gt;
::&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No MT, single threaded; &lt;br /&gt;
::&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Single state; &lt;br /&gt;
::&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - Single state, batching of unsynced events; &lt;br /&gt;
::&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via EXPORT table and SendToUnsynced; &lt;br /&gt;
::&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via SendToUnsynced only; &lt;br /&gt;
::&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) via SendToUnsynced only; &lt;br /&gt;
::&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) is unmanaged and via SendToUnsynced only.}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = pathFinderSystem&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 0&lt;br /&gt;
|special={{new|85.0}}&lt;br /&gt;
|description = Which pathfinder does the game use? Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - The legacy default pathfinder or &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Quad-Tree Pathfinder System ([[QTPFS]]).}}&lt;br /&gt;
&lt;br /&gt;
===transportability===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportAir&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Can aircraft be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportShip&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Can ships be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportHover&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Can hovercraft be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportGround&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Can ground units be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = targetableTransportedUnits&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|89.0}}&lt;br /&gt;
|description = Can transported units be targeted by weapons? &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; allows both manual and automatic targeting.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
&lt;br /&gt;
===Empty===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;modrules.lua&amp;lt;/code&amp;gt; can simply return an empty table like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
return {}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
If you do this, Spring will use the default values.&lt;br /&gt;
&lt;br /&gt;
===Configurable by modoptions===&lt;br /&gt;
Interestingly &amp;lt;code&amp;gt;modrules.lua&amp;lt;/code&amp;gt; can read [[Modoptions.lua|modoptions]], so these parameters can be scripted to be configurable from the lobby.&lt;br /&gt;
For example to allow selecting either legacy default pathfinder or [[QTPFS]] via a modoption:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  system = {&lt;br /&gt;
    pathFinderSystem = (Spring.GetModOptions() and (Spring.GetModOptions().qtpfs == &amp;quot;1&amp;quot;) and 1) or 0,&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===External Examples===&lt;br /&gt;
[http://imolarpg.dyndns.org/trac/balatest/browser/trunk/gamedata/modrules.lua &#039;Balanced Annihilation&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://trac.caspring.org/browser/trunk/mods/ca/gamedata/modrules.lua &#039;Complete Annihilation&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://code.google.com/p/conflictterra/source/browse/games/CT/gamedata/modrules.lua &#039;Conflict Terra&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[https://code.google.com/p/evolutionrts/source/browse/trunk/evolutiondev.sdd/Gamedata/modrules.lua &#039;Evolution RTS&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://spring1944.svn.sourceforge.net/viewvc/spring1944/trunk/S44Main.sdd/gamedata/modrules.lua?&amp;amp;view=markup &#039;Spring: 1944&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://code.google.com/p/zero-k/source/browse/trunk/mods/zk/gamedata/modrules.lua &#039;ZeroK&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:gamedata]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Modrules.lua&amp;diff=14448</id>
		<title>Modrules.lua</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Modrules.lua&amp;diff=14448"/>
		<updated>2013-03-22T23:22:56Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* system */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Location==&lt;br /&gt;
&amp;lt;code&amp;gt;modrules.lua&amp;lt;/code&amp;gt; is a file in the &amp;lt;code&amp;gt;Gamedata/&amp;lt;/code&amp;gt; directory of a Spring game. &lt;br /&gt;
&lt;br /&gt;
==Purpose==&lt;br /&gt;
This file controls various global parameters of the game, for example how fast units gain experience, what unit types can be transported, how fine grained the LOS system is, etc.&lt;br /&gt;
&lt;br /&gt;
==Source==&lt;br /&gt;
The engine source code which parses the data from this file is viewable here:&lt;br /&gt;
&lt;br /&gt;
* {{sourcelink|file=rts/Sim/Misc/ModInfo.cpp}}&lt;br /&gt;
&lt;br /&gt;
==Details==&lt;br /&gt;
&amp;lt;code&amp;gt;Modrules.lua&amp;lt;/code&amp;gt; is divided into several sub-tables containing tags specific to each section, as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===capture===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = energyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much of the original energy cost it requires to capture something.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===construction===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = constructionDecay&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Do uncompleted building frames begin to decay if no builder is working on them?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = constructionDecayTime&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 6.66&lt;br /&gt;
|description = The time in seconds before abandoned building frames begin to decay.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = constructionDecaySpeed&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.03&lt;br /&gt;
|description = How fast build progress decays for abandoned building frames. Note that the rate is inversely proportional to the {{xtaglink|Units-UnitDefs|buildtime}} i.e. a building with a larger {{xtaglink|Units-UnitDefs|buildtime}} will decay more slowly for a given value of this tag than a building with a shorter {{xtaglink|Units-UnitDefs|buildtime}}.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===experience===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = experienceMult&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Controls the amount of experience gained by units engaging in combat. The formulae used are: &lt;br /&gt;
::&amp;lt;code&amp;gt;xp for damage = 0.1 * experienceMult * damage / target_HP * target_power / attacker_power&amp;lt;/code&amp;gt; &lt;br /&gt;
::&amp;lt;code&amp;gt;xp for kill = 0.1 * experienceMult * target_power / attacker_power&amp;lt;/code&amp;gt;. &lt;br /&gt;
: Where {{xtaglink|Units-UnitDefs|power}} can be set by the UnitDef tag.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = powerScale&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Controls how gaining experience changes the relative {{xtaglink|Units-UnitDefs|power}} of the unit. The formula used is &amp;lt;code&amp;gt;Power multiplier = powerScale * (1 + xp / (xp + 1))&amp;lt;/code&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = healthScale&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.7&lt;br /&gt;
|description = Controls how gaining experience increases the {{xtaglink|Units-UnitDefs|maxDamage}} (total hitpoints) of the unit. The formula used is &amp;lt;code&amp;gt;Health multiplier = healthScale * (1 + xp / (xp + 1))&amp;lt;/code&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = reloadScale&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.4&lt;br /&gt;
|description = Controls how gaining experience decreases the {{xtaglink|Units-UnitDefs|reloadTime}} of the unit&#039;s weapons. The formula used is &amp;lt;code&amp;gt;Rate of fire multiplier = reloadScale * (1 + xp / (xp + 1))&amp;lt;/code&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===featureLOS===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = featureVisibility&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 3&lt;br /&gt;
|description = Controls the visibility of features. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - no default LOS for features, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Gaia features always visible, &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - allyteam &amp;amp; Gaia features always visible, or &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - all features always visible.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===fireAtDead===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = fireAtKilled&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Will units continue to target and fire on enemies which are running their &amp;lt;code&amp;gt;Killed()&amp;lt;/code&amp;gt; animation? (See [[Animation-LuaCallins#Generic]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = fireAtCrashing&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Will units continue to target and fire on enemy aircraft which are in the &#039;crashing&#039; state? (See [[Lua_SyncedCtrl#Unit_Control]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===flankingBonus===&lt;br /&gt;
For a deeper explanation of the flanking system, see [[Units:FlankingBonus]].&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = defaultMode&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = The default {{xtaglink|Units-UnitDefs|flankingBonusMode}} for units. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No flanking bonus. Mode &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; builds up the ability to move over time, and swings to face attacks, but does not respect the way the unit is facing. Mode &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; also can swing, but moves with the unit as it turns. Mode &amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; stays with the unit as it turns and otherwise doesn&#039;t move, the ideal mode to simulate something such as tank armour. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====los====&lt;br /&gt;
{{tag&lt;br /&gt;
|name = losMipLevel&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = Controls the resolution of the LOS calculations. A higher value means lower resolution but increased performance. An increase by one level means half the resolution of the LOS map in both x and y direction. Must be between &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; inclusive.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = losMul&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Multiplies all unit&#039;s {{xtaglink|Units-UnitDefs|sightDistance}} by this value. Generally speaking you should always use the default.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = airMipLevel&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 2&lt;br /&gt;
|description = Controls the resolution of the LOS vs. aircraft calculations. A higher value means lower resolution but increased performance. An increase by one level means half the resolution of the air-LOS map in both x and y direction. Must be between &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;30&amp;lt;/code&amp;gt; inclusive.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = airLosMul&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = Multiplies all unit&#039;s {{xtaglink|Units-UnitDefs|airSightDistance}} by this value. Generally speaking you should always use the default.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===movement===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowAirPlanesToLeaveMap&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Are (gunship) aircraft allowed to fly outside the bounds of the map?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowAircraftToHitGround&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|special = {{new|90.0}}&lt;br /&gt;
|description = Are aircraft allowed to hit the ground whilst manoeuvring?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowPushingEnemyUnits&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|83.0}}&lt;br /&gt;
|description = Can enemy ground units push each other during collisions?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowCrushingAlliedUnits&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|85.0}}&lt;br /&gt;
|description = Can allied ground units crush each other during collisions? Units still have to be explicitly set as crushable using the &amp;lt;code&amp;gt;crushable&amp;lt;/code&amp;gt; parameter of [[Lua_SyncedCtrl#Unit_Control|Spring.SetUnitBlocking]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowUnitCollisionDamage&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|85.0}}&lt;br /&gt;
|description = Do unit-unit (skidding) collisions cause damage?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowUnitCollisionOverlap&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|special = {{new|89.0}}&lt;br /&gt;
|description = Can mobile units collision volumes overlap one another? Allows unit movement like [http://www.youtube.com/watch?v=mRtePUdVk2o this (video)] at the cost of more &#039;clumping&#039;.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowGroundUnitGravity&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|special = {{new|92.0}}&lt;br /&gt;
|description = Allows fast moving mobile units to &#039;catch air&#039; as they move over terrain.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowHoverUnitStrafing&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true if using QTPFS pathfinder&lt;br /&gt;
|special = {{new|92.0}}&lt;br /&gt;
|description = Allows hovercraft units to slide in turns.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = useClassicGroundMoveType&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|89.0}}&lt;br /&gt;
|description = A ticket back to unit movement circa 2009: no reversing, no {{xtaglink|Units-UnitDefs|turninplace|false}}, no smooth collision handling, no nothing. For comparison of pathfinding code.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===nanospray===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allow_team_colors&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Are players allowed to use teamcolour nanospray? Set by the &amp;lt;code&amp;gt;TeamNanoSpray&amp;lt;/code&amp;gt; key in the [[Springrc|config file]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===paralyze===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = paralyzeOnMaxHealth&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Are units paralyzed when the level of emp is greater than their current health or their maximum health?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===reclaim===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = multiReclaim&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 0&lt;br /&gt;
|description = Can multiple units reclaim a feature or only one? &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; implies the latter, all other values the former.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = reclaimMethod&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = Controls how features are reclaimed. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - gradual reclaim, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - all reclaimed at end, any other positive value &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; - reclaim in &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; chunks.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = unitMethod&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 1&lt;br /&gt;
|description = Controls how units are reclaimed. Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - gradual reclaim, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - all reclaimed at end, any other positive value &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; - reclaim in &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; chunks.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = featureEnergyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much energy should reclaiming a feature cost? Multiplier against the fraction of the features&#039; {{xtaglink|Units-FeatureDefs|metal}} content reclaimed.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = unitEnergyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much energy should reclaiming a unit cost? Multiplier against the fraction of the unit&#039;s {{xtaglink|Units-UnitDefs|buildCostEnergy}} reclaimed. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = unitEfficiency&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 1.0&lt;br /&gt;
|description = How much metal should reclaiming a unit return? Multiplier against the unit&#039;s {{xtaglink|Units-UnitDefs|buildCostMetal}}.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowEnemies&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Can enemy units be reclaimed?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = allowAllies&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Can allied units be reclaimed?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===repair===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = energyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.0&lt;br /&gt;
|description = How much of the original energy cost it requires to repair something.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===resurrect===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = energyCostFactor&lt;br /&gt;
|type = float&lt;br /&gt;
|default = 0.5&lt;br /&gt;
|description = How much of the original energy cost it requires to resurrect something.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===sensors===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = requireSonarUnderWater&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = If &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; then when underwater, units only get LOS if they also have sonar.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===system===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = luaThreadingModel&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 2&lt;br /&gt;
|description = Controls which Lua MT optimizations the mod will use by default, for a more detailed explanation see [[Asynchronous_Simulation#Lua_Threading_Models|here]]. Can be: &lt;br /&gt;
::&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No MT, single threaded; &lt;br /&gt;
::&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Single state; &lt;br /&gt;
::&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - Single state, batching of unsynced events; &lt;br /&gt;
::&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via EXPORT table and SendToUnsynced; &lt;br /&gt;
::&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via SendToUnsynced only; &lt;br /&gt;
::&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) via SendToUnsynced only; &lt;br /&gt;
::&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) is unmanaged and via SendToUnsynced only.}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = pathFinderSystem&lt;br /&gt;
|type = int&lt;br /&gt;
|default = 0&lt;br /&gt;
|special={{new|85.0}}&lt;br /&gt;
|description = Which pathfinder does the game use? Can be &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - The legacy default pathfinder or &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Quad-Tree Pathfinder System ([[QTPFS]]).}}&lt;br /&gt;
&lt;br /&gt;
===transportability===&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportAir&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Can aircraft be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportShip&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Can ships be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportHover&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|description = Can hovercraft be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = transportGround&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = true&lt;br /&gt;
|description = Can ground units be transported?&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{tag&lt;br /&gt;
|name = targetableTransportedUnits&lt;br /&gt;
|type = bool&lt;br /&gt;
|default = false&lt;br /&gt;
|special = {{new|89.0}}&lt;br /&gt;
|description = Can transported units be targeted by weapons? &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; allows both manual and automatic targeting.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
&lt;br /&gt;
===Empty===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;modrules.lua&amp;lt;/code&amp;gt; can simply return an empty table like this:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
return {}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
If you do this, Spring will use the default values.&lt;br /&gt;
&lt;br /&gt;
===Configurable by modoptions===&lt;br /&gt;
Interestingly &amp;lt;code&amp;gt;modrules.lua&amp;lt;/code&amp;gt; can read [[Modoptions.lua|modoptions]], so these parameters can be scripted to be configurable from the lobby.&lt;br /&gt;
For example to allow selecting either legacy default pathfinder or [[QTPFS]] via a modoption:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  system = {&lt;br /&gt;
    pathFinderSystem = (Spring.GetModOptions() and (Spring.GetModOptions().qtpfs == &amp;quot;1&amp;quot;) and 1) or 0,&lt;br /&gt;
  },&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===External Examples===&lt;br /&gt;
[http://imolarpg.dyndns.org/trac/balatest/browser/trunk/gamedata/modrules.lua &#039;Balanced Annihilation&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://trac.caspring.org/browser/trunk/mods/ca/gamedata/modrules.lua &#039;Complete Annihilation&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://code.google.com/p/conflictterra/source/browse/games/CT/gamedata/modrules.lua &#039;Conflict Terra&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[https://code.google.com/p/evolutionrts/source/browse/trunk/evolutiondev.sdd/Gamedata/modrules.lua &#039;Evolution RTS&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://spring1944.svn.sourceforge.net/viewvc/spring1944/trunk/S44Main.sdd/gamedata/modrules.lua?&amp;amp;view=markup &#039;Spring: 1944&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
[http://code.google.com/p/zero-k/source/browse/trunk/mods/zk/gamedata/modrules.lua &#039;ZeroK&#039; Modrules.lua]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:gamedata]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2271</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2271"/>
		<updated>2013-03-22T23:18:08Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Common side effects */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite the Lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better, with less side effects, but also requires more work. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered ASIM compatible, and will have &amp;lt;code&amp;gt;ASIM enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what call-ins the game and any user-enabled widgets implement. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2270</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2270"/>
		<updated>2013-03-22T23:15:49Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite the Lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better, with less side effects, but also requires more work. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered ASIM compatible, and will have &amp;lt;code&amp;gt;ASIM enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what call-ins the game and any user-enabled widgets implement. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2269</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2269"/>
		<updated>2013-03-22T23:14:35Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite the Lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better, with less side effects, but also requires more work. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered ASIM compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what call-ins the game and any user-enabled widgets implement. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2268</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2268"/>
		<updated>2013-03-22T23:08:54Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Steps required to support ASIM in your game */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite the Lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better, with less side effects, but also requires more work. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what call-ins the game and any user-enabled widgets implement. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2267</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2267"/>
		<updated>2013-03-22T23:06:49Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better, with less side effects, but also requires more work. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what call-ins the game and any user-enabled widgets implement. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2266</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2266"/>
		<updated>2013-03-22T23:03:22Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better, with less side effects, but also requires more work. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2265</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2265"/>
		<updated>2013-03-22T23:02:02Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Asynchronous Simulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2264</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2264"/>
		<updated>2013-03-22T23:01:10Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Asynchronous Simulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Asynchronous simulation (ASIM) allows the game physics simulation to run alongside the 3D graphics rendering on a dual core CPU or better. This gives higher performance, and allows the engine to maintain a high rendering frame rate (FPS) at all times even in big battles.&lt;br /&gt;
&lt;br /&gt;
Spring &amp;lt;code&amp;gt;disables ASIM by default&amp;lt;/code&amp;gt;, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Lua:Main&amp;diff=10887</id>
		<title>Lua:Main</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Lua:Main&amp;diff=10887"/>
		<updated>2013-03-22T16:48:47Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Other useful information */ link update&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; {{FULLPAGENAME}}&lt;br /&gt;
&lt;br /&gt;
=Lua FAQ=&lt;br /&gt;
[[Lua_Beginners_FAQ]]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://springrts.com/phpbb/viewtopic.php?f=23&amp;amp;t=15596 Forum topic with some basic information about gadgets]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://springrts.com/phpbb/viewtopic.php?f=23&amp;amp;t=16223 Forum topic with a manual on Spring lua scripting]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://answers.springlobby.info/ Q&amp;amp;A Site for Spring Developement]&lt;br /&gt;
&lt;br /&gt;
=Interfaces {{HeaderNotice|(last update: 0.82rc)}}=&lt;br /&gt;
[[:Category:Lua]] (shows which interfaces are loaded by LuaUI,LuaRules,etc.)&amp;lt;br&amp;gt;&lt;br /&gt;
{{LuaInterfaces}}&lt;br /&gt;
&lt;br /&gt;
=Tutorials=&lt;br /&gt;
* [[LuaTutorials::InterCommunications]] (i.e. synced &amp;lt;-&amp;gt; unsynced communications)&lt;br /&gt;
&lt;br /&gt;
=Other useful information=&lt;br /&gt;
* [[LuaCallinReturn]]&lt;br /&gt;
* [[Lua_Performance | Lua performance tips]]&lt;br /&gt;
* [[Asynchronous_Simulation | Asynchronous Simulation and Lua]]&lt;br /&gt;
* [http://spring.clan-sy.com/wiki/COB_Constants#Custom_Variables COB Custom Variables]&lt;br /&gt;
* [http://springrts.com/phpbb/viewtopic.php?f=12&amp;amp;t=19560 Font Drawing System]&lt;br /&gt;
* [[UI_commands]]&lt;br /&gt;
* [[Animation-LuaScripting | Unit animation scripting with Lua]]&lt;br /&gt;
* [[LUA ComonPitfalls]]&lt;br /&gt;
* [[LuaSocket]]&lt;br /&gt;
&lt;br /&gt;
=Official Lua documentation=&lt;br /&gt;
[http://www.lua.org/pil/ &#039;Programming in Lua&#039; book online]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.lua.org/manual/5.1/ Lua 5.1 Reference manual]&amp;lt;br&amp;gt;&lt;br /&gt;
[http://lua-users.org/wiki/TutorialDirectory Lua tutorials]&lt;br /&gt;
[[Category: Lua]]&lt;br /&gt;
&lt;br /&gt;
=Widget Database=&lt;br /&gt;
[[WidgetDatabaseFAQ]]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://widgets.springrts.de/ Web-Interface]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2263</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2263"/>
		<updated>2013-03-22T16:21:17Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Asynchronous Simulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Spring disables asynchronous simulation (ASIM) by default, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous Lua related side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2262</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2262"/>
		<updated>2013-03-22T16:20:18Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Compatibility for Asynchronous Simulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Asynchronous Simulation ==&lt;br /&gt;
Spring disables asynchronous simulation (ASIM) by default, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_Multithreaded_Lua&amp;diff=17254</id>
		<title>Spring Multithreaded Lua</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Spring_Multithreaded_Lua&amp;diff=17254"/>
		<updated>2013-03-22T16:19:19Z</updated>

		<summary type="html">&lt;p&gt;Zerver: Zerver moved page Spring Multithreaded Lua to Asynchronous Simulation: better name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Asynchronous Simulation]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2261</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2261"/>
		<updated>2013-03-22T16:19:19Z</updated>

		<summary type="html">&lt;p&gt;Zerver: Zerver moved page Spring Multithreaded Lua to Asynchronous Simulation: better name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Lua Compatibility for Asynchronous Simulation ==&lt;br /&gt;
Spring disables asynchronous simulation (ASIM) by default, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2260</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2260"/>
		<updated>2013-03-22T16:13:11Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Lua Compatibility for Asynchronous Simulation ==&lt;br /&gt;
Spring disables asynchronous simulation (ASIM) by default, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
::For reference only, this mode should never be used in practice&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2259</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2259"/>
		<updated>2013-03-22T02:22:07Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Common side effects */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Lua Compatibility for Asynchronous Simulation ==&lt;br /&gt;
Spring disables asynchronous simulation (ASIM) by default, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined if ASIM is enabled. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2258</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2258"/>
		<updated>2013-03-22T02:07:35Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Lua Compatibility for Asynchronous Simulation ==&lt;br /&gt;
Spring disables asynchronous simulation (ASIM) by default, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined in MT Spring. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2257</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2257"/>
		<updated>2013-03-22T02:00:45Z</updated>

		<summary type="html">&lt;p&gt;Zerver: major rewrite for ASIM&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Lua Compatibility for Asynchronous Simulation ==&lt;br /&gt;
Spring disables asynchronous simulation (ASIM) by default, unless a game has been specifically designed to support it. The reason is that ASIM gives rise to numerous side effects that can be a bit hard to understand, especially for a game designer who has little experience with threaded programming.&lt;br /&gt;
&lt;br /&gt;
== Steps required to support ASIM in your game ==&lt;br /&gt;
:&#039;&#039;&#039;1.&#039;&#039;&#039; Choose a Lua Threading Model &amp;gt; 2 below&lt;br /&gt;
:&#039;&#039;&#039;2.&#039;&#039;&#039; Rewrite your lua code to conform with the rules imposed by that threading model&lt;br /&gt;
:&#039;&#039;&#039;3.&#039;&#039;&#039; Learn about the side effects of the model chosen and tweak your code to work around it&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better with Spring MT. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. No MT, single threaded&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;. Single state&#039;&#039;&#039;&lt;br /&gt;
::This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;. Single state, batching of unsynced events &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
::This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&lt;br /&gt;
::All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&lt;br /&gt;
::The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&lt;br /&gt;
::This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&lt;br /&gt;
::With this mode, it is illegal to invoke LuaUI from another Lua environment (LuaGaia or LuaRules). This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Unfortunately there is no other solution than to stop using the call-in that throws the error, or to use a higher threading model.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via EXPORT table and SendToUnsynced&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;. Dual states for synced, batching of unsynced events, synced/unsynced communication&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt;. Dual states for all, all synced/unsynced communication (widgets included)&#039;&#039;&#039;&lt;br /&gt;
::&#039;&#039;&#039;is unmanaged and via SendToUnsynced only&#039;&#039;&#039;&lt;br /&gt;
::Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&lt;br /&gt;
&lt;br /&gt;
== Common side effects ==&lt;br /&gt;
:&#039;&#039;&#039;1. Out-of-order execution&#039;&#039;&#039;, applies to all threading models&lt;br /&gt;
::All rendering call-ins (Draw*, Update, Mouse/Keyboard) must be designed so that they work correctly even if objects are deleted (and possibly replaced by another object with same ID) in between the rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;2. Performance hit for rendering call-ins in gadgets&#039;&#039;&#039;, applies to threading models &amp;lt; 3&lt;br /&gt;
::Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined in MT Spring. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist. If the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;3. Batching glitches&#039;&#039;&#039;, applies to threading models 2 - 4&lt;br /&gt;
::For example, a widget that processes an UnitEnteredLOS event cannot safely make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this type of issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2256</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2256"/>
		<updated>2013-03-22T00:48:58Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring Multithreaded Lua Compatibility ==&lt;br /&gt;
In order to make your Lua code compatible with asynchronous simulation (ASIM), you need to follow certain rules. The rules apply to any code run by a rendering thread, which means all DrawXXX call-ins plus the Update call-in. UI call-ins (mouse/keyboard etc) are also run by the rendering thread.&lt;br /&gt;
&lt;br /&gt;
== All versions ==&lt;br /&gt;
Lua code must be designed so that it works even if objects are deleted (and possibly replaced by another object with same ID) in between &#039;&#039;&#039;any&#039;&#039;&#039; rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
== 0.82.X ==&lt;br /&gt;
Unfortunately, Spring MT has very limited Lua rendering support in this engine version, and it carries a huge negative performance impact. Especially time-consuming rendering such as looping through a set of units and drawing something for each one, must be avoided.&lt;br /&gt;
&lt;br /&gt;
Only the rendering thread may use Lua OpenGL stuff, so you must be careful not to create e.g. display lists in the wrong call-ins.&lt;br /&gt;
&lt;br /&gt;
There are also numerous related bugs in this version, that could turn your coding job into a trial-and-error nightmare. Deadlocks and crashes can be expected.&lt;br /&gt;
&lt;br /&gt;
== 83.0+ ==&lt;br /&gt;
Rendering in a gadget can - depending on the threading model (see below) - negatively affect the performance, although the performance penalty is less severe compared to in the previous engine version. Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined in MT Spring. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist.&lt;br /&gt;
&lt;br /&gt;
Depending on the threading model (see below) - batching mechanisms can also produce some side effects. For example, a widget that processes an UnitEnteredLOS event cannot make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
Finally, if the threading model (see below) is set to mode(2), it is illegal to invoke LuaUI from another Lua environment. This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Update the game to use a threading model &amp;gt; 2 to resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better with Spring MT. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No MT, single threaded; &lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Single state; &lt;br /&gt;
::&#039;&#039;This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - Single state, batching of unsynced events; &amp;lt;code&amp;gt;(default mode)&amp;lt;/code&amp;gt;&lt;br /&gt;
::&#039;&#039;This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&#039;&#039;&lt;br /&gt;
::&#039;&#039;All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&#039;&#039; &lt;br /&gt;
::&#039;&#039;The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&#039;&#039;&lt;br /&gt;
::&#039;&#039;This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via EXPORT table and SendToUnsynced;&lt;br /&gt;
::&#039;&#039;Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) is unmanaged and via SendToUnsynced only.&lt;br /&gt;
::&#039;&#039;Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Which mode to use?&#039;&#039;&#039; The default mode(2) is usually good enough unless you need rendering gadgets. Extreme lightweight rendering gadgets may be OK, but if the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem, especially if the value displayed is higher than 1%. If you write a new widget/gadget, consider designing it to be compatible with a higher mode.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2255</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2255"/>
		<updated>2013-03-22T00:42:26Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring Multithreaded Lua Compatibility ==&lt;br /&gt;
In order to make your Lua code compatible with asynchronous simulation (ASIM), you need to follow certain rules. The rules apply to any code run by a rendering thread, which means all DrawXXX call-ins plus the Update call-in. UI call-ins (mouse/keyboard etc) are also run by the rendering thread.&lt;br /&gt;
&lt;br /&gt;
== All versions ==&lt;br /&gt;
Lua code must be designed so that it works even if objects are deleted (and possibly replaced by another object with same ID) in between &#039;&#039;&#039;any&#039;&#039;&#039; rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
== 0.82.X ==&lt;br /&gt;
Unfortunately, Spring MT has very limited Lua rendering support in this engine version, and it carries a huge negative performance impact. Especially time-consuming rendering such as looping through a set of units and drawing something for each one, must be avoided.&lt;br /&gt;
&lt;br /&gt;
Only the rendering thread may use Lua OpenGL stuff, so you must be careful not to create e.g. display lists in the wrong call-ins.&lt;br /&gt;
&lt;br /&gt;
There are also numerous related bugs in this version, that could turn your coding job into a trial-and-error nightmare. Deadlocks and crashes can be expected.&lt;br /&gt;
&lt;br /&gt;
== 83.0+ ==&lt;br /&gt;
Rendering in a gadget can - depending on the threading model (see below) - negatively affect the performance, although the performance penalty is less severe compared to in the previous engine version. Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined in MT Spring. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist.&lt;br /&gt;
&lt;br /&gt;
Depending on the threading model (see below) - batching mechanisms can also produce some side effects. For example, a widget that processes an UnitEnteredLOS event cannot make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
Finally, if the threading model (see below) is set to mode(2), it is illegal to invoke LuaUI from another Lua environment. This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Update the game to use a threading model &amp;gt; 2 to resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better with Spring MT. A game that specifies &amp;lt;code&amp;gt;luaThreadingModel &amp;gt; 2&amp;lt;/code&amp;gt; will be considered asynchronous simulation (ASIM) compatible, and will have the &amp;lt;code&amp;gt;simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No MT, single threaded; &lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Single state; &lt;br /&gt;
::&#039;&#039;This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - Single state, batching of unsynced events;&lt;br /&gt;
::&#039;&#039;This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&#039;&#039;&lt;br /&gt;
::&#039;&#039;All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&#039;&#039; &lt;br /&gt;
::&#039;&#039;The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&#039;&#039;&lt;br /&gt;
::&#039;&#039;This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via EXPORT table and SendToUnsynced;&lt;br /&gt;
::&#039;&#039;Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) is unmanaged and via SendToUnsynced only.&lt;br /&gt;
::&#039;&#039;Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Which mode to use?&#039;&#039;&#039; The default mode(2) is usually good enough unless you need rendering gadgets. Extreme lightweight rendering gadgets may be OK, but if the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem, especially if the value displayed is higher than 1%. If you write a new widget/gadget, consider designing it to be compatible with a higher mode.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2254</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2254"/>
		<updated>2013-03-22T00:38:00Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring Multithreaded Lua Compatibility ==&lt;br /&gt;
In order to make your Lua code compatible with asynchronous simulation (ASIM), you need to follow certain rules. The rules apply to any code run by a rendering thread, which means all DrawXXX call-ins plus the Update call-in. UI call-ins (mouse/keyboard etc) are also run by the rendering thread.&lt;br /&gt;
&lt;br /&gt;
== All versions ==&lt;br /&gt;
Lua code must be designed so that it works even if objects are deleted (and possibly replaced by another object with same ID) in between &#039;&#039;&#039;any&#039;&#039;&#039; rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
== 0.82.X ==&lt;br /&gt;
Unfortunately, Spring MT has very limited Lua rendering support in this engine version, and it carries a huge negative performance impact. Especially time-consuming rendering such as looping through a set of units and drawing something for each one, must be avoided.&lt;br /&gt;
&lt;br /&gt;
Only the rendering thread may use Lua OpenGL stuff, so you must be careful not to create e.g. display lists in the wrong call-ins.&lt;br /&gt;
&lt;br /&gt;
There are also numerous related bugs in this version, that could turn your coding job into a trial-and-error nightmare. Deadlocks and crashes can be expected.&lt;br /&gt;
&lt;br /&gt;
== 83.0+ ==&lt;br /&gt;
Rendering in a gadget can - depending on the threading model (see below) - negatively affect the performance, although the performance penalty is less severe compared to in the previous engine version. Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined in MT Spring. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist.&lt;br /&gt;
&lt;br /&gt;
Depending on the threading model (see below) - batching mechanisms can also produce some side effects. For example, a widget that processes an UnitEnteredLOS event cannot make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
Finally, if the threading model (see below) is set to mode(2), it is illegal to invoke LuaUI from another Lua environment. This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Update the game to use a threading model &amp;gt; 2 to resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better with Spring MT. &amp;lt;code&amp;gt;A game that specifies luaThreadingModel &amp;gt; 2 will be considered asynchronous simulation (ASIM) compatible, and will have the simulation thread enabled by default.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No MT, single threaded; &lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Single state; &lt;br /&gt;
::&#039;&#039;This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - Single state, batching of unsynced events;&lt;br /&gt;
::&#039;&#039;This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&#039;&#039;&lt;br /&gt;
::&#039;&#039;All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&#039;&#039; &lt;br /&gt;
::&#039;&#039;The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&#039;&#039;&lt;br /&gt;
::&#039;&#039;This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via EXPORT table and SendToUnsynced;&lt;br /&gt;
::&#039;&#039;Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) is unmanaged and via SendToUnsynced only.&lt;br /&gt;
::&#039;&#039;Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Which mode to use?&#039;&#039;&#039; The default mode(2) is usually good enough unless you need rendering gadgets. Extreme lightweight rendering gadgets may be OK, but if the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem, especially if the value displayed is higher than 1%. If you write a new widget/gadget, consider designing it to be compatible with a higher mode.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2253</id>
		<title>Asynchronous Simulation</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Asynchronous_Simulation&amp;diff=2253"/>
		<updated>2013-03-21T23:52:58Z</updated>

		<summary type="html">&lt;p&gt;Zerver: /* Lua Threading Models */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Spring Multithreaded Lua Compatibility ==&lt;br /&gt;
In order to make your Lua code compatible with asynchronous simulation (ASIM), you need to follow certain rules. The rules apply to any code run by a rendering thread, which means all DrawXXX call-ins plus the Update call-in. UI call-ins (mouse/keyboard etc) are also run by the rendering thread.&lt;br /&gt;
&lt;br /&gt;
== All versions ==&lt;br /&gt;
Lua code must be designed so that it works even if objects are deleted (and possibly replaced by another object with same ID) in between &#039;&#039;&#039;any&#039;&#039;&#039; rendering call-ins. This means rendering code that stores lists of e.g. units in global variables must update these according to UnitCreated/UnitDestroyed events or re-check the units for validity before use. Keep in mind that if an object has been replaced, the operation that you intended to perform may no longer be valid for the new object.&lt;br /&gt;
&lt;br /&gt;
== 0.82.X ==&lt;br /&gt;
Unfortunately, Spring MT has very limited Lua rendering support in this engine version, and it carries a huge negative performance impact. Especially time-consuming rendering such as looping through a set of units and drawing something for each one, must be avoided.&lt;br /&gt;
&lt;br /&gt;
Only the rendering thread may use Lua OpenGL stuff, so you must be careful not to create e.g. display lists in the wrong call-ins.&lt;br /&gt;
&lt;br /&gt;
There are also numerous related bugs in this version, that could turn your coding job into a trial-and-error nightmare. Deadlocks and crashes can be expected.&lt;br /&gt;
&lt;br /&gt;
== 83.0+ ==&lt;br /&gt;
Rendering in a gadget can - depending on the threading model (see below) - negatively affect the performance, although the performance penalty is less severe compared to in the previous engine version. Avoid writing any time-consuming rendering code in a gadget. The easy way out is to let a widget do the rendering instead. The gadget can send a message to the widget by calling Script.LuaUI.XXX(), but the value returned from this call is undefined in MT Spring. Similarly, the result obtained when checking for the existence of a Script.LuaUI.XXX function can be unpredictable, instead the widget may send a LuaRules message to indicate that the function now exists or has ceased to exist.&lt;br /&gt;
&lt;br /&gt;
Depending on the threading model (see below) - batching mechanisms can also produce some side effects. For example, a widget that processes an UnitEnteredLOS event cannot make any assumptions about the unit actually being in LOS. Because of batching delay, it may have left LOS already when the message is processed, and an attempt to get further info about the unit may therefore fail, since access to out-of-LOS units is restricted. Numerous events are more or less affected by this issue. Batch management is expensive, making it very difficult to solve this problem engine side.&lt;br /&gt;
&lt;br /&gt;
Finally, if the threading model (see below) is set to mode(2), it is illegal to invoke LuaUI from another Lua environment. This can happen depending on what features (call-ins) the game implements, and what widgets the user has activated. If such an attempt to invoke LuaUI is detected, it will be skipped to prevent a deadlock, and a warning will also be printed in the console. Update the game to use a threading model &amp;gt; 2 to resolve the issue.&lt;br /&gt;
&lt;br /&gt;
== Lua Threading Models==&lt;br /&gt;
These modes can be set for a game using &amp;lt;code&amp;gt;luaThreadingModel&amp;lt;/code&amp;gt; in [[Modrules.lua#system|Modrules.lua]]. The engine can override with the setting &amp;lt;code&amp;gt;MultiThreadLua&amp;lt;/code&amp;gt;. A higher mode generally means that the game will perform better with Spring MT. &#039;&#039;A game that specifies luaThreadingModel &amp;gt; 2 will be considered asynchronous simulation (ASIM) compatible, and will have the ASIM enabled by default.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; - No MT, single threaded; &lt;br /&gt;
:&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; - Single state; &lt;br /&gt;
::&#039;&#039;This mode has a single Lua environment for everything. It will cause a significant slowdown because simulation and rendering threads block each other trying to access the shared Lua environment. Especially problematic is Lua rendering; being inherently time consuming (looping through large amounts of units etc.) it will force the simulation thread to wait. This gives rise to the classic phenomenon of having incredibly high FPS but still lagging behind (high ping) since simulation cannot keep up with the normal pace.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; - Single state, batching of unsynced events;&lt;br /&gt;
::&#039;&#039;This mode is considerably better than mode(1) since it has a separate Lua environment for LuaUI.&#039;&#039;&lt;br /&gt;
::&#039;&#039;All simulation events sent to LuaUI are also batched/delayed to reduce the need for the threads to block each other. For instance, if simulation triggers UnitMoved(), the event will not reach LuaUI right away, but is put in a batch and handled as soon as possible by the rendering thread. The batching system is managed, i.e. if the unit that triggered UnitMoved is about to be deleted (and thus invalidated) the batch is forcefully run before deletion occurs. Because the forced batch run is performed by the simulation thread, locking is required and this can degrade simulation performance for the same reasons as in mode(1).&#039;&#039; &lt;br /&gt;
::&#039;&#039;The other means of unsynced communication, SendToUnsynced and Script.LuaUI.XXX() are also batched and managed to make sure any object ID or such sent are still valid once the message arrives. Note: Script.LuaUI.XXX() does because of the batching NOT have a return value.&#039;&#039;&lt;br /&gt;
::&#039;&#039;This mode unfortunately suffers the same problems as mode(1) for rendering gadgets, since simulation events must be sent to the gadgets directly (without batching) in order not to desync the game.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;3&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via EXPORT table and SendToUnsynced;&lt;br /&gt;
::&#039;&#039;Same as mode(2), but the gadgets have separate Lua environments depending on whether the simulation or rendering thread is invoking it. This alleviates the negative performance impact for rendering gadgets, but makes it impossible to directly share synced gadget data to the unsynced part via _G --&amp;gt; SYNCED. To work around this limitation, this mode introduces _G.EXPORT that is automatically copied to SYNCED.EXPORT. Only small amounts of data should be stored in the EXPORT table, because the copying is performed very frequently. Cyclical and/or very deeply nested tables are not allowed. Larger data can be stored temporarily, e.g.&lt;br /&gt;
::_G.EXPORT.myhugetable = huge_table&lt;br /&gt;
::SendToUnsynced(&amp;quot;huge_table_available&amp;quot;)&lt;br /&gt;
::_G.EXPORT.myhugetable = nil&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt; - Dual states for synced, batching of unsynced events, synced/unsynced communication via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(3) but with the EXPORT table disabled to increase the performance further. You don&#039;t need EXPORT, SendToUnsynced alone is sufficient.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;5&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) via SendToUnsynced only;&lt;br /&gt;
::&#039;&#039;Same as mode(4), but adds separate Lua environments for LuaUI depending on whether the simulation or rendering thread is invoking it. With dual LuaUI states, batching is no longer needed and therefore disabled. This makes it even faster, since batching overhead is eliminated and forced batch runs (see mode(2)) are not needed. However, this mode adds significant complexity for the programmer, since essentially two instances of the same widget are run, and only the calling thread determines which one is invoked. As a rule of thumb, all simulation events (GameFrame etc.) are invoked by the simulation thread. All UI and rendering events and Update() are invoked by the rendering thread. So, if a variable is modified in GameFrame(), that change cannot be seen in Update(). The widget must instead use SendToUnsynced to communicate any data from the simulation widget instance to the rendering widget instance. Design wise it may be suitable to write the widget similarly to a gadget, with clearly separated &amp;quot;synced&amp;quot; and &amp;quot;unsynced&amp;quot; parts, each with their own variables, functions and call-ins.&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; - Dual states for all, all synced/unsynced communication (widgets included) is unmanaged and via SendToUnsynced only.&lt;br /&gt;
::&#039;&#039;Same as mode(5) but the SendToUnsynced and Script.LuaUI.XXX() communication is unmanaged. The Lua coder must manually check if object references sent are still valid when the message arrives.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Which mode to use?&#039;&#039;&#039; The default mode(2) is usually good enough unless you need rendering gadgets. Extreme lightweight rendering gadgets may be OK, but if the LUA-SYNC-CPU indicator appears in the upper right part of the window it usually indicates a performance problem, especially if the value displayed is higher than 1%. If you write a new widget/gadget, consider designing it to be compatible with a higher mode.&lt;br /&gt;
&lt;br /&gt;
[[Category:Lua]]&lt;/div&gt;</summary>
		<author><name>Zerver</name></author>
	</entry>
</feed>