View Javadoc

1   /*
2    * Copyright (C) 2013 AMIS research group, Faculty of Mathematics and Physics, Charles University in Prague, Czech Republic
3    *
4    * This program is free software: you can redistribute it and/or modify
5    * it under the terms of the GNU General Public License as published by
6    * the Free Software Foundation, either version 3 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,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16   */
17  package cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh;
18  
19  import java.io.File;
20  import java.io.FileInputStream;
21  import java.io.FileOutputStream;
22  import java.io.ObjectInputStream;
23  import java.io.ObjectOutputStream;
24  import java.util.Random;
25  import java.util.logging.Logger;
26  
27  import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
28  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
29  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
30  import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectFirstEncounteredEvent;
31  import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
32  import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
33  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.drawing.IUT2004ServerProvider;
34  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.drawing.LevelGeometryDraw;
35  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo;
36  import cz.cuni.amis.utils.ExceptionToString;
37  
38  /**
39   * LevelGeometryModule is wrapping the load/save logic for the {@link LevelGeometry}.
40   * 
41   * @author Jakub Tomek
42   * @author Jakub Gemrot aka Jimmy
43   */
44  public class LevelGeometryModule {
45  	
46  	private IWorldView worldView;	
47  	private Logger log;
48  	
49  	private Random random;
50  		
51  	//
52  	// STATE
53  	//
54  	
55  	private boolean loaded = false;
56  	private GameInfo loadedForMap = null;
57  	
58  	//
59  	// NAVMESH DATA STRUCTURES
60  	//
61  	
62      private LevelGeometry levelGeometry;
63      private LevelGeometryDraw draw;
64      
65  	private IWorldObjectEventListener<GameInfo, IWorldObjectEvent<GameInfo>> gameInfoListener = new IWorldObjectEventListener<GameInfo, IWorldObjectEvent<GameInfo>>() {
66  		@Override
67  		public void notify(IWorldObjectEvent<GameInfo> event) {
68  			load(event.getObject());
69  		}
70  	};
71         
72      public LevelGeometryModule(IUT2004ServerProvider serverProvider, IWorldView worldView, IAgentLogger logger) {
73      	if (logger == null) {
74      		log = new LogCategory("LevelGeometry");
75      	} else {
76      		log = logger.getCategory("LevelGeometry");
77      	}
78      	random = new Random();
79      	
80      	worldView.addObjectListener(GameInfo.class, WorldObjectFirstEncounteredEvent.class, gameInfoListener);
81      	
82      	GameInfo info = worldView.getSingle(GameInfo.class);
83      	if (info != null) {
84      		load(info);
85      	}
86      	
87      	draw = new LevelGeometryDraw(null, log, serverProvider);
88      }
89      
90      private void clear() {
91      	log.warning("LevelGeometry has been cleared...");
92      	
93          levelGeometry = null;
94          
95          loaded = false;
96          loadedForMap = null;
97      }
98      	
99      private boolean loadLevelGeometry(String mapName) {
100     	// try to read it from processed file        
101         String levelGeometryFileName = NavMeshConstants.processedLevelGeometryDir + "\\" + mapName + ".processed";
102         File levelGeometryFile = new File(levelGeometryFileName);
103         
104         try {
105         	if (!levelGeometryFile.exists()) {
106         		log.warning("Processed LevelGeometry does not exist at: " + levelGeometryFile.getAbsolutePath());
107         	} else {
108         		log.info("Loading previously stored LevelGeometry from binary file: " + levelGeometryFile.getAbsolutePath());
109 	            ObjectInputStream in = new ObjectInputStream(new FileInputStream(levelGeometryFile));
110 	            levelGeometry = (LevelGeometry) in.readObject();  	            
111 	            log.info("LevelGeometry LOADED SUCCESSFULLY.");
112 	            return true;
113         	}
114         } catch (Exception e) {
115         	log.severe(ExceptionToString.process("Previously saved level geometry file could not have been restored.", e));
116         }        
117 
118         try { 
119             levelGeometry = new LevelGeometry(log);
120             if (levelGeometry.load(mapName)) {
121             	log.info("LevelGeometry LOADED SUCCESSFULLY.");
122             	
123 	            // save levelgeom for next time
124 	            try {
125 	                log.warning("Writing level geometry to a file at: " + levelGeometryFile.getAbsolutePath());
126 	                levelGeometryFile.getParentFile().mkdirs();
127 	                ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(levelGeometryFile));
128 	                out.writeObject(levelGeometry); 
129 	                log.info("Level geometry written ok.");
130 	            } catch (Exception e) {
131 	            	log.severe(ExceptionToString.process("Exception during writing level geom to a file.", e));
132 	            }  
133 	            
134 	            return true;
135             }
136             log.severe("COULD NOT INITIALIZE FOR MAP: " + mapName);
137             levelGeometry = null;
138             return false;
139         } catch(Exception e) {
140         	log.severe(ExceptionToString.process("Unable to load level geometry files.", e));
141             levelGeometry = null;
142             return false;
143         }        
144     }
145     
146     private void load(GameInfo info) {
147     	if (info == null) {
148     		log.severe("Could not load for 'null' GameInfo!");
149     		return;
150     	}
151         if (loaded) {
152         	if (loadedForMap == null) {
153         		// WTF?
154         		// => clear
155         		clear();
156         		// => and reload
157         	} else {
158         		if (loadedForMap.getLevel().equals(info.getLevel())) {
159         			// ALREADY INITIALIZED FOR THE SAME LEVEL
160         			return;
161         		}
162         	}
163         }
164         
165         // LOAD THE LEVEL GEOMETRY FOR THE MAP FROM 'info'
166         String mapName = info.getLevel();        
167         log.warning("Initializing LevelGeometry for: " + mapName);
168     	
169         if (loadLevelGeometry(mapName)) {	 
170         	draw.setLevelGeometry(levelGeometry);
171 	        loaded = true;
172 	        loadedForMap = info;
173 	        return;
174         } 
175         
176         loaded = false;
177         loadedForMap = null;
178     }
179     
180     /**
181      * Tells, whether the module has been correctly initialized and it is possible to call {@link #getLevelGeometry()} method.  
182      * @return
183      */
184     public boolean isInitialized() {
185     	return this.levelGeometry != null && this.levelGeometry.isLoaded();
186     }
187     
188     /**
189      * Returns {@link LevelGeometry} object for currently running map.
190      * 
191      * Non-null iff {@link #isInitialized()}.
192      * 
193      * @return 
194      */
195     public LevelGeometry getLevelGeometry() {
196         return this.levelGeometry;
197     }
198     
199     /**
200      * Return {@link LevelGeometryDraw} that can be used to visualize currently loaded {@link LevelGeometry} from this module.
201      * @return
202      */
203     public LevelGeometryDraw getDraw() {
204     	return this.draw;
205     }
206     
207 }