<?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=Meriton</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=Meriton"/>
	<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/wiki/Special:Contributions/Meriton"/>
	<updated>2026-11-08T18:44:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.11</generator>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=653</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=653"/>
		<updated>2014-05-19T18:43:30Z</updated>

		<summary type="html">&lt;p&gt;Meriton: /* Building a metal extractor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
Whenever a unit has been built, the engine sends a unitFinished event. At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit) {&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;)) {&lt;br /&gt;
        commander = unit;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commands are issued by invoking the respective method on the &amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;). In our case, that&#039;s the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; method, which takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;UnitDef toBuildUnitDef&amp;lt;/code&amp;gt;: the kind of unit to build&lt;br /&gt;
* &amp;lt;code&amp;gt;AIFLoat3 buildPos&amp;lt;/code&amp;gt;: the location the unit should be built at (in our case, we use the commander&#039;s current position)&lt;br /&gt;
* &amp;lt;code&amp;gt;int facing&amp;lt;/code&amp;gt;: the direction the new unit will be facing (mostly matters for buildings, which can not turn after being constructed)&lt;br /&gt;
* &amp;lt;code&amp;gt;short options&amp;lt;/code&amp;gt;: a set of UnitCommandOptions. 0 means no option.&lt;br /&gt;
* &amp;lt;code&amp;gt;int timeout&amp;lt;/code&amp;gt;: the number of frames after which the command times out. We don&#039;t want a timeout, and therefore specify a suitably high number :-)&lt;br /&gt;
&lt;br /&gt;
Therefore, our command looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    commander.build(solarDef, commander.getPos(), 0, (short) 0, Integer.MAX_VALUE);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       commander.build(metalExtractor, closestspot, 0, (short) 0, Integer.MAX_VALUE);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=652</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=652"/>
		<updated>2014-05-19T18:42:52Z</updated>

		<summary type="html">&lt;p&gt;Meriton: /* Building a metal extractor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
Whenever a unit has been built, the engine sends a unitFinished event. At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit) {&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;)) {&lt;br /&gt;
        commander = unit;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commands are issued by invoking the respective method on the &amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;). In our case, that&#039;s the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; method, which takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;UnitDef toBuildUnitDef&amp;lt;/code&amp;gt;: the kind of unit to build&lt;br /&gt;
* &amp;lt;code&amp;gt;AIFLoat3 buildPos&amp;lt;/code&amp;gt;: the location the unit should be built at (in our case, we use the commander&#039;s current position)&lt;br /&gt;
* &amp;lt;code&amp;gt;int facing&amp;lt;/code&amp;gt;: the direction the new unit will be facing (mostly matters for buildings, which can not turn after being constructed)&lt;br /&gt;
* &amp;lt;code&amp;gt;short options&amp;lt;/code&amp;gt;: a set of UnitCommandOptions. 0 means no option.&lt;br /&gt;
* &amp;lt;code&amp;gt;int timeout&amp;lt;/code&amp;gt;: the number of frames after which the command times out. We don&#039;t want a timeout, and therefore specify a suitably high number :-)&lt;br /&gt;
&lt;br /&gt;
Therefore, our command looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    commander.build(solarDef, commander.getPos(), 0, (short) 0, Integer.MAX_VALUE);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       commander.build(metalExtractor, closestSpot, 0, (short) 0, Integer.MAX_VALUE);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=651</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=651"/>
		<updated>2014-05-18T20:44:38Z</updated>

		<summary type="html">&lt;p&gt;Meriton: /* Telling the commander to build the solar plant */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
Whenever a unit has been built, the engine sends a unitFinished event. At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit) {&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;)) {&lt;br /&gt;
        commander = unit;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commands are issued by invoking the respective method on the &amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;). In our case, that&#039;s the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; method, which takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;UnitDef toBuildUnitDef&amp;lt;/code&amp;gt;: the kind of unit to build&lt;br /&gt;
* &amp;lt;code&amp;gt;AIFLoat3 buildPos&amp;lt;/code&amp;gt;: the location the unit should be built at (in our case, we use the commander&#039;s current position)&lt;br /&gt;
* &amp;lt;code&amp;gt;int facing&amp;lt;/code&amp;gt;: the direction the new unit will be facing (mostly matters for buildings, which can not turn after being constructed)&lt;br /&gt;
* &amp;lt;code&amp;gt;short options&amp;lt;/code&amp;gt;: a set of UnitCommandOptions. 0 means no option.&lt;br /&gt;
* &amp;lt;code&amp;gt;int timeout&amp;lt;/code&amp;gt;: the number of frames after which the command times out. We don&#039;t want a timeout, and therefore specify a suitably high number :-)&lt;br /&gt;
&lt;br /&gt;
Therefore, our command looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    commander.build(solarDef, commander.getPos(), 0, (short) 0, Integer.MAX_VALUE);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=650</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=650"/>
		<updated>2014-05-18T20:43:46Z</updated>

		<summary type="html">&lt;p&gt;Meriton: /* Getting a reference to the commander */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
Whenever a unit has been built, the engine sends a unitFinished event. At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit) {&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;)) {&lt;br /&gt;
        commander = unit;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commands are issued by invoking the respective method on the &amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;. In our case, that&#039;s the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; method, which takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;UnitDef toBuildUnitDef&amp;lt;/code&amp;gt;: the kind of unit to build&lt;br /&gt;
* &amp;lt;code&amp;gt;AIFLoat3 buildPos&amp;lt;/code&amp;gt;: the location the unit should be built at (in our case, we use the commander&#039;s current position)&lt;br /&gt;
* &amp;lt;code&amp;gt;int facing&amp;lt;/code&amp;gt;: the direction the new unit will be facing (mostly matters for buildings, which can not turn after being constructed)&lt;br /&gt;
* &amp;lt;code&amp;gt;short options&amp;lt;/code&amp;gt;: a set of UnitCommandOptions. 0 means no option.&lt;br /&gt;
* &amp;lt;code&amp;gt;int timeout&amp;lt;/code&amp;gt;: the number of frames after which the command times out. We don&#039;t want a timeout, and therefore specify a suitably high number :-)&lt;br /&gt;
&lt;br /&gt;
Therefore, our command looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    commander.build(solarDef, commander.getPos(), 0, (short) 0, Integer.MAX_VALUE);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=649</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=649"/>
		<updated>2014-05-18T20:42:58Z</updated>

		<summary type="html">&lt;p&gt;Meriton: Removed the command stuff (commands no longer exist)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
Whenever a unit has been built, the engine sends a unitFinished event. At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit) {&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;)) {&lt;br /&gt;
        Unit commander = unit;&lt;br /&gt;
&lt;br /&gt;
        // do something with the commander here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commands are issued by invoking the respective method on the &amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;. In our case, that&#039;s the &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; method, which takes the following arguments:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;UnitDef toBuildUnitDef&amp;lt;/code&amp;gt;: the kind of unit to build&lt;br /&gt;
* &amp;lt;code&amp;gt;AIFLoat3 buildPos&amp;lt;/code&amp;gt;: the location the unit should be built at (in our case, we use the commander&#039;s current position)&lt;br /&gt;
* &amp;lt;code&amp;gt;int facing&amp;lt;/code&amp;gt;: the direction the new unit will be facing (mostly matters for buildings, which can not turn after being constructed)&lt;br /&gt;
* &amp;lt;code&amp;gt;short options&amp;lt;/code&amp;gt;: a set of UnitCommandOptions. 0 means no option.&lt;br /&gt;
* &amp;lt;code&amp;gt;int timeout&amp;lt;/code&amp;gt;: the number of frames after which the command times out. We don&#039;t want a timeout, and therefore specify a suitably high number :-)&lt;br /&gt;
&lt;br /&gt;
Therefore, our command looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    commander.build(solarDef, commander.getPos(), 0, (short) 0, Integer.MAX_VALUE);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=648</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=648"/>
		<updated>2014-05-18T20:23:44Z</updated>

		<summary type="html">&lt;p&gt;Meriton: Shorter example (if people don&amp;#039;t know what a field is, they won&amp;#039;t be having much luck coding an ai, so it&amp;#039;s pointless repeating this here)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
Whenever a unit has been built, the engine sends a unitFinished event. At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit) {&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;)) {&lt;br /&gt;
        Unit commander = unit;&lt;br /&gt;
&lt;br /&gt;
        // do something with the commander here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Giving a command is straightforward. All we need to do is to create the appropriate command object and pass it through the callback to the engine.&lt;br /&gt;
&lt;br /&gt;
EDIT: the command class is outdated and not included in the current oo wrapper. Commands are now given via the unit class. See: http://spring.abma.de/doc-Interface-JavaOO/com/springrts/ai/oo/clb/Unit.html&lt;br /&gt;
&lt;br /&gt;
The command we need to tell commander to build a solar plant is a &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt;. This command takes a number of arguments:&lt;br /&gt;
&lt;br /&gt;
; Unit unit : the unit we want to give to order to&lt;br /&gt;
; int groupId : the group we want to give the order to&lt;br /&gt;
; List&amp;lt;AICommand.Option&amp;gt; optionsList : a list addional options. See the values of AICommand.Option for details&lt;br /&gt;
; int timeOut : the number of frames after which the command times out&lt;br /&gt;
; UnitDef toBuildUnitDef : the UnitDef of the unit we want to build&lt;br /&gt;
; AIFloat3 buildPos : the position to build the unit at&lt;br /&gt;
; int facing : the direction the new unit should face&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see above, we can give a command to either a single unit or a group of units. In this example we only have a single unit. This means that unit should be a reference to our commander, and &amp;lt;code&amp;gt;groupId&amp;lt;/code&amp;gt; should be -1.&lt;br /&gt;
To keep things simple, we will not use any options, set the timeout to a large number, and set facing to 0.&lt;br /&gt;
The value of &amp;lt;code&amp;gt;toBuildUnitDef&amp;lt;/code&amp;gt; should be the object reference stored int UnitDef solarPlant.&lt;br /&gt;
That only leaves &amp;lt;code&amp;gt;buildPos&amp;lt;/code&amp;gt;, for which we will just use the current position of our commander. This means that our &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt; looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we should give the command to the engine. We do this through the method &amp;lt;code&amp;gt;callback.getEngine().handleCommand()&amp;lt;/code&amp;gt;. This method takes three arguments: the id of the recipient of the command, a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; and the command itself.&lt;br /&gt;
The command should be sent to the engine, and for now we will use a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;, as this is a feature which is not yet supported by spring (asynchronous command tracking).&lt;br /&gt;
Our code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
&lt;br /&gt;
        this.callback.getEngine().handleCommand(AICommandWrapper.COMMAND_TO_ID_ENGINE,&lt;br /&gt;
            -1, command);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=647</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=647"/>
		<updated>2014-05-18T19:08:56Z</updated>

		<summary type="html">&lt;p&gt;Meriton: OOAIFactory no longer exists&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
In order to have your AI build a solar plant, the first thing you need is a reference to your commander. You first need an instance field &#039;Unit commander&#039; to put the reference in, then we need to get the reference itself.&lt;br /&gt;
A UnitFinished event is triggered whenever a unit has been built. (This may sound similar to &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;. For a quick explanation of the difference, see the FAQ below.)&lt;br /&gt;
At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method. &lt;br /&gt;
&lt;br /&gt;
To get a reference to the commander, you need to check if the unit is indeed the command, and if so, assign the value of the unit parameter to the commander field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit)&lt;br /&gt;
{&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;))&lt;br /&gt;
        this.commander = unit;&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Giving a command is straightforward. All we need to do is to create the appropriate command object and pass it through the callback to the engine.&lt;br /&gt;
