diff -r 9a7cc0f29430 -r 10011f051f9c project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/Scheme.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/Scheme.java Thu Oct 20 22:54:34 2011 +0200 @@ -0,0 +1,358 @@ +/* + * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game + * Copyright (c) 2011 Richard Deurwaarder + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +package org.hedgewars.hedgeroid.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.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 basic; + private Integer gamemod; + private ArrayList basic;; + private static ArrayList> basicflags = new ArrayList>(); + + public Scheme(String _name, ArrayList _basic, int _gamemod){ + name = _name; + gamemod = _gamemod; + basic = _basic; + + } + + public Scheme(Parcel in){ + readFromParcel(in); + } + + public void sendToEngine(EngineProtocolNetwork epn)throws IOException{ + epn.sendToEngine(String.format("e$gmflags %d", gamemod)); + + for(int pos = 0; pos < basic.size(); pos++){ + LinkedHashMap 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; + + epn.sendToEngine(String.format("%s %d", command, value)); + } + } + 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 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 schemes = new ArrayList(); + + 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 basic = new ArrayList(); + 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();//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 + * + * + * false + * + * + * + * It returns a LinkedHashMap with key/value pairs + */ + private static LinkedHashMap parseFlag(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{ + LinkedHashMap hash = new LinkedHashMap(); + + 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);// + while(eventType == XmlPullParser.START_TAG){ + lcKey = xmlPuller.getName();//checkOverMax + if(getEventType(xmlPuller) == XmlPullParser.START_TAG){// + lcType = xmlPuller.getName().toLowerCase(); + if(getEventType(xmlPuller) == XmlPullParser.TEXT){ + value = xmlPuller.getText(); + if(getEventType(xmlPuller) == XmlPullParser.END_TAG && // + getEventType(xmlPuller) == XmlPullParser.END_TAG){// + 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); + } + }// / + }//if TEXT + }//if boolean + eventType = getEventType(xmlPuller);//start new loop + } + eventType = getEventType(xmlPuller);// + } + + 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)); + } + + 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 CREATOR = new Parcelable.Creator() { + public Scheme createFromParcel(Parcel source) { + return new Scheme(source); + } + public Scheme[] newArray(int size) { + return new Scheme[size]; + } + + }; +}