1 // Copyright Hugh Perkins 2006, 2009
2 // hughperkins@gmail.com http://manageddreams.com
3 //
4 // This program is free software; you can redistribute it and/or modify it
5 // under the terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 //  more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program in the file licence.txt; if not, write to the
16 // Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-
17 // 1307 USA
18 // You can find the licence also on the web at:
19 // http://www.opensource.org/licenses/gpl-license.php
20 //
21 // ======================================================================================
22 //
23 
24 package hughai.unitdata;
25 
26 import java.util.*;
27 import java.util.Map;
28 
29 import com.springrts.ai.*;
30 import com.springrts.ai.oo.clb.*;
31 
32 import hughai.*;
33 import hughai.utils.*;
34 import hughai.basictypes.*;
35 import hughai.basictypes.Float3.*;
36 import hughai.ui.*;
37 
38 // The role of UnitController is to keep track of what units we have
39 // Really it's just a wrapper for unitfinished and unitdestroyed events from csai.
40 // Note to self: do we really need this class???
41 public class UnitController
42 {
43 	public static interface UnitListener {
ExistingUnit(Unit unit)44 		public void ExistingUnit(Unit unit);
UnitAdded(Unit unit )45 		public void UnitAdded(Unit unit );
UnitRemoved( Unit unit )46 		public void UnitRemoved( Unit unit );
AllUnitsLoaded()47 		public void AllUnitsLoaded();
48 	}
49 	public static class UnitAdapter implements UnitListener {
ExistingUnit(Unit unit)50 		@Override public void ExistingUnit(Unit unit){}
UnitAdded(Unit unit )51 		@Override public void UnitAdded(Unit unit ){}
UnitRemoved( Unit unit )52 		@Override public void UnitRemoved( Unit unit ){}
AllUnitsLoaded()53 		@Override public void AllUnitsLoaded(){}
54 	}
55 
56 	HashSet<UnitListener> unitListeners = new HashSet<UnitListener>();
57 
registerListener( UnitListener listener )58 	public void registerListener( UnitListener listener ){
59 		unitListeners.add(listener);
60 	}
61 
62 	CSAI csai;
63 	OOAICallback aicallback;
64 	LogFile logfile;
65 	UnitDefHelp unitdefhelp;
66 	GiveOrderWrapper giveOrderWrapper;
67 	DrawingUtils drawingUtils;
68 
69 	//public Hashtable UnitDefByDeployedId = new Hashtable();
70 	//public HashMap<Integer,UnitDef> UnitDefByDeployedId = new HashMap<Integer,UnitDef>();
71 	//public HashMap<Integer,Unit> UnitByUnitId = new HashMap<Integer,Unit>();
72 	public HashMap<String, List<Unit>> UnitsByName = new HashMap<String, List<Unit>>();
73 	public List<Unit> units = new ArrayList<Unit>();
74 	HashMap<Unit,UnitDef> unitdefbyunit = new HashMap<Unit, UnitDef>(); // because unit.getDef() is f**king slow.
75 
76 	// wipe these each frame:
77 	HashMap<Unit,TerrainPos> posbyunit = new HashMap<Unit,TerrainPos>();
78     List<Map<?,?>> mapstowipeeachframe = Arrays.asList( new Map<?,?>[]{
79        posbyunit } );
80 
getUnitDef( Unit unit )81 	public UnitDef getUnitDef( Unit unit ) {
82 	   return unitdefbyunit.get( unit );
83 	}
84 
85 	// retrieves cached pos if exists, or gets it, and caches it.
getPos( Unit unit )86 	public TerrainPos getPos( Unit unit ) {
87 	   // we assume that mostly the pos will already exist, so check this first
88 	   if( posbyunit.containsKey( unit ) ) {
89 	      return posbyunit.get( unit );
90 	   }
91 	   // store it in variable, so we don't have to do a fetch from the collection after the put
92 	   TerrainPos thispos = TerrainPos.fromAIFloat3( unit.getPos() );
93 	   if( thispos.equals( new TerrainPos() ) ) { // if the pos is zero, just make it null, it makes life simpler...
94 	      thispos = null;
95 	   }
96        posbyunit.put( unit, thispos );
97        return thispos;
98 	}
99 
UnitController( PlayerObjects playerObjects )100 	public UnitController( PlayerObjects playerObjects )
101 	{
102 		csai = playerObjects.getCSAI();
103 		aicallback = csai.aicallback;
104 		logfile = playerObjects.getLogFile();
105 		unitdefhelp = new UnitDefHelp( playerObjects );
106 		giveOrderWrapper = playerObjects.getGiveOrderWrapper();
107 		drawingUtils = playerObjects.getDrawingUtils();
108 
109 		csai.registerGameListener(new GameListenerHandler());
110 
111 //		csai.RegisterVoiceCommand( "killallfriendly", new VoiceCommandKillAllFriendlyHandler() );
112 		csai.RegisterVoiceCommand( "countunits", new VoiceCommandCountUnits() );
113 //        csai.RegisterVoiceCommand( "labelunits", new VoiceLabelUnits() );
114 
115         playerObjects.getMainUI().registerButton( "Label units", new ButtonLabelUnits() );
116         playerObjects.getMainUI().registerButton( "Kill all friendly", new ButtonKillAllFriendly() );
117 
118 		logfile.WriteLine ("*UnitController initialized*");
119 	}
120 
121 	class ButtonLabelUnits implements MainUI.ButtonHandler {
go()122 	   public void go() {
123 	      labelUnits();
124 	   }
125 	}
126 
127     class ButtonKillAllFriendly implements MainUI.ButtonHandler {
go()128        public void go() {
129           killAllFriendly();
130        }
131     }
132 
133 	public class VoiceCommandCountUnits implements VoiceCommandHandler {
commandReceived( String cmd, String[]splitcmd, int player )134 		@Override public void commandReceived( String cmd, String[]splitcmd, int player )
135 		{
136 			csai.SendTextMsg( "friendly unit count: " + units.size() );
137 		}
138 	}
139 
140     public class VoiceLabelUnits implements VoiceCommandHandler {
commandReceived( String cmd, String[]splitcmd, int player )141        @Override public void commandReceived( String cmd, String[]splitcmd, int player )
142        {
143           labelUnits();
144        }
145    }
146 
labelUnits()147     public void labelUnits() {
148        for( Unit unit : units ) {
149           drawingUtils.drawText( getPos( unit ), "" + unit.getUnitId() );
150        }
151     }
152 
153 	class GameListenerHandler extends GameAdapter {
154 		@Override
Tick( int frame )155 		public void Tick( int frame ) {
156 //			csai.sendTextMessage("unitcontroller.tick");
157 			//units = aicallback.getTeamUnits();
158            for( Map<?,?> map : mapstowipeeachframe ) {
159               map.clear();
160            }
161 		}
162 
163 		@Override
UnitFinished( Unit newunit )164 		public void UnitFinished( Unit newunit )
165 		{
166 			logfile.WriteLine( "UnitController.NewUnitFinished " + newunit.getDef().getHumanName() + " " + newunit.getUnitId() );
167 			AddUnit( newunit );
168 		}
169 
170 		@Override
UnitDestroyed( Unit destroyedunit, Unit enemy )171 		public void UnitDestroyed( Unit destroyedunit, Unit enemy )
172 		{
173 			logfile.WriteLine( "UnitController.UnitDestroyed " + destroyedunit.getUnitId() );
174 			RemoveUnit( destroyedunit );
175 		}
176 	}
177 
LoadExistingUnits()178 	public void LoadExistingUnits()
179 	{
180 		List<Unit> friendlyunits = aicallback.getFriendlyUnits();
181 		for( Unit friendlyunit : friendlyunits )
182 		{
183 			logfile.WriteLine("friendly unit existing: " + friendlyunit.getUnitId() + " " + friendlyunit.getDef().getHumanName() + " " + friendlyunit.getDef().getName() + " " + friendlyunit.getDef().getHumanName() );
184 			AddUnit( friendlyunit );
185 			for( UnitListener unitListener : unitListeners ) {
186 				unitListener.ExistingUnit( friendlyunit );
187 			}
188 		}
189 		for( UnitListener unitListener : unitListeners ) {
190 			unitListener.AllUnitsLoaded();
191 		}
192 	}
193 
RefreshMyMemory( UnitListener listener )194 	public void RefreshMyMemory( UnitListener listener )
195 	{
196 		units = aicallback.getTeamUnits();
197 		//for( int deployedid : UnitByUnitId.keySet() )
198 		for( Unit unit : units )
199 		{
200 		//	Unit unit = UnitByUnitId.get(deployedid);
201 			listener.UnitAdded( unit );
202 		}
203 	}
204 
AddUnit( Unit friendlyunit )205 	public void AddUnit( Unit friendlyunit )
206 	{
207 		UnitDef unitdef = friendlyunit.getDef();
208 		if( !units.contains( friendlyunit ) )
209 		{
210 			logfile.WriteLine("UnitController.AddUnit: unit id " + friendlyunit.getDef().getName() + " " + unitdef.getHumanName() );
211 			String name = unitdef.getName().toLowerCase();
212 			//UnitByUnitId.put( friendlyunit.getUnitId(), friendlyunit );
213 			if( !UnitsByName.containsKey( name ) )
214 			{
215 				UnitsByName.put( name, new ArrayList<Unit>() );
216 			}
217 			UnitsByName.get(name).add(friendlyunit);
218 			units.add(friendlyunit);
219 			unitdefbyunit.put( friendlyunit, friendlyunit.getDef() );
220 
221 			for( UnitListener unitListener : unitListeners ) {
222 				unitListener.UnitAdded( friendlyunit );
223 			}
224 			logfile.WriteLine("UnitController.AddUnit finished");
225 		}
226 		else
227 		{
228 			logfile.WriteLine( "UnitController.AddUnit: unit id " + friendlyunit.getUnitId() + " " + unitdef.getHumanName() + " already exists" );
229 		}
230 	}
231 
RemoveUnit( Unit friendlyunit )232 	void RemoveUnit( Unit friendlyunit )
233 	{
234 		if( units.contains( friendlyunit ) )
235 		{
236 			UnitDef unitdef = friendlyunit.getDef();
237 			String name = unitdef.getName().toLowerCase();
238 			//UnitByUnitId.remove(friendlyunit);
239 			UnitsByName.get(name).remove(friendlyunit);
240 			units.remove(friendlyunit);
241 			unitdefbyunit.remove(  friendlyunit );
242 		}
243 		for( UnitListener unitListener : unitListeners ) {
244 			unitListener.UnitRemoved( friendlyunit );
245 		}
246 	}
247 
killAllFriendly()248 	public void killAllFriendly(){
249        for( Unit unit : units )
250        {
251            if( !unit.getDef().isCommander() )
252            {
253                giveOrderWrapper.SelfDestruct(unit);
254            }
255        }
256 	}
257 
258 	// kills all except commander, allows testing expansion from nothing, without having to relaod spring.exe
259 	public class VoiceCommandKillAllFriendlyHandler implements VoiceCommandHandler {
260 		@Override
commandReceived( String cmd, String[]splitcmd, int player )261 		public void commandReceived( String cmd, String[]splitcmd, int player )
262 		{
263 		   killAllFriendly();
264 		}
265 	}
266 }
267