&lt;br /&gt;
EDIT: the command class is outdated and not included in the current oo wrapper. Commands are now given via the unit class. See: http://spring.abma.de/doc-Interface-JavaOO/com/springrts/ai/oo/clb/Unit.html&lt;br /&gt;
&lt;br /&gt;
The command we need to tell commander to build a solar plant is a &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt;. This command takes a number of arguments:&lt;br /&gt;
&lt;br /&gt;
; Unit unit : the unit we want to give to order to&lt;br /&gt;
; int groupId : the group we want to give the order to&lt;br /&gt;
; List&amp;lt;AICommand.Option&amp;gt; optionsList : a list addional options. See the values of AICommand.Option for details&lt;br /&gt;
; int timeOut : the number of frames after which the command times out&lt;br /&gt;
; UnitDef toBuildUnitDef : the UnitDef of the unit we want to build&lt;br /&gt;
; AIFloat3 buildPos : the position to build the unit at&lt;br /&gt;
; int facing : the direction the new unit should face&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see above, we can give a command to either a single unit or a group of units. In this example we only have a single unit. This means that unit should be a reference to our commander, and &amp;lt;code&amp;gt;groupId&amp;lt;/code&amp;gt; should be -1.&lt;br /&gt;
To keep things simple, we will not use any options, set the timeout to a large number, and set facing to 0.&lt;br /&gt;
The value of &amp;lt;code&amp;gt;toBuildUnitDef&amp;lt;/code&amp;gt; should be the object reference stored int UnitDef solarPlant.&lt;br /&gt;
That only leaves &amp;lt;code&amp;gt;buildPos&amp;lt;/code&amp;gt;, for which we will just use the current position of our commander. This means that our &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt; looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we should give the command to the engine. We do this through the method &amp;lt;code&amp;gt;callback.getEngine().handleCommand()&amp;lt;/code&amp;gt;. This method takes three arguments: the id of the recipient of the command, a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; and the command itself.&lt;br /&gt;
The command should be sent to the engine, and for now we will use a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;, as this is a feature which is not yet supported by spring (asynchronous command tracking).&lt;br /&gt;
Our code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
&lt;br /&gt;
        this.callback.getEngine().handleCommand(AICommandWrapper.COMMAND_TO_ID_ENGINE,&lt;br /&gt;
            -1, command);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=646</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=646"/>
		<updated>2014-05-18T18:48:08Z</updated>

		<summary type="html">&lt;p&gt;Meriton: OOAIFactory no longer exists&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the main class ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI.&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAIFactory&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
In order to have your AI build a solar plant, the first thing you need is a reference to your commander. You first need an instance field &#039;Unit commander&#039; to put the reference in, then we need to get the reference itself.&lt;br /&gt;
A UnitFinished event is triggered whenever a unit has been built. (This may sound similar to &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;. For a quick explanation of the difference, see the FAQ below.)&lt;br /&gt;
At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method. &lt;br /&gt;
&lt;br /&gt;
To get a reference to the commander, you need to check if the unit is indeed the command, and if so, assign the value of the unit parameter to the commander field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit)&lt;br /&gt;
{&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;))&lt;br /&gt;
        this.commander = unit;&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Giving a command is straightforward. All we need to do is to create the appropriate command object and pass it through the callback to the engine.&lt;br /&gt;
