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