project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Scheme.java
changeset 7476 2fb781bbdd51
parent 6852 9e724f4863a3
child 7485 0481bd74267c
equal deleted inserted replaced
7473:45b9f25ff611 7476:2fb781bbdd51
    17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    18  */
    18  */
    19 
    19 
    20 package org.hedgewars.hedgeroid.Datastructures;
    20 package org.hedgewars.hedgeroid.Datastructures;
    21 
    21 
       
    22 import java.util.Collections;
       
    23 import java.util.Comparator;
       
    24 import java.util.HashMap;
    22 import java.util.Map;
    25 import java.util.Map;
    23 
    26 
    24 import java.io.File;
    27 public final class Scheme {
    25 import java.io.FilenameFilter;
    28 	public final MetaScheme metascheme;
    26 import java.io.IOException;
    29 	public final String name;
    27 import java.util.ArrayList;
    30 	public final Map<String, Integer> settings;
    28 import java.util.Arrays;
    31 	public final Map<String, Boolean> mods;
    29 import java.util.List;
       
    30 import java.util.Map.Entry;
       
    31 import java.util.TreeMap;
       
    32 
       
    33 import org.hedgewars.hedgeroid.EngineProtocol.EngineProtocolNetwork;
       
    34 import org.ini4j.Ini;
       
    35 import org.ini4j.InvalidFileFormatException;
       
    36 import org.ini4j.Profile.Section;
       
    37 
       
    38 import android.content.Context;
       
    39 import android.os.Parcel;
       
    40 import android.os.Parcelable;
       
    41 import android.util.Log;
       
    42 
       
    43 public class Scheme implements Parcelable, Comparable<Scheme>{
       
    44 	public static final String DIRECTORY_SCHEME = "schemes";
       
    45 	private static final Map<String, BasicSettingMeta> basicSettingsMeta = new TreeMap<String, BasicSettingMeta>();
       
    46 	private static final Map<String, GameModMeta> gameModsMeta = new TreeMap<String, GameModMeta>();
       
    47 
       
    48 	private final String name;
       
    49 	private final int gamemod;
       
    50 	private final Map<String, Integer> basic = new TreeMap<String, Integer>();
       
    51 		
    32 		
    52 	public Scheme(String _name, Map<String, Integer> _basic, int _gamemod) {
    33 	public Scheme(MetaScheme metascheme, String name, Map<String, Integer> settings, Map<String, Boolean> mods) {
    53 		name = _name;
    34 		this.metascheme = metascheme;
    54 		gamemod = _gamemod;
    35 		this.name = name;
    55 		basic.putAll(_basic);
    36 		this.settings = Collections.unmodifiableMap(new HashMap<String, Integer>(settings));
       
    37 		this.mods = Collections.unmodifiableMap(new HashMap<String, Boolean>(mods));
    56 	}
    38 	}
    57 	
    39 	
    58 	public Scheme(Parcel in){
       
    59 		name = in.readString();
       
    60 		gamemod = in.readInt();
       
    61 		in.readMap(basic, Integer.class.getClassLoader());
       
    62 	}
       
    63 
       
    64 	public int getHealth() {
    40 	public int getHealth() {
    65 		return basic.get("InitialHealth");
    41 		return settings.get("health");
    66 	}
       
    67 	
       
    68 	public void sendToEngine(EngineProtocolNetwork epn) throws IOException{ 
       
    69 		epn.sendToEngine(String.format("e$gmflags %d", gamemod));
       
    70 
       
    71 		for(Map.Entry<String, Integer> entry : basic.entrySet()) {
       
    72 			BasicSettingMeta basicflag = basicSettingsMeta.get(entry.getKey());
       
    73 			
       
    74 			//Health is a special case, it doesn't need to be send 				                             
       
    75 			//to the engine yet, we'll do that with the other HH info
       
    76 			if(!basicflag.command.equals("inithealth")){
       
    77 				epn.sendToEngine(String.format("%s %d", basicflag.command, entry.getValue()));
       
    78 			}
       
    79 		}
       
    80 	}
       
    81 	
       
    82 	public String toString(){
       
    83 		return name;
       
    84 	}
       
    85 
       
    86 	public static List<Scheme> getSchemes(Context c) throws IllegalArgumentException {
       
    87 		File schemeDir = new File(c.getFilesDir(), DIRECTORY_SCHEME);
       
    88 		File[] files = schemeDir.listFiles(new FilenameFilter() {
       
    89 			public boolean accept(File dir, String filename) {
       
    90 				return filename.toLowerCase().startsWith("scheme_");
       
    91 			}
       
    92 		});
       
    93 		if(files == null) files = new File[0];
       
    94 		Arrays.sort(files);
       
    95 		List<Scheme> schemes = new ArrayList<Scheme>();
       
    96 
       
    97 		for(File file : files) {
       
    98 			try {
       
    99 				Ini ini = new Ini(file);
       
   100 				
       
   101 				String name = ini.get("Scheme", "name");
       
   102 				if(name==null) {
       
   103 					name = file.getName();
       
   104 				}
       
   105 				Section basicSettingsSection = ini.get("BasicSettings");
       
   106 				Section gameModsSection = ini.get("GameMods");
       
   107 				if(basicSettingsSection == null || gameModsSection == null) {
       
   108 					Log.e(Scheme.class.getCanonicalName(), "Scheme file "+file+" is missing the BasicSettings or GameMods section - skipping.");
       
   109 					continue;
       
   110 				}
       
   111 				
       
   112 				Map<String, Integer> basicSettings = new TreeMap<String, Integer>();
       
   113 				for(Entry<String, BasicSettingMeta> entry : basicSettingsMeta.entrySet()) {
       
   114 					String key = entry.getKey();
       
   115 					BasicSettingMeta settingMeta = entry.getValue();
       
   116 					Integer value = null;
       
   117 					if(basicSettingsSection.containsKey(key)) {
       
   118 						try {
       
   119 							value = Integer.valueOf(basicSettingsSection.get(key));						
       
   120 						} catch (NumberFormatException e) {
       
   121 							// ignore
       
   122 						}
       
   123 					}
       
   124 					
       
   125 					if(value==null) {
       
   126 						Log.w(Scheme.class.getCanonicalName(), "Scheme file "+file+" setting "+key+" is missing or invalid, using default.");
       
   127 						value = settingMeta.def;
       
   128 					}
       
   129 					
       
   130 					if(settingMeta.checkOverMax) {
       
   131 						value = Math.min(value, settingMeta.max);
       
   132 					}
       
   133 					if(settingMeta.times1000) {
       
   134 						value *= 1000;
       
   135 					}
       
   136 					
       
   137 					basicSettings.put(key, value);						
       
   138 				}
       
   139 				
       
   140 				int gamemods = 0;
       
   141 				for(Entry<String, GameModMeta> entry : gameModsMeta.entrySet()) {
       
   142 					String key = entry.getKey();
       
   143 					GameModMeta modMeta = entry.getValue();
       
   144 					if(Boolean.parseBoolean(gameModsSection.get(key))) {
       
   145 						gamemods |= (1 << modMeta.bitmaskIndex);
       
   146 					}
       
   147 				}
       
   148 				
       
   149 				schemes.add(new Scheme(name, basicSettings, gamemods));
       
   150 			} catch (InvalidFileFormatException e) {
       
   151 				throw new RuntimeException(e);
       
   152 			} catch (IOException e) {
       
   153 				throw new RuntimeException(e);
       
   154 			}
       
   155 		}
       
   156 		return schemes;
       
   157 	}
       
   158 	
       
   159 	/**
       
   160 	 * This method will parse the basic flags from a prespecified ini file.
       
   161 	 * In the future we could use one provided by the Data folder.
       
   162 	 */
       
   163 	public static void parseConfiguration(Context c) {
       
   164 		File schemeDir = new File(c.getFilesDir(), DIRECTORY_SCHEME);
       
   165 		File settingsFile = new File(schemeDir, "basicsettings");
       
   166 		File gameModsFile = new File(schemeDir, "gamemods");
       
   167 		
       
   168 		try {
       
   169 			Ini ini = new Ini(settingsFile);
       
   170 			for(Entry<String, Section> sectionEntry : ini.entrySet()) {
       
   171 				basicSettingsMeta.put(sectionEntry.getKey(), new BasicSettingMeta(sectionEntry.getValue()));
       
   172 			}
       
   173 			
       
   174 			ini = new Ini(gameModsFile);
       
   175 			for(Entry<String, Section> sectionEntry : ini.entrySet()) {
       
   176 				gameModsMeta.put(sectionEntry.getKey(), new GameModMeta(sectionEntry.getValue()));
       
   177 			}
       
   178 		} catch (InvalidFileFormatException e) {
       
   179 			throw new RuntimeException(e);
       
   180 		} catch (IOException e) {
       
   181 			throw new RuntimeException(e);
       
   182 		}
       
   183 	}
       
   184 
       
   185 	public int describeContents() {
       
   186 		return 0;
       
   187 	}
       
   188 
       
   189 	public void writeToParcel(Parcel dest, int flags) {
       
   190 		dest.writeString(name);
       
   191 		dest.writeInt(gamemod);
       
   192 		dest.writeMap(basic);
       
   193 	}
       
   194 
       
   195 	public static final Parcelable.Creator<Scheme> CREATOR = new Parcelable.Creator<Scheme>() {
       
   196 		public Scheme createFromParcel(Parcel source) {
       
   197 			return new Scheme(source);
       
   198 		}
       
   199 		public Scheme[] newArray(int size) {
       
   200 			return new Scheme[size];
       
   201 		}
       
   202 		
       
   203 	};
       
   204 
       
   205 	public int compareTo(Scheme another) {
       
   206 		return name.compareTo(another.name);
       
   207 	}
       
   208 }
       
   209 
       
   210 class BasicSettingMeta {
       
   211 	final String command;
       
   212 	final String title;
       
   213 	final int def;
       
   214 	final int min;
       
   215 	final int max;
       
   216 	final boolean times1000;
       
   217 	final boolean checkOverMax;
       
   218 	
       
   219 	public BasicSettingMeta(Ini.Section section) {
       
   220 		command = getRequired(section, "command");
       
   221 		title = section.get("title", "");
       
   222 		def = Integer.parseInt(getRequired(section, "default"));
       
   223 		min = Integer.parseInt(getRequired(section, "min"));
       
   224 		max = Integer.parseInt(getRequired(section, "max"));
       
   225 		times1000 = Boolean.parseBoolean(section.get("times1000", "false"));
       
   226 		checkOverMax = Boolean.parseBoolean(section.get("checkOverMax", "false"));
       
   227 	}
       
   228 	
       
   229 	private String getRequired(Ini.Section section, String key) {
       
   230 		String result = section.get(key);
       
   231 		if(result==null) {
       
   232 			throw new IllegalArgumentException("basicsettings.ini, section "+section.getName()+" is missing required setting "+key+".");
       
   233 		}
       
   234 		return result;
       
   235 	}
    42 	}
   236 
    43 
   237 	@Override
    44 	@Override
   238 	public String toString() {
    45 	public String toString() {
   239 		return String
    46 		return "Scheme [metascheme=" + metascheme + ", name=" + name
   240 				.format("BasicSettingMeta [command=%s, title=%s, def=%s, min=%s, max=%s, times1000=%s, checkOverMax=%s]",
    47 				+ ", settings=" + settings + ", mods=" + mods + "]";
   241 						command, title, def, min, max, times1000, checkOverMax);
       
   242 	}
       
   243 }
       
   244 
       
   245 // TODO: Extend with additional metadata
       
   246 class GameModMeta {
       
   247 	final int bitmaskIndex;
       
   248 	
       
   249 	public GameModMeta(Ini.Section section) {
       
   250 		bitmaskIndex = Integer.parseInt(getRequired(section, "bitmaskIndex"));
       
   251 	}
    48 	}
   252 	
    49 	
   253 	private String getRequired(Ini.Section section, String key) {
    50 	public static final Comparator<Scheme> caseInsensitiveNameComparator = new Comparator<Scheme>() {
   254 		String result = section.get(key);
    51 		public int compare(Scheme lhs, Scheme rhs) {
   255 		if(result==null) {
    52 			return lhs.name.compareToIgnoreCase(rhs.name);
   256 			throw new IllegalArgumentException("gamemods.ini, section "+section.getName()+" is missing required setting "+key+".");
       
   257 		}
    53 		}
   258 		return result;
    54 	};
   259 	}
       
   260 
       
   261 	@Override
       
   262 	public String toString() {
       
   263 		return String.format("GameModMeta [bitmaskIndex=%s]", bitmaskIndex);
       
   264 	}
       
   265 }
    55 }