&lt;br /&gt;
EDIT: the command class is outdated and not included in the current oo wrapper. Commands are now given via the unit class. See: http://spring.abma.de/doc-Interface-JavaOO/com/springrts/ai/oo/clb/Unit.html&lt;br /&gt;
&lt;br /&gt;
The command we need to tell commander to build a solar plant is a &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt;. This command takes a number of arguments:&lt;br /&gt;
&lt;br /&gt;
; Unit unit : the unit we want to give to order to&lt;br /&gt;
; int groupId : the group we want to give the order to&lt;br /&gt;
; List&amp;lt;AICommand.Option&amp;gt; optionsList : a list addional options. See the values of AICommand.Option for details&lt;br /&gt;
; int timeOut : the number of frames after which the command times out&lt;br /&gt;
; UnitDef toBuildUnitDef : the UnitDef of the unit we want to build&lt;br /&gt;
; AIFloat3 buildPos : the position to build the unit at&lt;br /&gt;
; int facing : the direction the new unit should face&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see above, we can give a command to either a single unit or a group of units. In this example we only have a single unit. This means that unit should be a reference to our commander, and &amp;lt;code&amp;gt;groupId&amp;lt;/code&amp;gt; should be -1.&lt;br /&gt;
To keep things simple, we will not use any options, set the timeout to a large number, and set facing to 0.&lt;br /&gt;
The value of &amp;lt;code&amp;gt;toBuildUnitDef&amp;lt;/code&amp;gt; should be the object reference stored int UnitDef solarPlant.&lt;br /&gt;
That only leaves &amp;lt;code&amp;gt;buildPos&amp;lt;/code&amp;gt;, for which we will just use the current position of our commander. This means that our &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt; looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we should give the command to the engine. We do this through the method &amp;lt;code&amp;gt;callback.getEngine().handleCommand()&amp;lt;/code&amp;gt;. This method takes three arguments: the id of the recipient of the command, a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; and the command itself.&lt;br /&gt;
The command should be sent to the engine, and for now we will use a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;, as this is a feature which is not yet supported by spring (asynchronous command tracking).&lt;br /&gt;
Our code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
&lt;br /&gt;
        this.callback.getEngine().handleCommand(AICommandWrapper.COMMAND_TO_ID_ENGINE,&lt;br /&gt;
            -1, command);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=645</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=645"/>
		<updated>2014-05-18T18:16:21Z</updated>

		<summary type="html">&lt;p&gt;Meriton: /* Importing the interface libraries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the required classes ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI. After that you&#039;ll need another class, named &#039;&#039;MyJavaAIFactory&#039;&#039;. This class should extend &#039;&#039;com.springrts.ai.oo.OOAIFactory&#039;&#039;.&lt;br /&gt;
The class MyJavaAIFactory only has to implement a single method: &#039;&#039;public OOAI createAI(int teamId, OOAICallback callback)&#039;&#039;. This is the method that the Java interface calls to get an instance of your AI. If you wanted to, you could create a different AI depending on circumstances, but for now it is probably easiest to simply return a new MyJavaAI(), until you decide you require something more elaborate.&lt;br /&gt;
You should now have two classes, &#039;&#039;myjavaai.MyJavaAI&#039;&#039; and &#039;&#039;myjavaai.MyJavaAIFactory&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAIFactory&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
In order to have your AI build a solar plant, the first thing you need is a reference to your commander. You first need an instance field &#039;Unit commander&#039; to put the reference in, then we need to get the reference itself.&lt;br /&gt;
A UnitFinished event is triggered whenever a unit has been built. (This may sound similar to &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;. For a quick explanation of the difference, see the FAQ below.)&lt;br /&gt;
At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method. &lt;br /&gt;
&lt;br /&gt;
To get a reference to the commander, you need to check if the unit is indeed the command, and if so, assign the value of the unit parameter to the commander field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit)&lt;br /&gt;
{&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;))&lt;br /&gt;
        this.commander = unit;&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Giving a command is straightforward. All we need to do is to create the appropriate command object and pass it through the callback to the engine.&lt;br /&gt;
&lt;br /&gt;
EDIT: the command class is outdated and not included in the current oo wrapper. Commands are now given via the unit class. See: http://spring.abma.de/doc-Interface-JavaOO/com/springrts/ai/oo/clb/Unit.html&lt;br /&gt;
&lt;br /&gt;
The command we need to tell commander to build a solar plant is a &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt;. This command takes a number of arguments:&lt;br /&gt;
&lt;br /&gt;
; Unit unit : the unit we want to give to order to&lt;br /&gt;
; int groupId : the group we want to give the order to&lt;br /&gt;
; List&amp;lt;AICommand.Option&amp;gt; optionsList : a list addional options. See the values of AICommand.Option for details&lt;br /&gt;
; int timeOut : the number of frames after which the command times out&lt;br /&gt;
; UnitDef toBuildUnitDef : the UnitDef of the unit we want to build&lt;br /&gt;
; AIFloat3 buildPos : the position to build the unit at&lt;br /&gt;
; int facing : the direction the new unit should face&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see above, we can give a command to either a single unit or a group of units. In this example we only have a single unit. This means that unit should be a reference to our commander, and &amp;lt;code&amp;gt;groupId&amp;lt;/code&amp;gt; should be -1.&lt;br /&gt;
To keep things simple, we will not use any options, set the timeout to a large number, and set facing to 0.&lt;br /&gt;
The value of &amp;lt;code&amp;gt;toBuildUnitDef&amp;lt;/code&amp;gt; should be the object reference stored int UnitDef solarPlant.&lt;br /&gt;
That only leaves &amp;lt;code&amp;gt;buildPos&amp;lt;/code&amp;gt;, for which we will just use the current position of our commander. This means that our &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt; looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we should give the command to the engine. We do this through the method &amp;lt;code&amp;gt;callback.getEngine().handleCommand()&amp;lt;/code&amp;gt;. This method takes three arguments: the id of the recipient of the command, a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; and the command itself.&lt;br /&gt;
The command should be sent to the engine, and for now we will use a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;, as this is a feature which is not yet supported by spring (asynchronous command tracking).&lt;br /&gt;
Our code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
&lt;br /&gt;
        this.callback.getEngine().handleCommand(AICommandWrapper.COMMAND_TO_ID_ENGINE,&lt;br /&gt;
            -1, command);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=644</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=644"/>
		<updated>2014-05-18T16:35:10Z</updated>

		<summary type="html">&lt;p&gt;Meriton: /* Importing the interface libraries */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries (optionally, you can attach the sources for for JavaDoc support in your editor) &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt; (sources: jlib/AIInterface-src.jar&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Skirmish/NullOOJavaAI/0.1/jlib/vecmath.jar&amp;lt;/code&amp;gt; (sources: vecmath-src.jar)&lt;br /&gt;
* &amp;lt;code&amp;gt;JavaOO-AIWrapper.jar&amp;lt;/code&amp;gt; (sources: TODO)&lt;br /&gt;
&lt;br /&gt;
==== Creating the required classes ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI. After that you&#039;ll need another class, named &#039;&#039;MyJavaAIFactory&#039;&#039;. This class should extend &#039;&#039;com.springrts.ai.oo.OOAIFactory&#039;&#039;.&lt;br /&gt;
The class MyJavaAIFactory only has to implement a single method: &#039;&#039;public OOAI createAI(int teamId, OOAICallback callback)&#039;&#039;. This is the method that the Java interface calls to get an instance of your AI. If you wanted to, you could create a different AI depending on circumstances, but for now it is probably easiest to simply return a new MyJavaAI(), until you decide you require something more elaborate.&lt;br /&gt;
You should now have two classes, &#039;&#039;myjavaai.MyJavaAI&#039;&#039; and &#039;&#039;myjavaai.MyJavaAIFactory&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAIFactory&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
In order to have your AI build a solar plant, the first thing you need is a reference to your commander. You first need an instance field &#039;Unit commander&#039; to put the reference in, then we need to get the reference itself.&lt;br /&gt;
A UnitFinished event is triggered whenever a unit has been built. (This may sound similar to &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;. For a quick explanation of the difference, see the FAQ below.)&lt;br /&gt;
At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method. &lt;br /&gt;
&lt;br /&gt;
To get a reference to the commander, you need to check if the unit is indeed the command, and if so, assign the value of the unit parameter to the commander field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit)&lt;br /&gt;
{&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;))&lt;br /&gt;
        this.commander = unit;&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Giving a command is straightforward. All we need to do is to create the appropriate command object and pass it through the callback to the engine.&lt;br /&gt;
&lt;br /&gt;
EDIT: the command class is outdated and not included in the current oo wrapper. Commands are now given via the unit class. See: http://spring.abma.de/doc-Interface-JavaOO/com/springrts/ai/oo/clb/Unit.html&lt;br /&gt;
&lt;br /&gt;
The command we need to tell commander to build a solar plant is a &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt;. This command takes a number of arguments:&lt;br /&gt;
&lt;br /&gt;
; Unit unit : the unit we want to give to order to&lt;br /&gt;
; int groupId : the group we want to give the order to&lt;br /&gt;
; List&amp;lt;AICommand.Option&amp;gt; optionsList : a list addional options. See the values of AICommand.Option for details&lt;br /&gt;
; int timeOut : the number of frames after which the command times out&lt;br /&gt;
; UnitDef toBuildUnitDef : the UnitDef of the unit we want to build&lt;br /&gt;
; AIFloat3 buildPos : the position to build the unit at&lt;br /&gt;
; int facing : the direction the new unit should face&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see above, we can give a command to either a single unit or a group of units. In this example we only have a single unit. This means that unit should be a reference to our commander, and &amp;lt;code&amp;gt;groupId&amp;lt;/code&amp;gt; should be -1.&lt;br /&gt;
To keep things simple, we will not use any options, set the timeout to a large number, and set facing to 0.&lt;br /&gt;
The value of &amp;lt;code&amp;gt;toBuildUnitDef&amp;lt;/code&amp;gt; should be the object reference stored int UnitDef solarPlant.&lt;br /&gt;
That only leaves &amp;lt;code&amp;gt;buildPos&amp;lt;/code&amp;gt;, for which we will just use the current position of our commander. This means that our &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt; looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we should give the command to the engine. We do this through the method &amp;lt;code&amp;gt;callback.getEngine().handleCommand()&amp;lt;/code&amp;gt;. This method takes three arguments: the id of the recipient of the command, a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; and the command itself.&lt;br /&gt;
The command should be sent to the engine, and for now we will use a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;, as this is a feature which is not yet supported by spring (asynchronous command tracking).&lt;br /&gt;
Our code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
&lt;br /&gt;
        this.callback.getEngine().handleCommand(AICommandWrapper.COMMAND_TO_ID_ENGINE,&lt;br /&gt;
            -1, command);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=643</id>
		<title>AI:Development:Lang:Java</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=AI:Development:Lang:Java&amp;diff=643"/>
		<updated>2014-05-18T16:26:02Z</updated>

		<summary type="html">&lt;p&gt;Meriton: /* Getting Started on your own Java AI */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Engine_Development|Development]] &amp;lt; [[AI:Development|AI Development]] &amp;lt; Java AI Development&lt;br /&gt;
