datastructures for the different aspects of a gameconfiguration hedgeroid
authorXeli
Thu, 04 Aug 2011 17:27:05 +0200
branchhedgeroid
changeset 5463 83c53a80f7ff
parent 5460 c33b4daa4ce4
child 5465 b7e009722465
datastructures for the different aspects of a gameconfiguration
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/GameMode.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Grave.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Map.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Scheme.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Team.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Weapon.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/GameMode.java	Thu Aug 04 17:27:05 2011 +0200
@@ -0,0 +1,5 @@
+package org.hedgewars.mobile.EngineProtocol;
+
+public enum GameMode {
+		MODE_LOCAL, MODE_DEMO, MODE_NET, MODE_SAVE
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Grave.java	Thu Aug 04 17:27:05 2011 +0200
@@ -0,0 +1,17 @@
+package org.hedgewars.mobile.EngineProtocol;
+
+public class Grave{
+
+	public final String name;
+	public final String path;
+	
+	public Grave(String _name, String _path) {
+		name = _name;
+		path = _path;
+	}
+
+	public String toString(){
+		return name;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Map.java	Thu Aug 04 17:27:05 2011 +0200
@@ -0,0 +1,144 @@
+package org.hedgewars.mobile.EngineProtocol;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class Map implements Comparable<Map>, Parcelable{
+
+	private static final String MISSION_PREFIX = "Mission: ";
+
+	private String name;
+	private String path;
+	private String previewPath;
+	private MapType type;
+
+	public Map(File mapDir, MapType _type, Context c){
+		type = _type;
+
+		name = mapDir.getName();
+		path = mapDir.getAbsolutePath();
+		previewPath = path + "/preview.png";
+		
+		/*switch(type){
+		case TYPE_DEFAULT:
+			
+			break;
+		case TYPE_GENERATED:
+			//TODO
+			break;
+		case TYPE_MISSION:
+			name = MISSION_PREFIX + mapDir.getName();
+			path = mapDir.getAbsolutePath();
+			break;
+		}*/
+
+		
+	}
+	
+	public Map(Parcel in){
+		readFromParcel(in);
+	}
+
+	public String toString(){
+		switch(type){
+		default:
+		case TYPE_DEFAULT:
+			return name;
+		case TYPE_GENERATED:
+			return "bla";
+		case TYPE_MISSION:
+			return MISSION_PREFIX + name;
+		}
+	}
+	
+	public void sendToEngine(EngineProtocolNetwork epn) throws IOException{
+		epn.sendToEngine(String.format("emap %s",name));
+	}
+	
+	public MapType getType(){
+		return type;
+	}
+
+	public Drawable getDrawable(){
+		switch(type){
+		case TYPE_MISSION:
+		case TYPE_DEFAULT:
+			return Drawable.createFromPath(previewPath);
+		case TYPE_GENERATED:
+
+		default:
+			return null;
+		}
+	}
+
+	@Override
+	public int compareTo(Map another) {
+		switch(type){
+		case TYPE_GENERATED:
+			switch(another.getType()){
+			case TYPE_GENERATED:
+				return name.compareTo(another.name);
+			case TYPE_MISSION:
+				return -1;
+			case TYPE_DEFAULT:
+				return -1;
+			}
+		case TYPE_MISSION:
+			switch(another.getType()){
+			case TYPE_GENERATED:
+				return 1;
+			case TYPE_MISSION:
+				return name.compareTo(another.name);
+			case TYPE_DEFAULT:
+				return -1;
+			}
+		case TYPE_DEFAULT:
+			switch(another.getType()){
+			case TYPE_GENERATED:
+				return 1;
+			case TYPE_MISSION:
+				return 1;
+			case TYPE_DEFAULT:
+				return name.compareTo(another.name);
+			}
+		}
+		return 0;//default case this should never happen
+	}
+
+	public enum MapType{
+		TYPE_DEFAULT, TYPE_MISSION, TYPE_GENERATED
+	}
+
+	public int describeContents() {
+		return 0;
+	}
+	
+	public void writeToParcel(Parcel dest, int flags) {
+		dest.writeString(name);
+		dest.writeString(path);
+		dest.writeString(previewPath);
+		dest.writeString(type.name());
+	}
+	
+	private void readFromParcel(Parcel src){
+		name = src.readString();
+		path = src.readString();
+		previewPath = src.readString();
+		type = MapType.valueOf(src.readString());
+	}
+	public static final Parcelable.Creator<Map> CREATOR = new Parcelable.Creator<Map>() {
+		public Map createFromParcel(Parcel source) {
+			return new Map(source);
+		}
+		public Map[] newArray(int size) {
+			return new Map[size];
+		}
+		
+	};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Scheme.java	Thu Aug 04 17:27:05 2011 +0200
@@ -0,0 +1,343 @@
+package org.hedgewars.mobile.EngineProtocol;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class Scheme implements Parcelable{
+
+	public static final String DIRECTORY_SCHEME = "schemes";
+
+	private String name;
+	//private ArrayList<Integer> basic;
+	private Integer gamemod;
+	private ArrayList<Integer> basic;;
+	private static ArrayList<LinkedHashMap<String, ?>> basicflags = new ArrayList<LinkedHashMap<String, ?>>();
+	
+	public Scheme(String _name, ArrayList<Integer> _basic, int _gamemod){
+		name = _name;
+		gamemod = _gamemod;
+		basic = _basic;
+
+	}
+	
+	public Scheme(Parcel in){
+		readFromParcel(in);
+	}
+
+	public void sendToEngine(OutputStream os)throws IOException{ 
+		os.write(String.format("e$gmflags %d", gamemod).getBytes());
+
+		for(int pos = 0; pos < basic.size(); pos++){
+			LinkedHashMap<String, ?> basicflag = basicflags.get(pos);
+			
+			String command = (String)basicflag.get("command");
+			Integer value = basic.get(pos);
+			Boolean checkOverMax = (Boolean) basicflag.get("checkOverMax");
+			Boolean times1000 = (Boolean) basicflag.get("times1000");
+			Integer max = (Integer) basicflag.get("max");
+			
+			if(checkOverMax && value >= max) value = max;
+			if(times1000) value *= 1000;
+			
+			os.write(String.format("%s %d", command, value).getBytes());
+		}
+		os.flush();
+	}
+	public String toString(){
+		return name;
+	}
+
+
+	public static final int STATE_START = 0;
+	public static final int STATE_ROOT = 1;
+	public static final int STATE_NAME = 2;
+	public static final int STATE_BASICFLAGS = 3;
+	public static final int STATE_GAMEMOD = 4;
+	public static final int STATE_BASICFLAG_INTEGER = 5;
+	public static final int STATE_GAMEMOD_TRUE = 6;
+	public static final int STATE_GAMEMOD_FALSE = 7;
+
+	public static ArrayList<Scheme> getSchemes(Context c) throws IllegalArgumentException{
+		String dir = c.getFilesDir().getAbsolutePath() + '/' + DIRECTORY_SCHEME + '/';
+		String[] files = new File(dir).list(fnf);
+		if(files == null) files = new String[]{};
+		Arrays.sort(files);
+		ArrayList<Scheme> schemes = new ArrayList<Scheme>();
+
+		try {
+			XmlPullParserFactory xmlPullFactory = XmlPullParserFactory.newInstance();
+			XmlPullParser xmlPuller = xmlPullFactory.newPullParser();
+
+			for(String file : files){
+				BufferedReader br = new BufferedReader(new FileReader(dir + file), 1024);
+				xmlPuller.setInput(br);
+				String name = null;
+				ArrayList<Integer> basic = new ArrayList<Integer>();
+				Integer gamemod = 0;
+				int mask = 0x000000004;
+
+				int eventType = xmlPuller.getEventType();
+				int state = STATE_START;
+				while(eventType != XmlPullParser.END_DOCUMENT){
+					switch(state){
+					case STATE_START:
+						if(eventType == XmlPullParser.START_TAG && xmlPuller.getName().equals("scheme")) state = STATE_ROOT;
+						else if(eventType != XmlPullParser.START_DOCUMENT) throwException(file, eventType);
+						break;
+					case STATE_ROOT:
+						if(eventType == XmlPullParser.START_TAG){
+							if(xmlPuller.getName().equals("basicflags")) state = STATE_BASICFLAGS;
+							else if(xmlPuller.getName().toLowerCase().equals("gamemod")) state = STATE_GAMEMOD;
+							else if(xmlPuller.getName().toLowerCase().equals("name")) state = STATE_NAME;
+							else throwException(file, eventType);
+						}else if(eventType == XmlPullParser.END_TAG) state = STATE_START;
+						else throwException(xmlPuller.getText(), eventType);
+						break;
+					case STATE_BASICFLAGS:
+						if(eventType == XmlPullParser.START_TAG && xmlPuller.getName().toLowerCase().equals("integer")) state = STATE_BASICFLAG_INTEGER;
+						else if(eventType == XmlPullParser.END_TAG)	state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					case STATE_GAMEMOD:
+						if(eventType == XmlPullParser.START_TAG){
+							if(xmlPuller.getName().toLowerCase().equals("true")) state = STATE_GAMEMOD_TRUE;
+							else if(xmlPuller.getName().toLowerCase().equals("false")) state = STATE_GAMEMOD_FALSE;
+							else throwException(file, eventType);
+						}else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					case STATE_NAME:
+						if(eventType == XmlPullParser.TEXT) name = xmlPuller.getText().trim();
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					case STATE_BASICFLAG_INTEGER:
+						if(eventType == XmlPullParser.TEXT) basic.add(Integer.parseInt(xmlPuller.getText().trim()));
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_BASICFLAGS;
+						else throwException(file, eventType);
+						break;
+					case STATE_GAMEMOD_FALSE:
+						if(eventType == XmlPullParser.TEXT) gamemod <<= 1;
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_GAMEMOD;
+						else throwException(file, eventType);
+						break;
+					case STATE_GAMEMOD_TRUE:
+						if(eventType == XmlPullParser.TEXT){
+							gamemod |= mask;
+							gamemod <<= 1;
+						}else if(eventType == XmlPullParser.END_TAG) state = STATE_GAMEMOD;
+						else throwException(file, eventType);
+						break;
+					}
+					eventType = getEventType(xmlPuller);
+				}//end while(eventtype != END_DOCUMENT
+				schemes.add(new Scheme(name, basic, gamemod));
+			}//end for(string file : files
+			return schemes;
+		} catch (XmlPullParserException e) {
+			e.printStackTrace();
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return new ArrayList<Scheme>();//TODO handle correctly
+	}
+	
+	private static FilenameFilter fnf = new FilenameFilter(){
+		public boolean accept(File dir, String filename) {
+			return filename.toLowerCase().startsWith("scheme_");
+		}
+	};
+
+	/**
+	 * This method will parse the basic flags from a prespecified xml file.
+	 * I use a raw xml file rather than one parsed by aatp at compile time
+	 * to keep it generic with other frontends, ie in the future we could 
+	 * use one provided by the Data folder.
+	 */
+	public static void parseBasicFlags(Context c){
+		String filename = String.format("%s/%s/basicflags", c.getFilesDir().getAbsolutePath(), DIRECTORY_SCHEME);
+
+		XmlPullParser xmlPuller = null;
+		BufferedReader br = null;
+		try {
+			XmlPullParserFactory xmlPullFactory = XmlPullParserFactory.newInstance();
+			xmlPuller = xmlPullFactory.newPullParser();
+			br = new BufferedReader(new FileReader(filename), 1024);
+			xmlPuller.setInput(br);
+
+			int eventType = getEventType(xmlPuller);
+			boolean continueParsing = true;
+			do{
+				switch(eventType){
+				
+				case XmlPullParser.START_TAG:
+					if(xmlPuller.getName().toLowerCase().equals("flag")){
+						basicflags.add(parseFlag(xmlPuller));
+					}else if(xmlPuller.getName().toLowerCase().equals("basicflags")){
+						eventType = getEventType(xmlPuller);
+					}else{
+						skipCurrentTag(xmlPuller);
+						eventType = getEventType(xmlPuller);
+					}
+					break;
+				case XmlPullParser.START_DOCUMENT://ignore all tags not being "flag"
+				case XmlPullParser.END_TAG:
+				case XmlPullParser.TEXT:
+				default:
+					continueParsing = true;
+				case XmlPullParser.END_DOCUMENT:
+					continueParsing = false;
+				}
+			}while(continueParsing);
+
+		}catch(IOException e){
+			e.printStackTrace();
+		}catch (XmlPullParserException e) {
+			e.printStackTrace();
+		}finally{
+			if(br != null)
+				try {
+					br.close();
+				} catch (IOException e) {}
+		}
+
+	}
+
+	/*
+	 * * Parses a Tag structure from xml as example we use
+	 *<flag>
+	 *   <checkOverMax>
+	 *       <boolean>false</boolean>
+	 *   </checkOverMax>
+	 *</flag>
+	 *
+	 * It returns a LinkedHashMap with key/value pairs
+	 */
+	private static LinkedHashMap<String, Object> parseFlag(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{
+		LinkedHashMap<String, Object> hash = new LinkedHashMap<String, Object>();
+
+		int eventType = xmlPuller.getEventType();//Get the event type which triggered this method
+		if(eventType == XmlPullParser.START_TAG && xmlPuller.getName().toLowerCase().equals("flag")){//valid start of flag tag
+			String lcKey = null;
+			String lcType = null;
+			String value = null;
+
+			eventType = getEventType(xmlPuller);//<checkOverMax>
+			while(eventType == XmlPullParser.START_TAG){
+				lcKey = xmlPuller.getName();//checkOverMax
+				if(getEventType(xmlPuller) == XmlPullParser.START_TAG){//<boolean>
+					lcType = xmlPuller.getName().toLowerCase();
+					if(getEventType(xmlPuller) == XmlPullParser.TEXT){
+						value = xmlPuller.getText();
+						if(getEventType(xmlPuller) == XmlPullParser.END_TAG && //</boolean> 
+								getEventType(xmlPuller) == XmlPullParser.END_TAG){//</checkOverMax>
+							if(lcType.equals("boolean")) hash.put(lcKey, new Boolean(value));
+							else if(lcType.equals("string"))hash.put(lcKey, value);							
+							else if(lcType.equals("integer")){
+								try{
+									hash.put(lcKey, new Integer(value));
+								}catch (NumberFormatException e){
+									throw new XmlPullParserException("Wrong integer value in xml file");
+								}
+							}else{
+								throwException("basicflags", eventType);
+							}
+						}//</boolean> / </checkOverMax>
+					}//if TEXT
+				}//if boolean
+				eventType = getEventType(xmlPuller);//start new loop
+			}
+			eventType = getEventType(xmlPuller);//</flag>
+		}
+
+		return hash;
+	}
+
+	private static void skipCurrentTag(XmlPullParser xmlPuller) throws XmlPullParserException, IOException{
+		int eventType = xmlPuller.getEventType();
+		if(eventType != XmlPullParser.START_TAG)return;
+		String tag = xmlPuller.getName().toLowerCase();
+
+		while(true){
+			eventType = getEventType(xmlPuller);//getNext()
+			switch(eventType){
+			case XmlPullParser.START_DOCUMENT://we're inside of a start tag so START_ or END_DOCUMENT is just wrong
+			case XmlPullParser.END_DOCUMENT:
+				throw new XmlPullParserException("invalid xml file");
+			case XmlPullParser.START_TAG://if we get a new tag recursively handle it
+				skipCurrentTag(xmlPuller);
+				break;
+			case XmlPullParser.TEXT:
+				break;
+			case XmlPullParser.END_TAG:
+				if(!xmlPuller.getName().toLowerCase().equals(tag)){//if the end tag doesn't match the start tag
+					throw new XmlPullParserException("invalid xml file");
+				}else{
+					return;//skip completed	
+				}
+
+			}
+		}
+	}
+
+	/**
+	 * Skips whitespaces..
+	 */
+	private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{
+		int eventType = xmlPuller.next();
+		while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){
+			eventType = xmlPuller.next();
+		}
+		return eventType;
+	}
+	private static void throwException(String file, int eventType){
+		throw new IllegalArgumentException(String.format("Xml file: %s malformed with error: %d.", file, eventType));
+	}
+
+	@Override
+	public int describeContents() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	public void writeToParcel(Parcel dest, int flags) {
+		dest.writeString(name);
+		dest.writeInt(gamemod);
+		dest.writeList(basic);
+		
+	}
+	
+	public void readFromParcel(Parcel src){
+		name = src.readString();
+		gamemod = src.readInt();
+		basic = src.readArrayList(ArrayList.class.getClassLoader());
+	}
+
+	public static final Parcelable.Creator<Scheme> CREATOR = new Parcelable.Creator<Scheme>() {
+		public Scheme createFromParcel(Parcel source) {
+			return new Scheme(source);
+		}
+		public Scheme[] newArray(int size) {
+			return new Scheme[size];
+		}
+		
+	};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Team.java	Thu Aug 04 17:27:05 2011 +0200
@@ -0,0 +1,271 @@
+package org.hedgewars.mobile.EngineProtocol;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Xml;
+
+public class Team implements Parcelable{
+
+	public static final String DIRECTORY_TEAMS = "teams";
+
+	public String name, grave, flag, voice, fort, hash;
+
+	public static int maxNumberOfHogs = 0;
+	public static int maxNumberOfTeams = 0;
+
+	static{
+		maxNumberOfHogs = PascalExports.HWgetMaxNumberOfHogs();
+		maxNumberOfTeams = PascalExports.HWgetMaxNumberOfTeams();
+	}
+	public String[] hats = new String[maxNumberOfHogs];
+	public String[] hogNames = new String[maxNumberOfHogs];
+	public int[] levels = new int[maxNumberOfHogs];
+	
+	public Team(){
+	}
+	
+	public Team(Parcel in){
+		readFromParcel(in);
+	}
+
+	public boolean equals(Object o){
+		if(super.equals(o)) return true;
+		else if(o instanceof Team){
+			Team t = (Team)o;
+			boolean ret = name.equals(t.name);
+			ret &= grave.equals(t.grave);
+			ret &= flag.equals(t.flag);
+			ret &= voice.equals(t.voice);
+			ret &= fort.equals(t.fort);
+			ret &= hash.equals(t.hash);
+			return ret;
+		}else{
+			return false;
+		}
+	}
+	
+	
+	public void sendToEngine(OutputStream os, int hogCount, int health, int color) throws IOException{
+		os.write(String.format("eaddteam %s %d %s", hash, color, name).getBytes());
+		os.write(String.format("egrave %s", grave).getBytes());
+		os.write(String.format("efort %s", fort).getBytes());
+		os.write(String.format("evoicepack %s", voice).getBytes());
+		os.write(String.format("eflag %s", flag).getBytes());
+		
+		for(int i = 0; i < hogCount; i++){
+			os.write(String.format("eaddhh %d %d %s", levels[i], health, hogNames[i]).getBytes());
+			os.write(String.format("ehat %s", hats[i]).getBytes());
+		}
+		os.flush();
+	}
+	
+	public static final int STATE_START = 0;
+	public static final int STATE_ROOT = 1;
+	public static final int STATE_HOG_ROOT = 2;
+	public static final int STATE_HOG_HAT = 3;
+	public static final int STATE_HOG_NAME = 4;
+	public static final int STATE_HOG_LEVEL = 5;
+
+	/**
+	 * Read the xml file path and convert it to a Team object
+	 * @param path absolute path to the xml file
+	 * @return
+	 */
+	public static Team getTeamFromXml(String path){
+		try {
+			XmlPullParserFactory xmlPullFactory = XmlPullParserFactory.newInstance();
+			XmlPullParser xmlPuller = xmlPullFactory.newPullParser();
+
+			BufferedReader br = new BufferedReader(new FileReader(path), 1024);
+			xmlPuller.setInput(br);
+			Team team = new Team();
+			int hogCounter = 0;
+
+			int eventType = xmlPuller.getEventType();
+			int state = STATE_START;
+			while(eventType != XmlPullParser.END_DOCUMENT){
+				switch(state){
+				case STATE_START:
+					if(eventType == XmlPullParser.START_TAG && xmlPuller.getName().equals("team")) state = STATE_ROOT;
+					else if(eventType != XmlPullParser.START_DOCUMENT) throwException(path, eventType);
+					break;
+				case STATE_ROOT:
+					if(eventType == XmlPullParser.START_TAG){
+						if(xmlPuller.getName().toLowerCase().equals("name")){
+							team.name = getXmlText(xmlPuller, "name");
+						}else if(xmlPuller.getName().toLowerCase().equals("flag")){
+							team.flag= getXmlText(xmlPuller, "flag");
+						}else if(xmlPuller.getName().toLowerCase().equals("voice")){
+							team.voice = getXmlText(xmlPuller, "voice");
+						}else if(xmlPuller.getName().toLowerCase().equals("grave")){
+							team.grave = getXmlText(xmlPuller, "grave");
+						}else if(xmlPuller.getName().toLowerCase().equals("fort")){
+							team.fort = getXmlText(xmlPuller, "fort");
+						}else if(xmlPuller.getName().toLowerCase().equals("hash")){
+							team.hash = getXmlText(xmlPuller, "hash");
+						}else if(xmlPuller.getName().toLowerCase().equals("hog")){
+							state = STATE_HOG_ROOT;
+						}else throwException(xmlPuller.getName(), eventType);
+					}else if(eventType == XmlPullParser.END_TAG) state = STATE_START;
+					else throwException(xmlPuller.getText(), eventType);
+					break;
+				case STATE_HOG_ROOT:
+					if(eventType == XmlPullParser.START_TAG){
+						if(xmlPuller.getName().toLowerCase().equals("name")){
+							team.hogNames[hogCounter] = getXmlText(xmlPuller, "name");
+						}else if(xmlPuller.getName().toLowerCase().equals("hat")){
+							team.hats[hogCounter] = getXmlText(xmlPuller, "hat");
+						}else if(xmlPuller.getName().toLowerCase().equals("level")){
+							team.levels[hogCounter] = Integer.parseInt(getXmlText(xmlPuller, "level"));
+						}else throwException(xmlPuller.getText(), eventType);
+					}else if(eventType == XmlPullParser.END_TAG){
+						hogCounter++;
+						state = STATE_ROOT;
+					}else throwException(xmlPuller.getText(), eventType);
+					break;
+				}
+				eventType = getEventType(xmlPuller);
+			}//end while(eventtype != END_DOCUMENT
+			return team;
+		} catch (NumberFormatException e){
+			e.printStackTrace();
+		} catch (XmlPullParserException e) {
+			e.printStackTrace();
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	private static String getXmlText(XmlPullParser xmlPuller, String parentTag)throws XmlPullParserException, IOException{
+		if(getEventType(xmlPuller) == XmlPullParser.TEXT){
+			String txt = xmlPuller.getText();
+			if(getEventType(xmlPuller) == XmlPullParser.END_TAG && xmlPuller.getName().toLowerCase().equals(parentTag)){
+				return txt;
+			}
+		}
+		throw new XmlPullParserException("malformed xml file on string read from tag: " + parentTag);
+	}
+
+	/**
+	 * Skips whitespaces..
+	 */
+	private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{
+		int eventType = xmlPuller.next();
+		while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){
+			eventType = xmlPuller.next();
+		}
+		return eventType;
+	}
+
+	private static void throwException(String file, int eventType){
+		throw new IllegalArgumentException(String.format("Xml file: %s malformed with error: %d.", file, eventType));
+	}
+
+	public void writeToXml(OutputStream os){
+		XmlSerializer serializer = Xml.newSerializer();
+		try{
+			serializer.setOutput(os, "UTF-8");	
+			serializer.startDocument("UTF-8", true);
+			serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+			
+			serializer.startTag(null, "team");
+				serializer.startTag(null, "name");
+				serializer.text(name);
+				serializer.endTag(null, "name");
+				serializer.startTag(null, "flag");
+				serializer.text(flag);
+				serializer.endTag(null, "flag");
+				serializer.startTag(null, "fort");
+				serializer.text(fort);
+				serializer.endTag(null, "fort");
+				serializer.startTag(null, "grave");
+				serializer.text(grave);
+				serializer.endTag(null, "grave");
+				serializer.startTag(null, "voice");
+				serializer.text(voice);
+				serializer.endTag(null, "voice");
+				serializer.startTag(null, "hash");
+				serializer.text(hash);
+				serializer.endTag(null, "hash");
+				
+				for(int i = 0; i < maxNumberOfHogs; i++){
+					serializer.startTag(null, "hog");
+					serializer.startTag(null, "name");
+					serializer.text(hogNames[i]);
+					serializer.endTag(null, "name");
+					serializer.startTag(null, "hat");
+					serializer.text(hats[i]);
+					serializer.endTag(null, "hat");
+					serializer.startTag(null, "level");
+					serializer.text(String.valueOf(levels[i]));
+					serializer.endTag(null, "level");
+					
+					serializer.endTag(null, "hog");
+				}
+			serializer.endTag(null, "team");
+			serializer.endDocument();
+			serializer.flush();
+			
+		} catch (IOException e) {
+			e.printStackTrace();
+		}finally{
+			try {
+				os.close();
+			} catch (IOException e) {}
+		}
+	}
+
+	public int describeContents() {
+		return 0;
+	}
+
+	public void writeToParcel(Parcel dest, int flags) {
+		dest.writeString(name);
+		dest.writeString(grave);
+		dest.writeString(flag);
+		dest.writeString(voice);
+		dest.writeString(fort);
+		dest.writeString(hash);
+		dest.writeStringArray(hats);
+		dest.writeStringArray(hogNames);
+		dest.writeIntArray(levels);
+	}
+		
+	
+	public void readFromParcel(Parcel src){
+		name = src.readString();
+		grave = src.readString();
+		flag = src.readString();
+		voice = src.readString();
+		fort = src.readString();
+		hash = src.readString();
+		src.readStringArray(hats);
+		src.readStringArray(hogNames);
+		src.readIntArray(levels);
+	}
+
+	public static final Parcelable.Creator<Team> CREATOR = new Parcelable.Creator<Team>() {
+		public Team createFromParcel(Parcel source) {
+			return new Team(source);
+		}
+		public Team[] newArray(int size) {
+			return new Team[size];
+		}
+		
+	};
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/EngineProtocol/Weapon.java	Thu Aug 04 17:27:05 2011 +0200
@@ -0,0 +1,197 @@
+package org.hedgewars.mobile.EngineProtocol;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import android.content.Context;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class Weapon implements Parcelable{
+
+	public static final String DIRECTORY_WEAPON = "weapons";
+	
+	private String name;
+	private String QT;
+	private String prob;
+	private String delay;
+	private String crate;
+	private static int maxWeapons;
+	
+	static{
+		//maxWeapons = PascalExports.HWgetNumberOfWeapons();
+	}
+	
+	public Weapon(String _name, String _QT, String _prob, String _delay, String _crate){
+		name = _name;
+		
+		//Incase there's a newer ammoStore which is bigger we append with zeros
+		StringBuffer sb = new StringBuffer();
+		while(_QT.length() + sb.length() < maxWeapons){
+			sb.append('0');
+		}
+		
+		QT = String.format("e%s %s%s", "ammloadt", _QT, sb);
+		prob = String.format("e%s %s%s", "ammprob", _prob, sb);
+		delay = String.format("e%s %s%s", "ammdelay", _delay, sb);
+		crate = String.format("e%s %s%s", "ammreinf", _crate, sb);
+	}
+	
+	public Weapon(Parcel in){
+		readFromParcel(in);
+	}
+	
+	public String toString(){
+		return name;
+	}
+	
+	public void sendToEngine(OutputStream os, int teamsCount) throws IOException{
+		os.write(QT.getBytes());//command prefix is already in string 
+		os.write(prob.getBytes());
+		os.write(delay.getBytes());
+		os.write(crate.getBytes());
+		
+		byte[] ammstore = "eammstore".getBytes();
+		for(int i = 0; i < teamsCount; i++){
+			os.write(ammstore);
+		}
+		os.flush();
+	}
+	
+	public static final int STATE_START = 0;
+	public static final int STATE_ROOT = 1;
+	public static final int STATE_NAME = 2;
+	public static final int STATE_QT = 3;
+	public static final int STATE_PROBABILITY = 4;
+	public static final int STATE_DELAY = 5;
+	public static final int STATE_CRATE = 6;
+	
+	public static ArrayList<Weapon> getWeapons(Context c) throws IllegalArgumentException{
+		String dir = c.getFilesDir().getAbsolutePath() + '/' + DIRECTORY_WEAPON + '/';
+		String[] files = new File(dir).list();
+		if(files == null) files = new String[]{};
+		Arrays.sort(files);
+		
+		ArrayList<Weapon> weapons = new ArrayList<Weapon>();
+
+		try {
+			XmlPullParserFactory xmlPullFactory = XmlPullParserFactory.newInstance();
+			XmlPullParser xmlPuller = xmlPullFactory.newPullParser();
+			
+			for(String file : files){
+				BufferedReader br = new BufferedReader(new FileReader(dir + file), 1024);
+				xmlPuller.setInput(br);
+				String name = null;
+				String qt = null;
+				String prob = null;
+				String delay = null;
+				String crate = null;
+				
+				int eventType = xmlPuller.getEventType();
+				int state = STATE_START;
+				while(eventType != XmlPullParser.END_DOCUMENT){
+					switch(state){
+					case STATE_START:
+						if(eventType == XmlPullParser.START_TAG && xmlPuller.getName().equals("weapon")) state = STATE_ROOT;
+						else if(eventType != XmlPullParser.START_DOCUMENT) throwException(file, eventType);
+						break;
+					case STATE_ROOT:
+						if(eventType == XmlPullParser.START_TAG){
+							if(xmlPuller.getName().toLowerCase().equals("qt")) state = STATE_QT;
+							else if(xmlPuller.getName().toLowerCase().equals("name")) state = STATE_NAME;
+							else if(xmlPuller.getName().toLowerCase().equals("probability")) state = STATE_PROBABILITY;
+							else if(xmlPuller.getName().toLowerCase().equals("delay")) state = STATE_DELAY;
+							else if(xmlPuller.getName().toLowerCase().equals("crate")) state = STATE_CRATE;
+							else throwException(file, eventType);
+						}else if(eventType == XmlPullParser.END_TAG) state = STATE_START;
+						else throwException(xmlPuller.getText(), eventType);
+						break;
+					case STATE_NAME:
+						if(eventType == XmlPullParser.TEXT) name = xmlPuller.getText().trim();
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					case STATE_QT:
+						if(eventType == XmlPullParser.TEXT) qt = xmlPuller.getText().trim();
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					case STATE_PROBABILITY:
+						if(eventType == XmlPullParser.TEXT) prob = xmlPuller.getText().trim();
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					case STATE_DELAY:
+						if(eventType == XmlPullParser.TEXT) delay = xmlPuller.getText().trim();
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					case STATE_CRATE:
+						if(eventType == XmlPullParser.TEXT) crate = xmlPuller.getText().trim();
+						else if(eventType == XmlPullParser.END_TAG) state = STATE_ROOT;
+						else throwException(file, eventType);
+						break;
+					}
+					eventType = xmlPuller.next();
+					while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){//Skip whitespaces
+						eventType = xmlPuller.next();
+					}
+				}//end while(eventtype != END_DOCUMENT
+				weapons.add(new Weapon(name, qt, prob, delay, crate));
+			}//end for(string file : files
+			return weapons;
+			
+		} catch (XmlPullParserException e) {
+			e.printStackTrace();
+		} catch (FileNotFoundException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		return new ArrayList<Weapon>();//TODO handle correctly
+	}
+	
+	private static void throwException(String file, int eventType){
+		throw new IllegalArgumentException(String.format("Xml file: %s malformed with eventType: %d.", file, eventType));
+	}
+
+	public int describeContents() {
+		return 0;
+	}
+
+	public void writeToParcel(Parcel dest, int flags) {
+		dest.writeString(name);
+		dest.writeString(QT);
+		dest.writeString(prob);
+		dest.writeString(delay);
+		dest.writeString(crate);
+	}
+	
+	private void readFromParcel(Parcel src){
+		name = src.readString();
+		QT = src.readString();
+		prob = src.readString();
+		delay = src.readString();
+		crate = src.readString();
+	}
+	
+	public static final Parcelable.Creator<Weapon> CREATOR = new Parcelable.Creator<Weapon>() {
+		public Weapon createFromParcel(Parcel source) {
+			return new Weapon(source);
+		}
+		public Weapon[] newArray(int size) {
+			return new Weapon[size];
+		}
+		
+	};
+}