&lt;br /&gt;
== Getting Started on your own Java AI ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; This tutorial assumes you have Spring working on your machine. The Spring directory will be referred to as &#039;Spring&#039; from here on.&lt;br /&gt;
&lt;br /&gt;
You will also need to make sure that Java AI&#039;s run properly on your machine. This is most easily done by running a Spring game with the &#039;&#039;NullOOJavaAI&#039;&#039; that comes with the engine. You will need the JRE 1.5 or greater, and to set the &#039;&#039;JAVA_HOME&#039;&#039; environment variable on your system to point to the correct location.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note:&#039;&#039; If you&#039;re using a &#039;&#039;64 bit&#039;&#039; version of &#039;&#039;Windows&#039;&#039;, you will need a 32 bit Java Runtime Environment/Java Development Kit anyway, because Spring is (as of May 2014) not yet available as a 64bit version for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up a Java Project ===&lt;br /&gt;
&lt;br /&gt;
To start working on your own Java AI, you should first set up a project in your favorite Java IDE. You need to import the Spring Java AI Interface libraries, and then create an AI class and an AI Factory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OUTDATED&#039;&#039;&#039; If you are using &#039;&#039;&#039;Netbeans IDE&#039;&#039;&#039;, you can find a detailed tutorial [http://springrts.com/phpbb/download/file.php?id=4970 here] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread]). Otherwise, please continue reading this page.&lt;br /&gt;
&lt;br /&gt;
==== Importing the interface libraries ====&lt;br /&gt;
&lt;br /&gt;
In order to use the Java Interface, you will need to import the Java Interface libraries, located in &#039;&#039;Spring/AI/Interfaces/Java/[version]/&#039;&#039;. Replace &#039;&#039;[version]&#039;&#039; with the number of the latest Java Interface version. As of this writing, only &#039;&#039;0.1&#039;&#039; is available.&lt;br /&gt;
&lt;br /&gt;
The file you need is &#039;&#039;AIInterface.jar&#039;&#039;. You also need the additional library &#039;&#039;vecmath.jar&#039;&#039;, located in the &#039;&#039;jlib/&#039;&#039; subfolder. Optionally, you can attach the file &#039;&#039;AIInterface-src.jar&#039;&#039; as source to the &#039;&#039;AIInterface.jar&#039;&#039; file for JavaDoc support in your editor.&lt;br /&gt;
&lt;br /&gt;
Your project should now contain the following libraries:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/AIInterface.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/jlib/AIInterface-src.jar&amp;lt;/code&amp;gt; (optional)&lt;br /&gt;
* &amp;lt;code&amp;gt;Spring/AI/Interfaces/Java/[version]/jlib/vecmath.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Creating the required classes ====&lt;br /&gt;
&lt;br /&gt;
Now that you have the libraries, the next step is to create your AI&#039;s main class. Firstly, you may want to create a package to put your classes in, for example, &#039;&#039;myjavaai&#039;&#039;. Create a new class, named MyJavaAI (or whatever you would like your AI to be called). MyJavaAI should extend com.springrts.ai.oo.AbstractOOAI. After that you&#039;ll need another class, named &#039;&#039;MyJavaAIFactory&#039;&#039;. This class should extend &#039;&#039;com.springrts.ai.oo.OOAIFactory&#039;&#039;.&lt;br /&gt;
The class MyJavaAIFactory only has to implement a single method: &#039;&#039;public OOAI createAI(int teamId, OOAICallback callback)&#039;&#039;. This is the method that the Java interface calls to get an instance of your AI. If you wanted to, you could create a different AI depending on circumstances, but for now it is probably easiest to simply return a new MyJavaAI(), until you decide you require something more elaborate.&lt;br /&gt;
You should now have two classes, &#039;&#039;myjavaai.MyJavaAI&#039;&#039; and &#039;&#039;myjavaai.MyJavaAIFactory&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Adding your AI to Spring ===&lt;br /&gt;
&lt;br /&gt;
Your AI needs to have its own folder, and the engine will need to know your AI&#039;s attributes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating an AI folder ====&lt;br /&gt;
&lt;br /&gt;
Every Spring AI is stored in &#039;&#039;Spring/AI/Skirmish&#039;&#039;. You will have to create a folder for your AI as well. It is easiest to go to the directory &#039;&#039;Spring/AI/Skirmish&#039;&#039;, make a copy of the folder &#039;&#039;NullOOJavaAI&#039;&#039;, and rename the copy to &#039;&#039;MyJavaAI&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Telling the Engine about your AI ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;MyJavaAI&#039;&#039; folder you created contains the different versions of your AI. As of this writing, the &#039;&#039;NullOOJavaAI&#039;&#039; only has a version &#039;&#039;0.1&#039;&#039;, so there should be a folder &#039;&#039;0.1&#039;&#039; inside the &#039;&#039;MyJavaAI&#039;&#039; folder. Inside you will find a number of files.&lt;br /&gt;
These files are:&lt;br /&gt;
* &#039;&#039;SkirmishAI.jar&#039;&#039;: the jar file that contains the AI code.&lt;br /&gt;
* &#039;&#039;AIInfo.lua&#039;&#039;: contains information about the AI.&lt;br /&gt;
* &#039;&#039;AIOptions.lua&#039;&#039;: you can specify your AI&#039;s options in here.&lt;br /&gt;
* Possibly some text files: these are log files generated by the &#039;&#039;NullOOJavaAI&#039;&#039;. If you don&#039;t plan on using the same files, you may as well delete these.&lt;br /&gt;
&lt;br /&gt;
Additionally, there is a folder named &#039;&#039;jlib&#039;&#039;. This is where you should place any additional libraries you use in your AI.&lt;br /&gt;
&lt;br /&gt;
In order to let Spring recognize your AI, you will have to edit &#039;&#039;AIInfo.lua&#039;&#039;. You can do this with any regular text editor.&lt;br /&gt;
When you open it, the file will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
local infos = {&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;shortName&#039;,&lt;br /&gt;
      value  = &#039;NullOOJavaAI&#039;,&lt;br /&gt;
      desc   = &#039;machine conform name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;version&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI version - !This comment is used for parsing!&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;className&#039;,&lt;br /&gt;
      value  = &#039;nulloojavaai.NullOOJavaAIFactory&#039;,&lt;br /&gt;
      desc   = &#039;fully qualified name of a class that implements interface com.springrts.ai.AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;name&#039;,&lt;br /&gt;
      value  = &#039;high-level Java stub Skirmish AI&#039;,&lt;br /&gt;
      desc   = &#039;human readable name.&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;loadSupported&#039;,&lt;br /&gt;
      value  = &#039;no&#039;,&lt;br /&gt;
      desc   = &#039;whether this AI supports loading or not&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceShortName&#039;,&lt;br /&gt;
      value  = &#039;Java&#039;, -- AI Interface name - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the shortName of the AI interface this AI needs&#039;,&lt;br /&gt;
   },&lt;br /&gt;
   {&lt;br /&gt;
      key    = &#039;interfaceVersion&#039;,&lt;br /&gt;
      value  = &#039;0.1&#039;, -- AI Interface version - !This comment is used for parsing!&lt;br /&gt;
      desc   = &#039;the minimum version of the AI interface required by this AI&#039;,&lt;br /&gt;
   },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return infos&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The file describes a number of attributes. Each attribute has a key, a value and a desc(ription). The key is the name of the attribute, the description tells you what the attribute is used for, and the value is what you will want to edit.&lt;br /&gt;
&lt;br /&gt;
The shortName attribute is the name used for your AI internally. It&#039;s most logical to change this into to the same name you gave your AI class. (MyJavaAI.)&lt;br /&gt;
&lt;br /&gt;
&#039;version&#039; tells the engine which version of your AI this is. If you&#039;re in the 0.1 folder, make this 0.1. Your AI should be located at AI/Skirmish/&#039;&#039;shortName&#039;&#039;/&#039;&#039;version&#039;&#039;/.&lt;br /&gt;
&lt;br /&gt;
&#039;classname&#039; tells the interface which class is your AIFactory class. Take care that you use the fully qualified class name, or it won&#039;t work. In this example, this should be myjavaai.MyJavaAIFactory.&lt;br /&gt;
&lt;br /&gt;
&#039;name&#039; describes your AI to the user. In this example, you might put &#039;A simple Java AI to learn about AI programming in Spring.&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;loadSupported&#039; is rather self-explanatory. Since you have just started working on your AI, you may not get around to implementing loading support for some time, so it&#039;s best to put &#039;no,&#039; for now.&lt;br /&gt;
&lt;br /&gt;
&#039;interfaceShortName&#039; and &#039;interfaceversion&#039; tell the engine about the interface your AI uses. Since MyJavaAI uses the same interface as the NullOOJavaAI, leave these as they are.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Finally, the last thing you should do is exporting your AI to SkirmishAI.jar. The way to do this varies depending on your Java editor.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Test your AI ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After following all the above steps, you should be able to run your AI. Either use SpringLobby to start a new game and see if you can add your AI as a bot, or run &#039;&#039;spring.exe&#039;&#039; to see if you can start the script MyJavaAI Test.&lt;br /&gt;
Of course, since you haven&#039;t told the AI what to do, your starting unit(s) will sit there doing nothing.&lt;br /&gt;
&lt;br /&gt;
== Getting your AI to Do Something ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After getting your AI running, you will want to make it do something. Traditionally, the first thing to get your AI to is to build a solar plant, assuming you want it to play BA. If not, it is quite straightforward to build other units once you have the general idea.&lt;br /&gt;
You will need four things to get your AI to build a solar plant:&lt;br /&gt;
* A reference to the callback&lt;br /&gt;
* A reference to the commander (your starting unit in BA)&lt;br /&gt;
* A reference to the solar plant definition object&lt;br /&gt;
* To tell the commander to build the solar plant&lt;br /&gt;
&lt;br /&gt;
However, before we go about building solar plants, first you should know about events. We will use these to get the required object references.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
&lt;br /&gt;
Nearly everything that happens in the game is an event. When a unit is created, this is an event. Enemy spotted? Also an event. A player sends your AI a message? You got it, this is an event as well.&lt;br /&gt;
&lt;br /&gt;
Every event is made known to your AI. Have a look at the &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class again. &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;AbstractOOA&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt; implements a number of methods like &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;enemyEnterRadar()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;message()&amp;lt;/code&amp;gt;.&lt;br /&gt;
Sound familiar? The method &amp;lt;code&amp;gt;unitCreated(Unit unit, Unit builder)&amp;lt;/code&amp;gt; is called every time a unit is created, and tells you the unit that was created and the unit that built it. Similarly, enemyEnterRadar(Unit enemy) and message(int player, String message) tell you about an enemy unit entering radar range and receiving a message from another player respectively.&lt;br /&gt;
There are many other events that all have corresponding methods. To have your AI respond to these events, simply override the method in your &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; class.&lt;br /&gt;
The return type of these methods is an integer. The return value can be used for debugging. 0 means that no errors occurred, while any other value is threated as an error. This system can be used for debugging, but is it much easier to implement proper logging.&lt;br /&gt;
&lt;br /&gt;
In the sections below you will see an example of the use of these events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the callback ===&lt;br /&gt;
&lt;br /&gt;
The callback is the object through which the AI communicates with the engine. All information that does not change the state of the engine can be retrieved through individual methods in the callback, and state changing commands (eg to units) will go through a single, specialized method, which is in the callback as well.&lt;br /&gt;
Getting a reference to the callback is easy.&lt;br /&gt;
First create a class field &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; to put the reference in, then overwrite the method &amp;lt;code&amp;gt;init(int teamId, OOAICallback callback)&amp;lt;/code&amp;gt;. The init method is called at the start of every game (right at the end of the countdown).&lt;br /&gt;
As you can see, all that you need to do is set the parameter value callback to the field callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int init(int teamId, OOAICallback callback)&lt;br /&gt;
{&lt;br /&gt;
    this.callback = callback;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the commander ===&lt;br /&gt;
&lt;br /&gt;
In order to have your AI build a solar plant, the first thing you need is a reference to your commander. You first need an instance field &#039;Unit commander&#039; to put the reference in, then we need to get the reference itself.&lt;br /&gt;
A UnitFinished event is triggered whenever a unit has been built. (This may sound similar to &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt;. For a quick explanation of the difference, see the FAQ below.)&lt;br /&gt;
At the start of the game, the engine will send a UnitFinished event for every starting unit. When playing BA, this means you will get a UnitFinished event for the commander. Therefore, the most straightforward way of finding the reference to the commander is overriding the &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; method. &lt;br /&gt;
&lt;br /&gt;
To get a reference to the commander, you need to check if the unit is indeed the command, and if so, assign the value of the unit parameter to the commander field:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int unitFinished(Unit unit)&lt;br /&gt;
{&lt;br /&gt;
    if (unit.getDef().getName().equals(&amp;quot;armcom&amp;quot;))&lt;br /&gt;
        this.commander = unit;&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting a reference to the solar plant definition ===&lt;br /&gt;
&lt;br /&gt;
Every unit in Spring has a UnitDef (a &#039;unit defintion&#039;). This object tells you all there is to know about the properties of the unit type, such as maximum speed, turn rate and what weapons it carries.&lt;br /&gt;
One way to get the reference to the definition of a solar plant is to use &amp;lt;code&amp;gt;callback.getUnitDefs()&amp;lt;/code&amp;gt;. This will give you a list of all the available unit types in the game that is currently being played.&lt;br /&gt;
The name of the unit def we are looking for is &#039;armsolar&#039;, so we can just iterate through the list and find the one named armsolar, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs();&lt;br /&gt;
UnitDef solarPlant = null;&lt;br /&gt;
for (UnitDef def : unitDefs)&lt;br /&gt;
   if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
   {&lt;br /&gt;
       solarPlant = def;&lt;br /&gt;
       break;&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Telling the commander to build the solar plant ===&lt;br /&gt;
&lt;br /&gt;
Now, the only thing left to do is to tell the commander that we want it to build the solar plant, and where to place it. In short, we need to give the commander a build command.&lt;br /&gt;
&lt;br /&gt;
We want to give this command only once at the first frame of the game. For this we can use the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method, which is called at every frame of the game. All we need to do is overwrite the &amp;lt;code&amp;gt;update(int frame)&amp;lt;/code&amp;gt; method and give the command if the frame is 1. This results in the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        // give command here&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Giving a command is straightforward. All we need to do is to create the appropriate command object and pass it through the callback to the engine.&lt;br /&gt;
&lt;br /&gt;
EDIT: the command class is outdated and not included in the current oo wrapper. Commands are now given via the unit class. See: http://spring.abma.de/doc-Interface-JavaOO/com/springrts/ai/oo/clb/Unit.html&lt;br /&gt;
&lt;br /&gt;
The command we need to tell commander to build a solar plant is a &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt;. This command takes a number of arguments:&lt;br /&gt;
&lt;br /&gt;
; Unit unit : the unit we want to give to order to&lt;br /&gt;
; int groupId : the group we want to give the order to&lt;br /&gt;
; List&amp;lt;AICommand.Option&amp;gt; optionsList : a list addional options. See the values of AICommand.Option for details&lt;br /&gt;
; int timeOut : the number of frames after which the command times out&lt;br /&gt;
; UnitDef toBuildUnitDef : the UnitDef of the unit we want to build&lt;br /&gt;
; AIFloat3 buildPos : the position to build the unit at&lt;br /&gt;
; int facing : the direction the new unit should face&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see above, we can give a command to either a single unit or a group of units. In this example we only have a single unit. This means that unit should be a reference to our commander, and &amp;lt;code&amp;gt;groupId&amp;lt;/code&amp;gt; should be -1.&lt;br /&gt;
To keep things simple, we will not use any options, set the timeout to a large number, and set facing to 0.&lt;br /&gt;
The value of &amp;lt;code&amp;gt;toBuildUnitDef&amp;lt;/code&amp;gt; should be the object reference stored int UnitDef solarPlant.&lt;br /&gt;
That only leaves &amp;lt;code&amp;gt;buildPos&amp;lt;/code&amp;gt;, for which we will just use the current position of our commander. This means that our &amp;lt;code&amp;gt;BuildUnitAICommand&amp;lt;/code&amp;gt; looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Next, we should give the command to the engine. We do this through the method &amp;lt;code&amp;gt;callback.getEngine().handleCommand()&amp;lt;/code&amp;gt;. This method takes three arguments: the id of the recipient of the command, a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; and the command itself.&lt;br /&gt;
The command should be sent to the engine, and for now we will use a &amp;lt;code&amp;gt;commandID&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;, as this is a feature which is not yet supported by spring (asynchronous command tracking).&lt;br /&gt;
Our code will look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
@Override&lt;br /&gt;
public int update(int frame)&lt;br /&gt;
{&lt;br /&gt;
    if (frame == 0)&lt;br /&gt;
    {&lt;br /&gt;
        AICommand command = new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
            new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000, solarPlant,&lt;br /&gt;
            this.commander.getPos(), 0);&lt;br /&gt;
&lt;br /&gt;
        this.callback.getEngine().handleCommand(AICommandWrapper.COMMAND_TO_ID_ENGINE,&lt;br /&gt;
            -1, command);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point you will want to see if your AI actually works. Export your code to &#039;&#039;Spring/AI/Skirmish/MyJavaAI/SkirmishAI.jar&#039;&#039; and start up a game. Your AI should now build a solar plant at its start position.&lt;br /&gt;
&lt;br /&gt;
===Building a metal extractor===&lt;br /&gt;
Building a metal extractor is slightly more complicated. Assuming you&#039;re not on a metal map, you will need to find a suitable site to place the extractor. Generally, it&#039;s preferable to select a site closest to wherever your construction unit (commander) is located.&lt;br /&gt;
&lt;br /&gt;
Modify your code that got a reference to the solar plant by making the following changes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
List&amp;lt;UnitDef&amp;gt; unitDefs = this.callback.getUnitDefs(); UnitDef solarPlant = null; for (UnitDef def : unitDefs)&lt;br /&gt;
&lt;br /&gt;
  if (def.getName().equals(&amp;quot;armsolar&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
      solarPlant = def;&lt;br /&gt;
  }&lt;br /&gt;
  else if (def.getName().equals(&amp;quot;armmex&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
       metalExtractor=def;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, you will need to create a Unitdef metalExtractor field by where you declared your solarPlant field.&lt;br /&gt;
&lt;br /&gt;
Next, you need a method for determining the distance between two 3D coordinates (since Spring locations are three dimensional). A slightly modified version of a distance function is found below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public float calculateDistance(AIFloat3 a, AIFloat3 b)&lt;br /&gt;
    {&lt;br /&gt;
    float xDistance = a.x - b.x;&lt;br /&gt;
    float yDistance = a.y - b.y;&lt;br /&gt;
    float zDistance = a.z - b.z;&lt;br /&gt;
    float totalDistanceSquared = xDistance*xDistance + yDistance*yDistance + zDistance*zDistance;&lt;br /&gt;
    return totalDistanceSquared;&lt;br /&gt;
    } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above code actually returns the distance squared, but it will work for our purposes. In your init function, you will want to add the following code above the return statement but below the line defining the callback:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
checkForMetal();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will call the following function you need to place in your code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public void checkForMetal()&lt;br /&gt;
    {&lt;br /&gt;
    Resource metal=Resource.getInstance(clb, 0);&lt;br /&gt;
    availablemetalspots=clb.getMap().getResourceMapSpotsPositions(metal);&lt;br /&gt;
    if(availablemetalspots.isEmpty())&lt;br /&gt;
        {&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with no metal spots&amp;quot;);&lt;br /&gt;
        metalmap=false;&lt;br /&gt;
        }&lt;br /&gt;
    else&lt;br /&gt;
        {metalmap=true;&lt;br /&gt;
        sendTextMsg(&amp;quot;This is a map with metal spots. Listing Values...&amp;quot;);&lt;br /&gt;
        for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            sendTextMsg(&amp;quot;Metal Spot at X: &amp;quot;+metalspot.x + &amp;quot;, Y: &amp;quot;+metalspot.y +&amp;quot;, Z: &amp;quot;+metalspot.z);&lt;br /&gt;
        }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the above code to function properly, you will need to create a Boolean named metalmap and a List&amp;lt;AIFloat3&amp;gt; availablemetalspots. You will now have a function set up for calculating distance between two points, and a data structure holding a list of positions of metal spots. The next step is to tie these two together:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
public AIFloat3 closestMetalSpot(AIFloat3 unitposition)&lt;br /&gt;
    {&lt;br /&gt;
    AIFloat3 closestspot=null;&lt;br /&gt;
    for (AIFloat3 metalspot : availablemetalspots) {&lt;br /&gt;
            if (closestspot==null)&lt;br /&gt;
                {&lt;br /&gt;
                closestspot=metalspot;&lt;br /&gt;
                }&lt;br /&gt;
        else if(calculateDistance(metalspot, unitposition) &amp;lt; calculateDistance(closestspot, unitposition) &amp;amp;&amp;amp; metalspot.hashCode()!=unitposition.hashCode())&lt;br /&gt;
                    {&lt;br /&gt;
                    closestspot=metalspot;&lt;br /&gt;
                    }&lt;br /&gt;
        }&lt;br /&gt;
    availablemetalspots.remove(closestspot);&lt;br /&gt;
    return closestspot;&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above function accepts an AIFloat3 containing the location of your construction unit (commander). It will then find the closest metal spot and return that location. The next step is to have your commander make use of this.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  if (frame == 600)&lt;br /&gt;
  {&lt;br /&gt;
       if(metalmap){       sendTextMsg(&amp;quot;About to build mex at frame &amp;quot; + frame);&lt;br /&gt;
       AIFloat3 closestspot=closestMetalSpot(commander.getPos());&lt;br /&gt;
       BuildUnitAICommand command2=new BuildUnitAICommand(this.commander, -1,&lt;br /&gt;
               new ArrayList&amp;lt;AICommand.Option&amp;gt;(), 10000,&lt;br /&gt;
               metalExtractor,closestspot, 0);&lt;br /&gt;
       handleEngineCommand(command2);}&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Place the above code in your update() method. When the frame count reaches 600, your commander will start to build a metal extractor at the closest metal spot. The extractor may not be right on top of where the metal spot appears to be, but you can mouse over the extractor to make sure it&#039;s drawing the metal properly.&lt;br /&gt;
&lt;br /&gt;
== Frequently Asked Questions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; What is the difference between &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt;?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; The difference is that &amp;lt;code&amp;gt;unitCreated()&amp;lt;/code&amp;gt; is called when construction of a unit starts, while &amp;lt;code&amp;gt;unitFinished()&amp;lt;/code&amp;gt; when construction on the unit has been completed. Any number of things may happen in-between, including the unit under construction being destroyed, so it is important to remember this distinction.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; Do I have to copy and paste my jar file to the directory in Spring/AI/Skirmish/MyAI/0.1 each time I want to test my AI out?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Yes, but it is much easier if you automate the process. In Windows, a simple batch file can be created to move the files over for you. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
copy C:\Users\msm8bball\Documents\NetBeansProjects\MyAI\dist\MyAI.jar &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
del &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\SkirmishAI.jar&amp;quot;&lt;br /&gt;
rename &amp;quot;C:\Program Files (x86)\Spring\AI\Skirmish\MyAI\0.1\MyAI.jar&amp;quot; SkirmishAI.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Modify the above code to match your computer&#039;s directories. Place it in a text file and save it as MoveAI.bat. This will create a batch file that you can double click and it will automatically move your AI to the proper location and rename it. You might wish to put a shortcut to this in your Start menu or taskbar. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q:&#039;&#039;&#039; I have problems with the class-loader in my AI, any idea? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A:&#039;&#039;&#039; Each Java AI implementation is loaded by a separate class loader. This is used to load all the AI&#039;s class files and dependency libraries (in the &#039;&#039;jlib&#039;&#039; dir). Some libraries though, use the Thread contexts class loader, instead of the one of the current class. Therefore, if you want to load something from the AI&#039;s own class-path, make sure to let these libraries use the class-path of your AI classes, eg:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
ClassLoader myClassLoader = AIFactory.class.getClassLoader();&lt;br /&gt;
MySpecialUtil msp = new MySpecialUtil();&lt;br /&gt;
msp.setClassLoader(myClassLoader);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Please do not set this class-loader on the thread with &amp;lt;code&amp;gt;Thread.currentThread().setContextClassLoader(myClassLoader)&amp;lt;/code&amp;gt;, because all AI&#039;s are run in the same Java thread, and therefore this will cause problems.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[AIInterface:Java|Java AI Interface]]&lt;br /&gt;
* [http://spring.abma.de/doc-Interface-JavaOO/ Javadoc of the Java AI OO Wrapper] (generated daily from source by [[User:Abma|abma]])&lt;br /&gt;
* &#039;&#039;&#039;OUTDATED&#039;&#039;&#039; [http://springrts.com/phpbb/download/file.php?id=4970 Netbeans Java Skirmish AI Tutorial] (from [http://springrts.com/phpbb/viewtopic.php?p=448743#p448743 this forum thread])&lt;br /&gt;
* [http://modinfo.adune.nl/index.php?MOD=ba712 ModInfo] (contains a list of units and their short names)&lt;br /&gt;
&lt;br /&gt;
[[Category: AI Dev]]&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Keyboard&amp;diff=10082</id>
		<title>Keyboard</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Keyboard&amp;diff=10082"/>
		<updated>2011-01-09T02:52:10Z</updated>

		<summary type="html">&lt;p&gt;Meriton: manually change keyboad bindings by editing uikeys&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:FAQ]]&lt;br /&gt;
&lt;br /&gt;
==Default Keyboard Layout in Spring==&lt;br /&gt;
&lt;br /&gt;
Note: this page is currently incomplete&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/mediawiki/images/a/a5/KeyboardLayout.jpg Spring Keyboard Layout Image]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 1 &amp;lt;small&amp;gt;(left)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Select unit/s (also perform selected order, eg: build selected building)&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 2 &amp;lt;small&amp;gt;(right)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Default order. Depending on target:&amp;lt;br&amp;gt; - Move. &amp;lt;small&amp;gt;(drag mouse for line formation)&amp;lt;/small&amp;gt;&amp;lt;br&amp;gt; - Attack / Repair / Reclaim. &amp;lt;small&amp;gt;(drag to target an area)&amp;lt;/small&amp;gt;&amp;lt;br&amp;gt; - Build incomplete building or unit.&amp;lt;br&amp;gt; - Guard.&amp;lt;br&amp;gt; - If an order has been manually selected/hotkeyed, click to cancel.&lt;br /&gt;
|-&lt;br /&gt;
!Scroll Wheel&lt;br /&gt;
|Zoom in/out&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 3&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(click scroll wheel)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Move to point on minimap&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(Mouse 1 &amp;amp; 2 are used to select units and give orders on minimap)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!L&lt;br /&gt;
|(Duplicates middle click functionality)&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT &amp;lt;br&amp;gt;&amp;lt;small&amp;gt;+ (Mouse 1 or 2)&amp;lt;/small&amp;gt;&lt;br /&gt;
| - Queue order. Queue as many as you like.&lt;br /&gt;
(shift+drag to queue a line of buildings)&amp;lt;br&amp;gt; - Add unit/s to group&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + Mouse 1&lt;br /&gt;
|Remove unit/s from group&lt;br /&gt;
|-&lt;br /&gt;
![ and ]&lt;br /&gt;
|Rotate building (first select something to build and then rotate)&lt;br /&gt;
|-&lt;br /&gt;
!A&lt;br /&gt;
|Attack &amp;lt;small&amp;gt;(attack unit/ground)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!M&lt;br /&gt;
|Move&lt;br /&gt;
|-&lt;br /&gt;
!F&lt;br /&gt;
|Fight &amp;lt;small&amp;gt;(as move, but units will stop to kill enemies along the way)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!G&lt;br /&gt;
|Guard&lt;br /&gt;
|-&lt;br /&gt;
!P&lt;br /&gt;
|Patrol. &amp;lt;small&amp;gt;(Moves back and forth between current position and patrol position)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!S&lt;br /&gt;
|Stop&lt;br /&gt;
|-&lt;br /&gt;
!E&lt;br /&gt;
|Reclaim&lt;br /&gt;
|-&lt;br /&gt;
!R&lt;br /&gt;
|Repair&lt;br /&gt;
|-&lt;br /&gt;
!D&lt;br /&gt;
|D-Gun&lt;br /&gt;
|-&lt;br /&gt;
!X&lt;br /&gt;
|On/Off. &amp;lt;small&amp;gt;(as the unit on/off button)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!K&lt;br /&gt;
|Cloak on/off&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + D&lt;br /&gt;
|Self Destruct&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + W&lt;br /&gt;
|Queue &#039;wait&#039; command&lt;br /&gt;
|-&lt;br /&gt;
!W&lt;br /&gt;
|Stop waiting&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + number (1-0)&lt;br /&gt;
|Assign group&lt;br /&gt;
|-&lt;br /&gt;
!number (1-0)&lt;br /&gt;
|Select group&lt;br /&gt;
|-&lt;br /&gt;
!Double Click&lt;br /&gt;
|Select all units of targetted type in view&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + Z&lt;br /&gt;
|Select all units of selected type on map.&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + A&lt;br /&gt;
|Select all units on map.&lt;br /&gt;
|-&lt;br /&gt;
!ALT + SHIFT (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a rectangular area of buildings.&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a line of buildings.&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + CTRL (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a line of buildings with fixed angles of 90 degrees.&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + SHIFT (+ mouse click)&lt;br /&gt;
|Build a circular area of buildings around some other building (must point on the building with mouse cursor).&lt;br /&gt;
|-&lt;br /&gt;
!TAB&lt;br /&gt;
|Zooms out to see the whole map.&lt;br /&gt;
|-&lt;br /&gt;
!F1&lt;br /&gt;
|Shows heightmap&lt;br /&gt;
|-&lt;br /&gt;
!F2&lt;br /&gt;
|Shows areas where you can build (if the building what you want to build is selected)&lt;br /&gt;
|-&lt;br /&gt;
!F3&lt;br /&gt;
|Goes to the latest spot of action (also goes to the latest markers)&lt;br /&gt;
|-&lt;br /&gt;
!F4&lt;br /&gt;
|Shows metalmap&lt;br /&gt;
|-&lt;br /&gt;
!F5&lt;br /&gt;
|Hides User Interface&lt;br /&gt;
|-&lt;br /&gt;
!CTRL+F5&lt;br /&gt;
|Changes to a cooler camera mode&lt;br /&gt;
|-&lt;br /&gt;
!F6&lt;br /&gt;
|Turns sounds off (currently a bug causes sounds be on when zoomed in the spot where sound comes from (for example an explosion))&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;| &amp;lt;h4&amp;gt;Multiplayer Communication&amp;lt;/h4&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!ENTER&lt;br /&gt;
|Chat&lt;br /&gt;
|-&lt;br /&gt;
!ALT + ENTER&lt;br /&gt;
|Allied chat&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + ENTER&lt;br /&gt;
|Spectator chat&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + ENTER&lt;br /&gt;
|Return to global chat&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 1&lt;br /&gt;
|Draw on map.&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(On a UK/US keyboard ` is to the key left of 1. The same functionality is mapped to the \ key)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 2&lt;br /&gt;
|Erase markers and drawings&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 3&lt;br /&gt;
|Place marker&lt;br /&gt;
|-&lt;br /&gt;
!` + Double Click&lt;br /&gt;
|Place marker with annotation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changing bindings ===&lt;br /&gt;
&lt;br /&gt;
Many keyboard bindings can be changed in springsettings.exe (hotkeys tab). In case that doesn&#039;t work, [http://springrts.com/phpbb/viewtopic.php?f=11&amp;amp;t=25043 this] forum thread might be helpful.&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Keyboard&amp;diff=10081</id>
		<title>Keyboard</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Keyboard&amp;diff=10081"/>
		<updated>2011-01-08T17:20:31Z</updated>

		<summary type="html">&lt;p&gt;Meriton: how to change bindings&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:FAQ]]&lt;br /&gt;
&lt;br /&gt;
==Default Keyboard Layout in Spring==&lt;br /&gt;
&lt;br /&gt;
Note: this page is currently incomplete&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/mediawiki/images/a/a5/KeyboardLayout.jpg Spring Keyboard Layout Image]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 1 &amp;lt;small&amp;gt;(left)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Select unit/s (also perform selected order, eg: build selected building)&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 2 &amp;lt;small&amp;gt;(right)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Default order. Depending on target:&amp;lt;br&amp;gt; - Move. &amp;lt;small&amp;gt;(drag mouse for line formation)&amp;lt;/small&amp;gt;&amp;lt;br&amp;gt; - Attack / Repair / Reclaim. &amp;lt;small&amp;gt;(drag to target an area)&amp;lt;/small&amp;gt;&amp;lt;br&amp;gt; - Build incomplete building or unit.&amp;lt;br&amp;gt; - Guard.&amp;lt;br&amp;gt; - If an order has been manually selected/hotkeyed, click to cancel.&lt;br /&gt;
|-&lt;br /&gt;
!Scroll Wheel&lt;br /&gt;
|Zoom in/out&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 3&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(click scroll wheel)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Move to point on minimap&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(Mouse 1 &amp;amp; 2 are used to select units and give orders on minimap)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!L&lt;br /&gt;
|(Duplicates middle click functionality)&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT &amp;lt;br&amp;gt;&amp;lt;small&amp;gt;+ (Mouse 1 or 2)&amp;lt;/small&amp;gt;&lt;br /&gt;
| - Queue order. Queue as many as you like.&lt;br /&gt;
(shift+drag to queue a line of buildings)&amp;lt;br&amp;gt; - Add unit/s to group&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + Mouse 1&lt;br /&gt;
|Remove unit/s from group&lt;br /&gt;
|-&lt;br /&gt;
![ and ]&lt;br /&gt;
|Rotate building (first select something to build and then rotate)&lt;br /&gt;
|-&lt;br /&gt;
!A&lt;br /&gt;
|Attack &amp;lt;small&amp;gt;(attack unit/ground)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!M&lt;br /&gt;
|Move&lt;br /&gt;
|-&lt;br /&gt;
!F&lt;br /&gt;
|Fight &amp;lt;small&amp;gt;(as move, but units will stop to kill enemies along the way)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!G&lt;br /&gt;
|Guard&lt;br /&gt;
|-&lt;br /&gt;
!P&lt;br /&gt;
|Patrol. &amp;lt;small&amp;gt;(Moves back and forth between current position and patrol position)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!S&lt;br /&gt;
|Stop&lt;br /&gt;
|-&lt;br /&gt;
!E&lt;br /&gt;
|Reclaim&lt;br /&gt;
|-&lt;br /&gt;
!R&lt;br /&gt;
|Repair&lt;br /&gt;
|-&lt;br /&gt;
!D&lt;br /&gt;
|D-Gun&lt;br /&gt;
|-&lt;br /&gt;
!X&lt;br /&gt;
|On/Off. &amp;lt;small&amp;gt;(as the unit on/off button)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!K&lt;br /&gt;
|Cloak on/off&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + D&lt;br /&gt;
|Self Destruct&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + W&lt;br /&gt;
|Queue &#039;wait&#039; command&lt;br /&gt;
|-&lt;br /&gt;
!W&lt;br /&gt;
|Stop waiting&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + number (1-0)&lt;br /&gt;
|Assign group&lt;br /&gt;
|-&lt;br /&gt;
!number (1-0)&lt;br /&gt;
|Select group&lt;br /&gt;
|-&lt;br /&gt;
!Double Click&lt;br /&gt;
|Select all units of targetted type in view&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + Z&lt;br /&gt;
|Select all units of selected type on map.&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + A&lt;br /&gt;
|Select all units on map.&lt;br /&gt;
|-&lt;br /&gt;
!ALT + SHIFT (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a rectangular area of buildings.&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a line of buildings.&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + CTRL (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a line of buildings with fixed angles of 90 degrees.&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + SHIFT (+ mouse click)&lt;br /&gt;
|Build a circular area of buildings around some other building (must point on the building with mouse cursor).&lt;br /&gt;
|-&lt;br /&gt;
!TAB&lt;br /&gt;
|Zooms out to see the whole map.&lt;br /&gt;
|-&lt;br /&gt;
!F1&lt;br /&gt;
|Shows heightmap&lt;br /&gt;
|-&lt;br /&gt;
!F2&lt;br /&gt;
|Shows areas where you can build (if the building what you want to build is selected)&lt;br /&gt;
|-&lt;br /&gt;
!F3&lt;br /&gt;
|Goes to the latest spot of action (also goes to the latest markers)&lt;br /&gt;
|-&lt;br /&gt;
!F4&lt;br /&gt;
|Shows metalmap&lt;br /&gt;
|-&lt;br /&gt;
!F5&lt;br /&gt;
|Hides User Interface&lt;br /&gt;
|-&lt;br /&gt;
!CTRL+F5&lt;br /&gt;
|Changes to a cooler camera mode&lt;br /&gt;
|-&lt;br /&gt;
!F6&lt;br /&gt;
|Turns sounds off (currently a bug causes sounds be on when zoomed in the spot where sound comes from (for example an explosion))&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;| &amp;lt;h4&amp;gt;Multiplayer Communication&amp;lt;/h4&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!ENTER&lt;br /&gt;
|Chat&lt;br /&gt;
|-&lt;br /&gt;
!ALT + ENTER&lt;br /&gt;
|Allied chat&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + ENTER&lt;br /&gt;
|Spectator chat&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + ENTER&lt;br /&gt;
|Return to global chat&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 1&lt;br /&gt;
|Draw on map.&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(On a UK/US keyboard ` is to the key left of 1. The same functionality is mapped to the \ key)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 2&lt;br /&gt;
|Erase markers and drawings&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 3&lt;br /&gt;
|Place marker&lt;br /&gt;
|-&lt;br /&gt;
!` + Double Click&lt;br /&gt;
|Place marker with annotation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Changing bindings ===&lt;br /&gt;
&lt;br /&gt;
Many keyboard bindings can be changed in springsettings.exe (hotkeys tab).&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
	<entry>
		<id>https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Keyboard&amp;diff=10080</id>
		<title>Keyboard</title>
		<link rel="alternate" type="text/html" href="https://springrts-wiki.p2004a.com/mediawiki/index.php?title=Keyboard&amp;diff=10080"/>
		<updated>2011-01-08T15:35:09Z</updated>

		<summary type="html">&lt;p&gt;Meriton: referenced uikeys.txt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[category:FAQ]]&lt;br /&gt;
&lt;br /&gt;
==Default Keyboard Layout in Spring==&lt;br /&gt;
&lt;br /&gt;
Note: this page is currently incomplete&lt;br /&gt;
&lt;br /&gt;
[http://springrts.com/mediawiki/images/a/a5/KeyboardLayout.jpg Spring Keyboard Layout Image]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 1 &amp;lt;small&amp;gt;(left)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Select unit/s (also perform selected order, eg: build selected building)&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 2 &amp;lt;small&amp;gt;(right)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Default order. Depending on target:&amp;lt;br&amp;gt; - Move. &amp;lt;small&amp;gt;(drag mouse for line formation)&amp;lt;/small&amp;gt;&amp;lt;br&amp;gt; - Attack / Repair / Reclaim. &amp;lt;small&amp;gt;(drag to target an area)&amp;lt;/small&amp;gt;&amp;lt;br&amp;gt; - Build incomplete building or unit.&amp;lt;br&amp;gt; - Guard.&amp;lt;br&amp;gt; - If an order has been manually selected/hotkeyed, click to cancel.&lt;br /&gt;
|-&lt;br /&gt;
!Scroll Wheel&lt;br /&gt;
|Zoom in/out&lt;br /&gt;
|-&lt;br /&gt;
!Mouse Button 3&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(click scroll wheel)&amp;lt;/small&amp;gt;&lt;br /&gt;
|Move to point on minimap&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(Mouse 1 &amp;amp; 2 are used to select units and give orders on minimap)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!L&lt;br /&gt;
|(Duplicates middle click functionality)&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT &amp;lt;br&amp;gt;&amp;lt;small&amp;gt;+ (Mouse 1 or 2)&amp;lt;/small&amp;gt;&lt;br /&gt;
| - Queue order. Queue as many as you like.&lt;br /&gt;
(shift+drag to queue a line of buildings)&amp;lt;br&amp;gt; - Add unit/s to group&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + Mouse 1&lt;br /&gt;
|Remove unit/s from group&lt;br /&gt;
|-&lt;br /&gt;
![ and ]&lt;br /&gt;
|Rotate building (first select something to build and then rotate)&lt;br /&gt;
|-&lt;br /&gt;
!A&lt;br /&gt;
|Attack &amp;lt;small&amp;gt;(attack unit/ground)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
!M&lt;br /&gt;
|Move&lt;br /&gt;
|-&lt;br /&gt;
!F&lt;br /&gt;
|Fight &amp;lt;small&amp;gt;(as move, but units will stop to kill enemies along the way)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!G&lt;br /&gt;
|Guard&lt;br /&gt;
|-&lt;br /&gt;
!P&lt;br /&gt;
|Patrol. &amp;lt;small&amp;gt;(Moves back and forth between current position and patrol position)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!S&lt;br /&gt;
|Stop&lt;br /&gt;
|-&lt;br /&gt;
!E&lt;br /&gt;
|Reclaim&lt;br /&gt;
|-&lt;br /&gt;
!R&lt;br /&gt;
|Repair&lt;br /&gt;
|-&lt;br /&gt;
!D&lt;br /&gt;
|D-Gun&lt;br /&gt;
|-&lt;br /&gt;
!X&lt;br /&gt;
|On/Off. &amp;lt;small&amp;gt;(as the unit on/off button)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!K&lt;br /&gt;
|Cloak on/off&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + D&lt;br /&gt;
|Self Destruct&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + W&lt;br /&gt;
|Queue &#039;wait&#039; command&lt;br /&gt;
|-&lt;br /&gt;
!W&lt;br /&gt;
|Stop waiting&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + number (1-0)&lt;br /&gt;
|Assign group&lt;br /&gt;
|-&lt;br /&gt;
!number (1-0)&lt;br /&gt;
|Select group&lt;br /&gt;
|-&lt;br /&gt;
!Double Click&lt;br /&gt;
|Select all units of targetted type in view&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + Z&lt;br /&gt;
|Select all units of selected type on map.&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + A&lt;br /&gt;
|Select all units on map.&lt;br /&gt;
|-&lt;br /&gt;
!ALT + SHIFT (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a rectangular area of buildings.&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a line of buildings.&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + CTRL (+ mouse click &amp;amp; drag)&lt;br /&gt;
|Build a line of buildings with fixed angles of 90 degrees.&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + SHIFT (+ mouse click)&lt;br /&gt;
|Build a circular area of buildings around some other building (must point on the building with mouse cursor).&lt;br /&gt;
|-&lt;br /&gt;
!TAB&lt;br /&gt;
|Zooms out to see the whole map.&lt;br /&gt;
|-&lt;br /&gt;
!F1&lt;br /&gt;
|Shows heightmap&lt;br /&gt;
|-&lt;br /&gt;
!F2&lt;br /&gt;
|Shows areas where you can build (if the building what you want to build is selected)&lt;br /&gt;
|-&lt;br /&gt;
!F3&lt;br /&gt;
|Goes to the latest spot of action (also goes to the latest markers)&lt;br /&gt;
|-&lt;br /&gt;
!F4&lt;br /&gt;
|Shows metalmap&lt;br /&gt;
|-&lt;br /&gt;
!F5&lt;br /&gt;
|Hides User Interface&lt;br /&gt;
|-&lt;br /&gt;
!CTRL+F5&lt;br /&gt;
|Changes to a cooler camera mode&lt;br /&gt;
|-&lt;br /&gt;
!F6&lt;br /&gt;
|Turns sounds off (currently a bug causes sounds be on when zoomed in the spot where sound comes from (for example an explosion))&lt;br /&gt;
|-&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;| &amp;lt;h4&amp;gt;Multiplayer Communication&amp;lt;/h4&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!ENTER&lt;br /&gt;
|Chat&lt;br /&gt;
|-&lt;br /&gt;
!ALT + ENTER&lt;br /&gt;
|Allied chat&lt;br /&gt;
|-&lt;br /&gt;
!SHIFT + ENTER&lt;br /&gt;
|Spectator chat&lt;br /&gt;
|-&lt;br /&gt;
!CTRL + ENTER&lt;br /&gt;
|Return to global chat&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 1&lt;br /&gt;
|Draw on map.&amp;lt;br&amp;gt;&amp;lt;small&amp;gt;(On a UK/US keyboard ` is to the key left of 1. The same functionality is mapped to the \ key)&amp;lt;/small&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 2&lt;br /&gt;
|Erase markers and drawings&lt;br /&gt;
|-&lt;br /&gt;
!` + Mouse Button 3&lt;br /&gt;
|Place marker&lt;br /&gt;
|-&lt;br /&gt;
!` + Double Click&lt;br /&gt;
|Place marker with annotation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More ===&lt;br /&gt;
&lt;br /&gt;
The keyboad binding configuration is stored in the file uikeys.txt in the Spring installation directory. That file also contains a more complete list of default keyboad bindings.&lt;/div&gt;</summary>
		<author><name>Meriton</name></author>
	</entry>
</feed>