Hedgeroid:
- (hopefully) completed the frontlib JNA mappings
- added documentation
- Changed more code to use frontlib for ini reading/writing
- tried to make everything work again that was working before
- Teamlist can now be used to add and remove teams
- Netplay now correctly handles team additions when being room chief
- Fixed TeamCreatorActivity so that editing teams works
--- a/project_files/Android-build/SDL-android-project/assets/assetsversion.txt Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/assets/assetsversion.txt Sun Aug 12 22:46:23 2012 +0200
@@ -1,1 +1,1 @@
-4
\ No newline at end of file
+5
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/res/layout/team_creation.xml Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/team_creation.xml Sun Aug 12 22:46:23 2012 +0200
@@ -15,8 +15,6 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
- <include layout="@layout/backbutton"/>
- <include layout="@layout/savebutton"/>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
--- a/project_files/Android-build/SDL-android-project/res/layout/team_selector.xml Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/team_selector.xml Sun Aug 12 22:46:23 2012 +0200
@@ -5,8 +5,6 @@
android:layout_height="fill_parent">
<include layout="@layout/background"/>
-
- <include layout="@layout/backbutton"/>
<ImageButton
android:id="@+id/btnAdd"
--- a/project_files/Android-build/SDL-android-project/res/raw/weapon_clean Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<weapon>
- <name>Clean</name>
- <QT>
- 101000900001000001100000000000000000000000000000100000
- </QT>
- <probability>
- 040504054160065554655446477657666666615551010111541111
- </probability>
- <delay>
- 000000000000000000000000000000000000000000000000000000
- </delay>
- <crate>
- 131111031211111112311411111111111111121111110111111111
- </crate>
-</weapon>
-
--- a/project_files/Android-build/SDL-android-project/res/raw/weapon_crazy Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<weapon>
- <name>Crazy</name>
- <QT>
- 999999999999999999299999999999999929999999990999999229
- </QT>
- <probability>
- 111111011111111111111111111111111111111111110111111111
- </probability>
- <delay>
- 000000000000000000000000000000000000000000000000000000
- </delay>
- <crate>
- 131111031211111112311411111111111111121111010111111111
- </crate>
-</weapon>
-
--- a/project_files/Android-build/SDL-android-project/res/raw/weapon_default Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<weapon>
- <name>Default</name>
- <QT>
- 939192942219912103223511100120100000021111010101111991
- </QT>
- <probability>
- 040504054160065554655446477657666666615551010111541111
- </probability>
- <delay>
- 000000000000020550000004000700400000000022000000060000
- </delay>
- <crate>
- 131111031211111112311411111111111111121111110111111111
- </crate>
-</weapon>
-
--- a/project_files/Android-build/SDL-android-project/res/raw/weapon_mines Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<weapon>
- <name>Mines</name>
- <QT>
- 000000990009000000030000000000000000000000000000000000
- </QT>
- <probability>
- 000000000000000000000000000000000000000000000000000000
- </probability>
- <delay>
- 000000000000020550000004000700400000000020000000060000
- </delay>
- <crate>
- 111111111111111111111111111111111111111111110111111111
- </crate>
-</weapon>
-
--- a/project_files/Android-build/SDL-android-project/res/raw/weapon_portals Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<weapon>
- <name>Portals</name>
- <QT>
- 900000900200000000210000000000000011000009000000000000
- </QT>
- <probability>
- 040504054160065554655446477657666666615551010111541111
- </probability>
- <delay>
- 000000000000020550000004000700400000000020000000060000
- </delay>
- <crate>
- 131111031211111112311411111111111111121111110111111111
- </crate>
-</weapon>
-
--- a/project_files/Android-build/SDL-android-project/res/raw/weapon_promode Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<weapon>
- <name>Pro Mode</name>
- <QT>
- 909000900000000000000900000000000000000000000000000000
- </QT>
- <probability>
- 000000000000000000000000000000000000000000000000000000
- </probability>
- <delay>
- 000000000000020550000004000700400000000020000000000000
- </delay>
- <crate>
- 111111111111111111111111111111111111111110010111111111
- </crate>
-</weapon>
-
--- a/project_files/Android-build/SDL-android-project/res/raw/weapon_shoppa Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<weapon>
- <name>Shoppa</name>
- <QT>
- 000000990000000000000000000000000000000000000000000000
- </QT>
- <probability>
- 444441004424440221011212122242200000000200040001001111
- </probability>
- <delay>
- 000000000000000000000000000000000000000000000000000000
- </delay>
- <crate>
- 111111111111111111111111111111111111111110110111111111
- </crate>
-</weapon>
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/raw/weapons_builtin.ini Sun Aug 12 22:46:23 2012 +0200
@@ -0,0 +1,8 @@
+[General]
+%44efault=9391929422199121032235111001201000000211110101011111011040504054160065554655446477657666666615551010111541101100000000000002055000000400070040000000002200000006000001311110312111111123114111111111111111211111101111111010
+%43razy=9999999999999999992999999999999999299999999909999992099111111011111111111111111111111111111111111110111111101100000000000000000000000000000000000000000000000000000001311110312111111123114111111111111111211110101111111011
+%50ro%20%4dode=9090009000000000000009000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002055000000400070040000000002000000000000001111111111111111111111111111111111111111100101111111011
+%53hoppa=0000009900000000000000000000000000000000000000000000000444441004424440221011212122242200000000200040001001100000000000000000000000000000000000000000000000000000000001111111111111111111111111111111111111111101101111111001
+%43lean%20%53late=1010009000010000011000000000000000000000000000001000000040504054160065554655446477657666666615551010111541101100000000000000000000000000000000000000000000000000000001311110312111111123114111111111111111211111101111111011
+%4dinefield=0000009900090000000300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002055000000400070040000000002000000006000001111111111111111111111111111111111111111111101111111011
+%54hinking%20with%20%50ortals=9000009002000000002100000000000000110000090000000000000040504054160065554655446477657666666615551010111541101100000000000002055000000400070040000000002000000006000001311110312111111123114111111111111111211111101111111011
--- a/project_files/Android-build/SDL-android-project/res/values/frontend_data_pointers.xml Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/values/frontend_data_pointers.xml Sun Aug 12 22:46:23 2012 +0200
@@ -1,16 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
-
-<array name="weapons">
- <item>@raw/weapon_default</item>
- <item>@raw/weapon_clean</item>
- <item>@raw/weapon_crazy</item>
- <item>@raw/weapon_mines</item>
- <item>@raw/weapon_portals</item>
- <item>@raw/weapon_promode</item>
- <item>@raw/weapon_shoppa</item>
-</array>
-
<array name="teams">
<item>@raw/team_one</item>
<item>@raw/team_two</item>
--- a/project_files/Android-build/SDL-android-project/res/values/strings.xml Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/values/strings.xml Sun Aug 12 22:46:23 2012 +0200
@@ -123,7 +123,8 @@
<string name="error_auth_failed">Unable to authenticate for your username.</string>
<string name="error_connection_lost">The connection to the server was lost.</string>
<string name="error_save_failed">Saving has failed.</string>
-
+ <string name="error_missing_sdcard_or_files">Error: Either the sdcard is not available, or files are missing from the Data directory.</string>
+ <string name="error_team_attribute_not_found">Error: This team uses assets which we do not have. Try downloading the big data package from the main menu.</string>
<!-- Dialogs -->
<string name="dialog_connecting_title">Please wait</string>
@@ -134,6 +135,7 @@
<string name="dialog_password_remember">remember password</string>
<string name="dialog_create_room_hint">Room name</string>
<string name="dialog_create_room_title">Create new room</string>
+ <string name="dialog_addteam_title">Add team</string>
<string name="toast_disconnected">Disconnected: %1$s</string>
<string name="toast_room_abandoned">The room was closed because the owner left.</string>
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/FrontendDataUtils.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/FrontendDataUtils.java Sun Aug 12 22:46:23 2012 +0200
@@ -20,15 +20,14 @@
package org.hedgewars.hedgeroid.Datastructures;
import java.io.File;
+import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.hedgewars.hedgeroid.R;
-import org.hedgewars.hedgeroid.StartGameActivity;
import org.hedgewars.hedgeroid.Utils;
-import org.hedgewars.hedgeroid.Datastructures.Map.MapType;
import android.content.Context;
import android.graphics.Bitmap;
@@ -36,59 +35,75 @@
public class FrontendDataUtils {
-
- public static ArrayList<Map> getMaps(Context c){
+ /**
+ * @throws FileNotFoundException if the sdcard isn't available or the Maps directory doesn't exist
+ */
+ public static ArrayList<MapFile> getMaps(Context c) throws FileNotFoundException {
File[] files = Utils.getFilesFromRelativeDir(c,"Maps");
- ArrayList<Map> ret = new ArrayList<Map>();
+ ArrayList<MapFile> ret = new ArrayList<MapFile>();
- for(File f : files){
- if(Utils.hasFileWithSuffix(f, ".lua")){
- ret.add(new Map(f,MapType.TYPE_MISSION, c));
- }else{
- ret.add(new Map(f, MapType.TYPE_DEFAULT,c));
- }
+ for(File f : files) {
+ boolean isMission = Utils.hasFileWithSuffix(f, ".lua");
+ ret.add(new MapFile(f.getName(), isMission));
}
- Collections.sort(ret);
+ Collections.sort(ret, MapFile.MISSIONS_FIRST_NAME_ORDER);
return ret;
}
- public static List<String> getGameplay(Context c){
- String[] files = Utils.getFileNamesFromRelativeDir(c, "Scripts/Multiplayer");
+ /**
+ * Returns a list of all multiplayer scripts (game styles)
+ * @throws FileNotFoundException if the sdcard isn't available or the Scripts/Multiplayer directory doesn't exist
+ */
+ public static List<String> getGameStyles(Context c) throws FileNotFoundException {
+ File[] files = Utils.getFilesFromRelativeDir(c, "Scripts/Multiplayer");
ArrayList<String> ret = new ArrayList<String>();
-
- for(int i = 0; i < files.length; i++){
- if(files[i].endsWith(".lua")){
- ret.add(files[i].replace('_', ' ').substring(0, files[i].length()-4)); //replace _ by a space and removed the last four characters (.lua)
+ /*
+ * Caution: It is important that the "empty" style has this exact name, because
+ * it will be interpreted as "don't load a script" by the frontlib, and also by
+ * the QtFrontend in a netgame. This should probably be improved some time
+ * (maybe TODO add a dummy script called "Normal" to the MP scripts?)
+ */
+ ret.add("Normal");
+ for(int i = 0; i < files.length; i++) {
+ String name = files[i].getName();
+ if(name.endsWith(".lua")){
+ //replace _ by a space and removed the last four characters (.lua)
+ ret.add(name.replace('_', ' ').substring(0, name.length()-4));
}
}
- ret.add(0,"None");
- Collections.sort(ret);
- return ret;
+ Collections.sort(ret, String.CASE_INSENSITIVE_ORDER);
+ return ret;
}
- public static List<String> getThemes(Context c){
+ /**
+ * @throws FileNotFoundException if the sdcard isn't available or the Themes directory doesn't exist
+ */
+ public static List<String> getThemes(Context c) throws FileNotFoundException {
List<String> list = Utils.getDirsWithFileSuffix(c, "Themes", "icon.png");
- Collections.sort(list);
+ Collections.sort(list, String.CASE_INSENSITIVE_ORDER);
return list;
}
- public static List<Weapon> getWeapons(Context c){
+ public static List<Weaponset> getWeaponsets(Context c) {
// TODO stub, re-implement
/*List<Weapon> list = Weapon.getWeapons(c);
Collections.sort(list);*/
return Collections.emptyList();
}
- public static ArrayList<HashMap<String, ?>> getGraves(Context c){
- String pathPrefix = Utils.getDataPath(c) + "Graphics/Graves/";
- ArrayList<String> names = Utils.getFilesFromDirWithSuffix(c,"Graphics/Graves", ".png", true);
+ /**
+ * @throws FileNotFoundException if the sdcard isn't available or the Graphics/Graves directory doesn't exist
+ */
+ public static ArrayList<HashMap<String, ?>> getGraves(Context c) throws FileNotFoundException {
+ File gravePath = new File(new File(Utils.getDataPathFile(c), "Graphics"), "Graves");
+ ArrayList<String> names = Utils.getFileNamesFromDirWithSuffix(c,"Graphics/Graves", ".png", true);
ArrayList<HashMap<String, ?>> data = new ArrayList<HashMap<String, ?>>(names.size());
for(String s : names){
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("txt", s);
- Bitmap b = BitmapFactory.decodeFile(pathPrefix + s + ".png");//create a full path - decode to to a bitmap
+ Bitmap b = BitmapFactory.decodeFile(new File(gravePath, s + ".png").getAbsolutePath());
int width = b.getWidth();
if(b.getHeight() > width){//some pictures contain more 'frames' underneath each other, if so we only use the first frame
Bitmap tmp = Bitmap.createBitmap(width, width, b.getConfig());
@@ -104,22 +119,28 @@
return data;
}
- public static ArrayList<HashMap<String, ?>> getFlags(Context c){
- String pathPrefix = Utils.getDataPath(c) + "Graphics/Flags/";
- ArrayList<String> names = Utils.getFilesFromDirWithSuffix(c, "Graphics/Flags", ".png", true);
+ /**
+ * @throws FileNotFoundException if the sdcard isn't available or the Graphics/Graves directory doesn't exist
+ */
+ public static ArrayList<HashMap<String, ?>> getFlags(Context c) throws FileNotFoundException {
+ File flagsPath = new File(new File(Utils.getDataPathFile(c), "Graphics"), "Flags");
+ ArrayList<String> names = Utils.getFileNamesFromDirWithSuffix(c, "Graphics/Flags", ".png", true);
ArrayList<HashMap<String, ?>> data = new ArrayList<HashMap<String, ?>>(names.size());
for(String s : names){
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("txt", s);
- Bitmap b = BitmapFactory.decodeFile(pathPrefix + s + ".png");//create a full path - decode to to a bitmap
+ Bitmap b = BitmapFactory.decodeFile(new File(flagsPath, s + ".png").getAbsolutePath());
map.put("img", b);
data.add(map);
}
return data;
}
- public static ArrayList<String> getVoices(Context c){
+ /**
+ * @throws FileNotFoundException if the sdcard isn't available or the Sounds/voices directory doesn't exist
+ */
+ public static ArrayList<String> getVoices(Context c) throws FileNotFoundException {
File[] files = Utils.getFilesFromRelativeDir(c, "Sounds/voices");
ArrayList<String> ret = new ArrayList<String>();
@@ -129,9 +150,14 @@
return ret;
}
- public static ArrayList<String> getForts(Context c){
- return Utils.getFilesFromDirWithSuffix(c,"Forts", "L.png", true);
+ /**
+ * @throws FileNotFoundException if the sdcard isn't available or the Forts directory doesn't exist
+ */
+ public static ArrayList<String> getForts(Context c) throws FileNotFoundException {
+ return Utils.getFileNamesFromDirWithSuffix(c,"Forts", "L.png", true);
}
+
+ // TODO wat
public static ArrayList<HashMap<String, ?>> getTypes(Context c){
ArrayList<HashMap<String, ?>> data = new ArrayList<HashMap<String, ?>>(6);
String[] levels = {c.getString(R.string.human), c.getString(R.string.bot5), c.getString(R.string.bot4), c.getString(R.string.bot3), c.getString(R.string.bot2), c.getString(R.string.bot1)};
@@ -147,9 +173,12 @@
return data;
}
- public static ArrayList<HashMap<String, ?>> getHats(Context c){
- ArrayList<String> files = Utils.getFilesFromDirWithSuffix(c,"Graphics/Hats", ".png", true);
- String pathPrefix = Utils.getDataPath(c) + "Graphics/Hats/";
+ /**
+ * @throws FileNotFoundException if the sdcard isn't available or the Graphics/Hats directory doesn't exist
+ */
+ public static ArrayList<HashMap<String, ?>> getHats(Context c) throws FileNotFoundException {
+ ArrayList<String> files = Utils.getFileNamesFromDirWithSuffix(c,"Graphics/Hats", ".png", true);
+ File hatsPath = new File(new File(Utils.getDataPathFile(c), "Graphics"), "Hats");
int size = files.size();
ArrayList<HashMap<String, ?>> data = new ArrayList<HashMap<String, ?>>(size);
@@ -157,7 +186,7 @@
for(String s : files){
hashmap = new HashMap<String, Object>();
hashmap.put("txt", s);
- Bitmap b = BitmapFactory.decodeFile(pathPrefix + s + ".png");//create a full path - decode to to a bitmap
+ Bitmap b = BitmapFactory.decodeFile(new File(hatsPath, s + ".png").getAbsolutePath());
b = Bitmap.createBitmap(b, 0,0,b.getWidth()/2, b.getWidth()/2);
hashmap.put("img", b);
data.add(hashmap);
@@ -166,8 +195,8 @@
return data;
}
- public static List<TeamFile> getTeamFiles(Context c) {
- List<TeamFile> ret = new ArrayList<TeamFile>();
+ public static List<Team> getTeams(Context c) {
+ List<Team> ret = new ArrayList<Team>();
File teamsDir = new File(c.getFilesDir(), Team.DIRECTORY_TEAMS);
File[] teamFileNames = teamsDir.listFiles();
@@ -175,15 +204,10 @@
for(File file : teamFileNames){
Team team = Team.load(file);
if(team != null){
- ret.add(new TeamFile(team, file));
+ ret.add(team);
}
}
}
return ret;
}
-
- public static Scheme[] getSchemes(StartGameActivity startGameActivity) {
- // TODO Auto-generated method stub
- return null;
- }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/GameConfig.java Sun Aug 12 22:46:23 2012 +0200
@@ -0,0 +1,54 @@
+/*
+ * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
+ * Copyright (c) 2011-2012 Richard Deurwaarder <xeli@xelification.com>
+ *
+ * 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.Datastructures;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * Game configuration from the point of view of the UI. This differs slightly from the
+ * frontlib view, because the engine allows setting a separate initial health and weapon set
+ * for each hog, while the Android UI currently only supports both attributes on a per-game
+ * basis (initial health is contained in the scheme).
+ *
+ * This difference means that creating a GameConfig object from a frontlib object can, in
+ * theory, lose information. This does not cause problems at the moment because for now
+ * weaponset and initial health are always per-game, but that might change in the future.
+ */
+public final class GameConfig {
+ public static final String DEFAULT_STYLE = "Normal";
+ public static final String DEFAULT_SCHEME = "Default";
+ public static final String DEFAULT_WEAPONSET = "Default";
+
+ public final String style;
+ public final Scheme scheme;
+ public final MapRecipe map;
+ public final List<TeamInGame> teams;
+ public final Weaponset weaponset;
+
+ public GameConfig(String style, Scheme scheme, MapRecipe map, List<TeamInGame> teams, Weaponset weaponset) {
+ this.style = style;
+ this.scheme = scheme;
+ this.map = map;
+ this.teams = Collections.unmodifiableList(new ArrayList<TeamInGame>(teams));
+ this.weaponset = weaponset;
+ }
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Map.java Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
- * Copyright (c) 2011-2012 Richard Deurwaarder <xeli@xelification.com>
- *
- * 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.Datastructures;
-
-import java.io.File;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-public class Map implements Comparable<Map> {
-
- 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 String toString(){
- switch(type){
- default:
- case TYPE_DEFAULT:
- return name;
- case TYPE_GENERATED:
- return "bla";
- case TYPE_MISSION:
- return MISSION_PREFIX + 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;
- }
- }
-
- 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
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/MapFile.java Sun Aug 12 22:46:23 2012 +0200
@@ -0,0 +1,52 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Comparator;
+
+import org.hedgewars.hedgeroid.Utils;
+
+import android.content.Context;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+/**
+ * Represents a map from the data directory
+ */
+public final class MapFile {
+ public static final String MISSION_PREFIX = "Mission: "; // TODO move text generation to UI to allow translation
+ public static final String MAP_DIRECTORY = "Maps";
+
+ public final String name;
+ public final boolean isMission;
+
+ public MapFile(String name, boolean isMission) {
+ this.name = name;
+ this.isMission = isMission;
+ }
+
+ /**
+ * @throws FileNotFoundException if the sdcard is not available. Does NOT throw if the requested map file does not exist.
+ */
+ public static File getFileForMapname(Context ctx, String mapname) throws FileNotFoundException {
+ return new File(new File(Utils.getDataPathFile(ctx), MAP_DIRECTORY), mapname);
+ }
+
+ public static final Comparator<MapFile> MISSIONS_FIRST_NAME_ORDER = new Comparator<MapFile>() {
+ public int compare(MapFile lhs, MapFile rhs) {
+ if(lhs.isMission != rhs.isMission) {
+ return lhs.isMission && !rhs.isMission ? -1 : 1;
+ } else {
+ return lhs.name.compareToIgnoreCase(rhs.name);
+ }
+ }
+ };
+
+ @Override
+ public String toString() {
+ return (isMission ? MISSION_PREFIX : "") + name;
+ }
+
+ public File getPreviewFile(Context c) throws FileNotFoundException {
+ return new File(new File(new File(Utils.getDataPathFile(c), MAP_DIRECTORY), name), "preview.png");
+ };
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/MapRecipe.java Sun Aug 12 22:46:23 2012 +0200
@@ -0,0 +1,80 @@
+/*
+ * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
+ * Copyright (c) 2011-2012 Richard Deurwaarder <xeli@xelification.com>
+ *
+ * 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.Datastructures;
+
+import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.frontlib.Frontlib;
+
+import android.content.res.Resources;
+
+public final class MapRecipe {
+ public static final String MAPNAME_REGULAR = "+rnd+";
+ public static final String MAPNAME_MAZE = "+maze+";
+ public static final String MAPNAME_DRAWN = "+drawn+";
+
+ public final int mapgen; // Frontlib.MAPGEN_xxx
+ public final int templateFilter; // Frontlib.TEMPLATEFILTER_xxx, only used when mapgen==MAPGEN_REGULAR
+ public final int mazeSize; // Frontlib.MAZE_SIZE_xxx, only used when mapgen==MAPGEN_MAZE
+ public final String name, seed, theme;
+
+ private final byte[] drawData; // For drawn maps, can be null.
+
+ public MapRecipe(int mapgen, int templateFilter, int mazeSize, String name, String seed, String theme, byte[] drawData) {
+ this.mapgen = mapgen;
+ this.templateFilter = templateFilter;
+ this.mazeSize = mazeSize;
+ this.name = name;
+ this.seed = seed;
+ this.theme = theme;
+ this.drawData = drawData==null ? null : drawData.clone();
+ }
+
+ public static MapRecipe makeMap(String name, String seed, String theme) {
+ return new MapRecipe(Frontlib.MAPGEN_NAMED, 0, 0, name, seed, theme, null);
+ }
+
+ public static MapRecipe makeRandomMap(int templateFilter, String seed, String theme) {
+ return new MapRecipe(Frontlib.MAPGEN_REGULAR, templateFilter, 0, MAPNAME_REGULAR, seed, theme, null);
+ }
+
+ public static MapRecipe makeRandomMaze(int mazeSize, String seed, String theme) {
+ return new MapRecipe(Frontlib.MAPGEN_MAZE, 0, mazeSize, MAPNAME_MAZE, seed, theme, null);
+ }
+
+ public static MapRecipe makeDrawnMap(String seed, String theme, byte[] drawData) {
+ return new MapRecipe(Frontlib.MAPGEN_DRAWN, 0, 0, MAPNAME_DRAWN, seed, theme, drawData);
+ }
+
+ public byte[] getDrawData() {
+ return drawData==null ? null : drawData.clone();
+ }
+
+ public static String formatMapName(Resources res, String map) {
+ if(map.charAt(0)=='+') {
+ if(map.equals(MAPNAME_REGULAR)) {
+ return res.getString(R.string.map_regular);
+ } else if(map.equals(MAPNAME_MAZE)) {
+ return res.getString(R.string.map_maze);
+ } else if(map.equals(MAPNAME_DRAWN)) {
+ return res.getString(R.string.map_drawn);
+ }
+ }
+ return map;
+ }
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/RoomlistRoom.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/RoomlistRoom.java Sun Aug 12 22:46:23 2012 +0200
@@ -1,14 +1,8 @@
package org.hedgewars.hedgeroid.Datastructures;
-import org.hedgewars.hedgeroid.R;
-
import android.content.res.Resources;
public final class RoomlistRoom {
- public static final String MAP_REGULAR = "+rnd+";
- public static final String MAP_MAZE = "+maze+";
- public static final String MAP_DRAWN = "+drawn+";
-
public final String name, map, scheme, weapons, owner;
public final int playerCount, teamCount;
public final boolean inProgress;
@@ -25,21 +19,8 @@
this.inProgress = inProgress;
}
- public static String formatMapName(Resources res, String map) {
- if(map.charAt(0)=='+') {
- if(map.equals(MAP_REGULAR)) {
- return res.getString(R.string.map_regular);
- } else if(map.equals(MAP_MAZE)) {
- return res.getString(R.string.map_maze);
- } else if(map.equals(MAP_DRAWN)) {
- return res.getString(R.string.map_drawn);
- }
- }
- return map;
- }
-
public String formatMapName(Resources res) {
- return formatMapName(res, map);
+ return MapRecipe.formatMapName(res, map);
}
@Override
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Scheme.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Scheme.java Sun Aug 12 22:46:23 2012 +0200
@@ -38,13 +38,19 @@
}
public int getHealth() {
- return settings.get("health");
+ Integer health = settings.get("health");
+ return health==null ? 100 : health.intValue();
}
- @Override
+ /*@Override
public String toString() {
return "Scheme [metascheme=" + metascheme + ", name=" + name
+ ", settings=" + settings + ", mods=" + mods + "]";
+ }*/
+
+ @Override
+ public String toString() {
+ return name; // TODO change back once StartGameActivity does not need this anymore
}
public static final Comparator<Scheme> caseInsensitiveNameComparator = new Comparator<Scheme>() {
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Schemes.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Schemes.java Sun Aug 12 22:46:23 2012 +0200
@@ -32,6 +32,12 @@
return new File(c.getFilesDir(), "schemes_builtin.ini");
}
+ public static Map<String, Scheme> loadAllSchemes(Context c) throws IOException {
+ Map<String, Scheme> result = loadUserSchemes(c);
+ result.putAll(loadBuiltinSchemes(c));
+ return result;
+ }
+
public static Map<String, Scheme> loadUserSchemes(Context c) throws IOException {
return loadSchemes(c, getUserSchemesFile(c));
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Team.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Team.java Sun Aug 12 22:46:23 2012 +0200
@@ -22,26 +22,28 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import org.hedgewars.hedgeroid.Utils;
import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
import org.hedgewars.hedgeroid.frontlib.Flib;
import org.hedgewars.hedgeroid.frontlib.Frontlib.TeamPtr;
-import android.util.Log;
+import android.content.Context;
public final class Team {
public static final String DIRECTORY_TEAMS = "teams";
- public static final int maxNumberOfHogs = PascalExports.HWgetMaxNumberOfHogs();
+ public static final int HEDGEHOGS_PER_TEAM = Flib.INSTANCE.flib_get_hedgehogs_per_team();
public static final int maxNumberOfTeams = PascalExports.HWgetMaxNumberOfTeams();
public final String name, grave, flag, voice, fort;
public final List<Hog> hogs;
public Team(String name, String grave, String flag, String voice, String fort, List<Hog> hogs) {
- if(hogs.size() != maxNumberOfHogs) {
- throw new IllegalArgumentException("A team must consist of "+maxNumberOfHogs+" hogs.");
+ if(hogs.size() != HEDGEHOGS_PER_TEAM) {
+ throw new IllegalArgumentException("A team must consist of "+HEDGEHOGS_PER_TEAM+" hogs.");
}
this.name = name;
this.grave = grave;
@@ -52,7 +54,6 @@
}
public void save(File f) throws IOException {
- Log.d("Team", "saving to "+f.getAbsolutePath());
TeamPtr teamPtr = TeamPtr.createJavaOwned(this);
if(Flib.INSTANCE.flib_team_to_ini(f.getAbsolutePath(), teamPtr) != 0) {
throw new IOException("Error saving team "+name);
@@ -69,11 +70,21 @@
return null;
}
}
-
+
+ public static File getTeamfileByName(Context c, String teamName) {
+ return new File(new File(c.getFilesDir(), DIRECTORY_TEAMS), Utils.replaceBadChars(teamName)+".hwt");
+ }
+
@Override
public String toString() {
return "Team [name=" + name + ", grave=" + grave + ", flag=" + flag
+ ", voice=" + voice + ", fort=" + fort + ", hogs=" + hogs
+ "]";
}
+
+ public static Comparator<Team> NAME_ORDER = new Comparator<Team>() {
+ public int compare(Team lhs, Team rhs) {
+ return lhs.name.compareToIgnoreCase(rhs.name);
+ }
+ };
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamFile.java Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-package org.hedgewars.hedgeroid.Datastructures;
-
-import java.io.File;
-
-public final class TeamFile {
- public final Team team;
- public final File file;
-
- public TeamFile(Team team, File file) {
- this.team = team;
- this.file = file;
- }
-
- @Override
- public String toString() {
- return "TeamFile [team=" + team + ", file=" + file + "]";
- }
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamInGame.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamInGame.java Sun Aug 12 22:46:23 2012 +0200
@@ -1,5 +1,10 @@
package org.hedgewars.hedgeroid.Datastructures;
+/**
+ * A team with per-game configuration. This is similar to the frontlib "team" structure,
+ * except that it does not include weaponset and initial health, which are handled on a
+ * per-game basis in the UI, but per-hog in the frontlib.
+ */
public final class TeamInGame {
public final Team team;
public final TeamIngameAttributes ingameAttribs;
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamIngameAttributes.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/TeamIngameAttributes.java Sun Aug 12 22:46:23 2012 +0200
@@ -3,19 +3,19 @@
import java.util.ArrayList;
import java.util.Random;
+import org.hedgewars.hedgeroid.frontlib.Flib;
+
public final class TeamIngameAttributes {
- public static final int[] TEAM_COLORS = {
- 0xd12b42, /* red */
- 0x4980c1, /* blue */
- 0x6ab530, /* green */
- 0xbc64c4, /* purple */
- 0xe76d14, /* orange */
- 0x3fb6e6, /* cyan */
- 0xe3e90c, /* yellow */
- 0x61d4ac, /* mint */
- 0xf1c3e1, /* pink */
- /* add new colors here */
- };
+ public static final int DEFAULT_HOG_COUNT = 4;
+ public static final int[] TEAM_COLORS;
+
+ static {
+ int[] teamColors = new int[Flib.INSTANCE.flib_get_teamcolor_count()];
+ for(int i=0; i<teamColors.length; i++) {
+ teamColors[i] = Flib.INSTANCE.flib_get_teamcolor(i);
+ }
+ TEAM_COLORS = teamColors;
+ }
public final String ownerName;
public final int colorIndex, hogCount;
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Weapon.java Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
- * Copyright (c) 2011-2012 Richard Deurwaarder <xeli@xelification.com>
- *
- * 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.Datastructures;
-
-import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
-
-public class Weapon implements Comparable<Weapon>{
- public static final String DIRECTORY_WEAPON = "weapons";
- public static final int maxWeapons = PascalExports.HWgetNumberOfWeapons();
-
- private String name;
- private String QT;
- private String prob;
- private String delay;
- private String crate;
-
- 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 String toString(){
- return name;
- }
-
- public int compareTo(Weapon another) {
- return name.compareTo(another.name);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Weaponset.java Sun Aug 12 22:46:23 2012 +0200
@@ -0,0 +1,22 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import org.hedgewars.hedgeroid.frontlib.Flib;
+
+public final class Weaponset {
+ public static final int WEAPONS_COUNT = Flib.INSTANCE.flib_get_weapons_count();
+
+ public final String name, loadout, crateProb, crateAmmo, delay;
+
+ public Weaponset(String name, String loadout, String crateProb, String crateAmmo, String delay) {
+ this.name = name;
+ this.loadout = loadout;
+ this.crateProb = crateProb;
+ this.crateAmmo = crateAmmo;
+ this.delay = delay;
+ }
+
+ @Override
+ public String toString() {
+ return name; // TODO use the generated one once StartGameActivity doesn't need this anymore
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Datastructures/Weaponsets.java Sun Aug 12 22:46:23 2012 +0200
@@ -0,0 +1,63 @@
+package org.hedgewars.hedgeroid.Datastructures;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.hedgewars.hedgeroid.frontlib.Flib;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.WeaponsetListPtr;
+
+import android.content.Context;
+
+public final class Weaponsets {
+ private Weaponsets() {
+ throw new AssertionError("This class is not meant to be instantiated");
+ }
+
+ public static File getUserWeaponsetsFile(Context c) {
+ return new File(c.getFilesDir(), "weapons_user.ini");
+ }
+
+ public static File getBuiltinWeaponsetsFile(Context c) {
+ return new File(c.getFilesDir(), "weapons_builtin.ini");
+ }
+
+ public static List<Weaponset> loadAllWeaponsets(Context c) throws IOException {
+ List<Weaponset> result = loadBuiltinWeaponsets(c);
+ result.addAll(loadUserWeaponsets(c));
+ return result;
+ }
+
+ public static List<Weaponset> loadUserWeaponsets(Context c) throws IOException {
+ return loadWeaponsets(c, getUserWeaponsetsFile(c));
+ }
+
+ public static List<Weaponset> loadBuiltinWeaponsets(Context c) throws IOException {
+ return loadWeaponsets(c, getBuiltinWeaponsetsFile(c));
+ }
+
+ public static List<Weaponset> loadWeaponsets(Context c, File weaponsetFile) throws IOException {
+ if(!weaponsetFile.isFile()) {
+ // No file == no weaponsets, no error
+ return new ArrayList<Weaponset>();
+ }
+ WeaponsetListPtr weaponsetListPtr = null;
+ try {
+ weaponsetListPtr = Flib.INSTANCE.flib_weaponsetlist_from_ini(weaponsetFile.getAbsolutePath());
+ if(weaponsetListPtr == null) {
+ throw new IOException("Unable to read weaponsets from "+weaponsetFile);
+ }
+ return weaponsetListPtr.deref();
+ } finally {
+ if(weaponsetListPtr != null) {
+ Flib.INSTANCE.flib_weaponsetlist_destroy(weaponsetListPtr);
+ }
+ }
+ }
+
+ public static void saveUserWeaponsets(Context c, List<Weaponset> weaponsets) throws IOException {
+ WeaponsetListPtr ptr = WeaponsetListPtr.createJavaOwned(weaponsets);
+ Flib.INSTANCE.flib_weaponsetlist_to_ini(getUserWeaponsetsFile(c).getAbsolutePath(), ptr);
+ }
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java Sun Aug 12 22:46:23 2012 +0200
@@ -7,10 +7,9 @@
import org.hedgewars.hedgeroid.MainActivity;
import org.hedgewars.hedgeroid.R;
import org.hedgewars.hedgeroid.Utils;
-import org.hedgewars.hedgeroid.Datastructures.Scheme;
import org.hedgewars.hedgeroid.Datastructures.Schemes;
import org.hedgewars.hedgeroid.Datastructures.Team;
-import org.hedgewars.hedgeroid.Datastructures.Weapon;
+import org.hedgewars.hedgeroid.Datastructures.Weaponsets;
import android.content.res.AssetManager;
import android.os.AsyncTask;
@@ -46,7 +45,7 @@
protected Boolean doInBackground(Object... params) {
try {
Utils.writeStreamToFile(act.getResources().openRawResource(R.raw.schemes_builtin), Schemes.getBuiltinSchemesFile(act));
- Utils.resRawToFilesDir(act, R.array.weapons, Weapon.DIRECTORY_WEAPON);
+ Utils.writeStreamToFile(act.getResources().openRawResource(R.raw.weapons_builtin), Weaponsets.getBuiltinWeaponsetsFile(act));
Utils.resRawToFilesDir(act, R.array.teams, Team.DIRECTORY_TEAMS);
copyFileOrDir(act.getAssets(), Utils.getDataPathFile(act), "Data");
copyFileOrDir(act.getAssets(), new File(Utils.getCachePath(act), VERSION_FILENAME), VERSION_FILENAME);
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/GameConfig.java Sun Aug 12 22:37:57 2012 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
- * Copyright (c) 2011-2012 Richard Deurwaarder <xeli@xelification.com>
- *
- * 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.util.ArrayList;
-
-import org.hedgewars.hedgeroid.Datastructures.GameMode;
-import org.hedgewars.hedgeroid.Datastructures.Map;
-import org.hedgewars.hedgeroid.Datastructures.Scheme;
-import org.hedgewars.hedgeroid.Datastructures.Team;
-import org.hedgewars.hedgeroid.Datastructures.Weapon;
-
-public class GameConfig {
- public GameMode mode = GameMode.MODE_LOCAL;
- public Map map = null;
- public String theme = null;
- public Scheme scheme = null;
- public Weapon weapon = null;
-
- public String style = null;
- public String training = null;
- public String seed = null;
-
- public ArrayList<Team> teams = new ArrayList<Team>();
-
- public GameConfig(){
-
- }
-}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/EngineProtocol/PascalExports.java Sun Aug 12 22:46:23 2012 +0200
@@ -31,10 +31,6 @@
System.loadLibrary("hwengine");
}
- public static native int HWversionInfoNetProto();
- public static native String HWversionInfoVersion();
- public static native int HWgetNumberOfWeapons();
public static native int HWgetMaxNumberOfTeams();
- public static native int HWgetMaxNumberOfHogs();
public static native int HWterminate(boolean b);
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Sun Aug 12 22:46:23 2012 +0200
@@ -24,6 +24,7 @@
import org.hedgewars.hedgeroid.Downloader.DownloadAssets;
import org.hedgewars.hedgeroid.Downloader.DownloadListActivity;
+import org.hedgewars.hedgeroid.frontlib.Flib;
import org.hedgewars.hedgeroid.netplay.LobbyActivity;
import org.hedgewars.hedgeroid.netplay.Netplay;
import org.hedgewars.hedgeroid.netplay.Netplay.State;
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/SDLActivity.java Sun Aug 12 22:46:23 2012 +0200
@@ -6,13 +6,16 @@
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
-import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
+import org.hedgewars.hedgeroid.Datastructures.GameConfig;
import org.hedgewars.hedgeroid.EngineProtocol.PascalExports;
import org.hedgewars.hedgeroid.frontlib.Flib;
import org.hedgewars.hedgeroid.frontlib.Frontlib.GameSetupPtr;
import org.hedgewars.hedgeroid.frontlib.Frontlib.GameconnPtr;
+import org.hedgewars.hedgeroid.frontlib.Frontlib.IntCallback;
import org.hedgewars.hedgeroid.netplay.TickHandler;
+import com.sun.jna.Pointer;
+
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
@@ -424,7 +427,18 @@
private final int surfaceWidth, surfaceHeight;
private final GameConfig config;
-
+ private GameconnPtr conn;
+ HandlerThread thread = new HandlerThread("IPC thread");
+
+ private final IntCallback dccb = new IntCallback() {
+ public void callback(Pointer context, int arg1) {
+ Log.d("SDLMain", "Disconnected: "+arg1);
+ Flib.INSTANCE.flib_gameconn_destroy(conn);
+ conn = null;
+ thread.quit();
+ }
+ };
+
public SDLMain(int width, int height, GameConfig _config) {
config = _config;
surfaceWidth = width;
@@ -433,35 +447,40 @@
public void run() {
//Set up the IPC socket server to communicate with the engine
- HandlerThread thread = new HandlerThread("IPC thread");
- thread.start(); // TODO ensure it gets stopped
+
final GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Xeli", GameSetupPtr.createJavaOwned(config), false);
if(conn == null) {
throw new AssertionError();
}
+ Flib.INSTANCE.flib_gameconn_onDisconnect(conn, dccb, null);
int port = Flib.INSTANCE.flib_gameconn_getport(conn);
String path = Utils.getDataPath(SDLActivity.mSingleton);//This represents the data directory
path = path.substring(0, path.length()-1);//remove the trailing '/'
+ thread.start(); // TODO ensure it gets stopped
+ new TickHandler(thread.getLooper(), 500, new Runnable() {
+ public void run() {
+ Log.d("SDLMain", "pre-tick");
+ Flib.INSTANCE.flib_gameconn_tick(conn);
+ Log.d("SDLMain", "post-tick");
+ }
+ }).start();
+
+ Log.d("SDLMain", "Starting engine");
// Runs SDL_main() with added parameters
SDLActivity.nativeInit(new String[] { String.valueOf(port),
String.valueOf(surfaceWidth), String.valueOf(surfaceHeight),
"0", "en.txt", "xeli", "1", "1", "1", path, "" });
-
- new TickHandler(thread.getLooper(), 50, new Runnable() {
- public void run() {
- Flib.INSTANCE.flib_gameconn_tick(conn);
- }
- });
+ Log.d("SDLMain", "Engine stopped");
try {
- thread.quit();
thread.join();
} catch (InterruptedException e) {
throw new AssertionError();
}
+ Log.v("SDLMain", "thread joined");
Flib.INSTANCE.flib_gameconn_destroy(conn);
- Log.v("SDL", "SDL thread terminated");
+ Log.v("SDLMain", "SDL thread terminated");
}
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartGameActivity.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/StartGameActivity.java Sun Aug 12 22:46:23 2012 +0200
@@ -19,19 +19,29 @@
package org.hedgewars.hedgeroid;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
-import org.hedgewars.hedgeroid.Datastructures.Map;
-import org.hedgewars.hedgeroid.Datastructures.Map.MapType;
+import org.hedgewars.hedgeroid.Datastructures.GameConfig;
+import org.hedgewars.hedgeroid.Datastructures.MapFile;
+import org.hedgewars.hedgeroid.Datastructures.MapRecipe;
import org.hedgewars.hedgeroid.Datastructures.Scheme;
-import org.hedgewars.hedgeroid.Datastructures.Team;
-import org.hedgewars.hedgeroid.Datastructures.Weapon;
-import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
+import org.hedgewars.hedgeroid.Datastructures.Schemes;
+import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+import org.hedgewars.hedgeroid.Datastructures.Weaponset;
+import org.hedgewars.hedgeroid.Datastructures.Weaponsets;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.os.Parcelable;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
@@ -43,17 +53,16 @@
import android.widget.Toast;
public class StartGameActivity extends Activity {
-
public static final int ACTIVITY_TEAM_SELECTOR = 0;
- private GameConfig config = null;
private ImageButton start, back, team;
private Spinner maps, gameplay, gamescheme, weapons, themes;
private ImageView themeIcon, mapPreview, teamCount;
+
+ private List<TeamInGame> teams = new ArrayList<TeamInGame>();
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
- config = new GameConfig();
setContentView(R.layout.starting_game);
@@ -75,22 +84,35 @@
back.setOnClickListener(backClicker);
team.setOnClickListener(teamClicker);
- ArrayAdapter<?> adapter = new ArrayAdapter<Map>(this, R.layout.listview_item, FrontendDataUtils.getMaps(this));
+ List<MapFile> mapFiles;
+ try {
+ mapFiles = FrontendDataUtils.getMaps(this);
+ } catch (FileNotFoundException e) {
+ Log.e("StartGameActivity", e.getMessage(), e);
+ mapFiles = Collections.emptyList();
+ }
+ ArrayAdapter<?> adapter = new ArrayAdapter<MapFile>(this, R.layout.listview_item, mapFiles);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
maps.setAdapter(adapter);
maps.setOnItemSelectedListener(mapsClicker);
- //set to first nonmap
+ //set to first nonmission
for(int i = 0; i < adapter.getCount(); i++){
- if(((Map)adapter.getItem(i)).getType() == MapType.TYPE_DEFAULT){
+ if(!((MapFile)adapter.getItem(i)).isMission){
maps.setSelection(i, false);
break;
}
}
- adapter = new ArrayAdapter<String>(this, R.layout.listview_item, FrontendDataUtils.getGameplay(this));
+ List<String> gameStyles;
+ try {
+ gameStyles = FrontendDataUtils.getGameStyles(this);
+ } catch (FileNotFoundException e) {
+ Log.e("StartGameActivity", e.getMessage(), e);
+ gameStyles = Collections.emptyList();
+ }
+ adapter = new ArrayAdapter<String>(this, R.layout.listview_item, gameStyles);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
gameplay.setAdapter(adapter);
- gameplay.setOnItemSelectedListener(gameplayClicker);
//set to first nonmap
for(int i = 0; i < adapter.getCount(); i++){
if(((String)adapter.getItem(i)).equals("None")){
@@ -99,30 +121,48 @@
}
}
- adapter = new ArrayAdapter<Scheme>(this, R.layout.listview_item, FrontendDataUtils.getSchemes(this));
+ List<Scheme> schemes;
+ try {
+ schemes = new ArrayList<Scheme>(Schemes.loadAllSchemes(this).values());
+ } catch (IOException e) {
+ Log.e("StartGameActivity", e.getMessage(), e);
+ schemes = Collections.emptyList();
+ }
+ adapter = new ArrayAdapter<Scheme>(this, R.layout.listview_item, schemes);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
gamescheme.setAdapter(adapter);
- gamescheme.setOnItemSelectedListener(schemeClicker);
- //set to first nonmap
for(int i = 0; i < adapter.getCount(); i++){
- if(((Scheme)adapter.getItem(i)).toString().equals("Default")){
+ if(((Scheme)adapter.getItem(i)).name.equals("Default")){
gamescheme.setSelection(i, false);
break;
}
}
-
- adapter = new ArrayAdapter<Weapon>(this, R.layout.listview_item, FrontendDataUtils.getWeapons(this));
+ List<Weaponset> weaponsets;
+ try {
+ weaponsets = Weaponsets.loadAllWeaponsets(this);
+ } catch(IOException e) {
+ Log.e("StartGameActivity", e.getMessage(), e);
+ weaponsets = Collections.emptyList();
+ }
+ adapter = new ArrayAdapter<Weaponset>(this, R.layout.listview_item, weaponsets);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
weapons.setAdapter(adapter);
- weapons.setOnItemSelectedListener(weaponClicker);
for(int i = 0; i < adapter.getCount(); i++){
- if(((Weapon)adapter.getItem(i)).toString().equals("Crazy")){
+ if(((Weaponset)adapter.getItem(i)).name.equals("Crazy")){
weapons.setSelection(i, false);
break;
}
}
- adapter = new ArrayAdapter<String>(this, R.layout.listview_item, FrontendDataUtils.getThemes(this));
+
+ List<String> themeList;
+ try {
+ themeList = FrontendDataUtils.getThemes(this);
+ } catch(FileNotFoundException e) {
+ Log.e("StartGameActivity", e.getMessage(), e);
+ themeList = Collections.emptyList();
+ }
+ adapter = new ArrayAdapter<String>(this, R.layout.listview_item, themeList);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
themes.setAdapter(adapter);
themes.setOnItemSelectedListener(themesClicker);
@@ -130,7 +170,7 @@
private void startTeamsActivity(){
Intent i = new Intent(StartGameActivity.this, TeamSelectionActivity.class);
- // TODO i.putParcelableArrayListExtra("teams", config.teams);
+ TeamSelectionActivity.activityParams = new ArrayList<TeamInGame>(teams);
startActivityForResult(i, ACTIVITY_TEAM_SELECTOR);
}
@@ -138,12 +178,9 @@
switch(requestCode){
case ACTIVITY_TEAM_SELECTOR:
if(resultCode == Activity.RESULT_OK){
- Parcelable[] parcelables = (Parcelable[])data.getParcelableArrayExtra("teams");
- config.teams.clear();
- for(Parcelable t : parcelables){
- // TODO config.teams.add((Team)t);
- }
- teamCount.getDrawable().setLevel(config.teams.size());
+ teams = new ArrayList<TeamInGame>(TeamSelectionActivity.activityReturn);
+ TeamSelectionActivity.activityReturn = Collections.emptyList();
+ teamCount.getDrawable().setLevel(teams.size());
}
break;
}
@@ -156,7 +193,6 @@
String themeName = (String) arg0.getAdapter().getItem(position);
Drawable themeIconDrawable = Drawable.createFromPath(Utils.getDataPath(StartGameActivity.this) + "Themes/" + themeName + "/icon@2X.png");
themeIcon.setImageDrawable(themeIconDrawable);
- config.theme = themeName;
}
public void onNothingSelected(AdapterView<?> arg0) {
@@ -167,9 +203,13 @@
private OnItemSelectedListener mapsClicker = new OnItemSelectedListener(){
public void onItemSelected(AdapterView<?> arg0, View view, int position,long rowId) {
- Map map = (Map)arg0.getAdapter().getItem(position);
- mapPreview.setImageDrawable(map.getDrawable());
- config.map = map;
+ MapFile map = (MapFile)arg0.getAdapter().getItem(position);
+ try {
+ File previewFile = map.getPreviewFile(getApplicationContext());
+ mapPreview.setImageDrawable(Drawable.createFromPath(previewFile.getAbsolutePath()));
+ } catch (FileNotFoundException e) {
+ mapPreview.setImageDrawable(null);
+ }
}
public void onNothingSelected(AdapterView<?> arg0) {
@@ -177,38 +217,19 @@
};
- private OnItemSelectedListener weaponClicker = new OnItemSelectedListener(){
- public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
- config.weapon = (Weapon)arg0.getAdapter().getItem(arg2);
- }
- public void onNothingSelected(AdapterView<?> arg0) {
-
- }
- };
- private OnItemSelectedListener schemeClicker = new OnItemSelectedListener(){
- public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
- config.scheme = (Scheme)arg0.getAdapter().getItem(arg2);
- }
- public void onNothingSelected(AdapterView<?> arg0) {
-
- }
- };
- private OnItemSelectedListener gameplayClicker = new OnItemSelectedListener(){
- public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
- //config = ()arg0.getAdapter().getItem(arg2);
- }
- public void onNothingSelected(AdapterView<?> arg0) {
-
- }
- };
-
private OnClickListener startClicker = new OnClickListener(){
public void onClick(View v) {
- if(config.teams.size() < 2){
- Toast.makeText(StartGameActivity.this, R.string.not_enough_teams, Toast.LENGTH_LONG).show();
+ if(teams.size() < 2) {
+ Toast.makeText(getApplicationContext(), R.string.not_enough_teams, Toast.LENGTH_LONG).show();
startTeamsActivity();
} else {
- SDLActivity.startConfig = config;
+ String style = (String)gameplay.getSelectedItem();
+ Scheme scheme = (Scheme)gamescheme.getSelectedItem();
+ String mapName = ((MapFile)maps.getSelectedItem()).name;
+ String theme = (String)themes.getSelectedItem();
+ MapRecipe map = MapRecipe.makeMap(mapName, UUID.randomUUID().toString(), theme);
+ Weaponset weaponset = (Weaponset)weapons.getSelectedItem();
+ SDLActivity.startConfig = new GameConfig(style, scheme, map, teams, weaponset);
Intent i = new Intent(StartGameActivity.this, SDLActivity.class);
startActivity(i);
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamCreatorActivity.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamCreatorActivity.java Sun Aug 12 22:46:23 2012 +0200
@@ -20,11 +20,13 @@
package org.hedgewars.hedgeroid;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
import org.hedgewars.hedgeroid.Datastructures.Hog;
@@ -37,7 +39,6 @@
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
-import android.view.View.OnFocusChangeListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
@@ -49,23 +50,29 @@
import android.widget.ScrollView;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
+import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;
-public class TeamCreatorActivity extends Activity implements Runnable{
-
+/**
+ * Edit or create a team. If a team should be edited, it is supplied in the extras
+ * as parameter oldTeamName.
+ */
+public class TeamCreatorActivity extends Activity implements Runnable {
+ public static final String PARAMETER_EXISTING_TEAMNAME = "existingTeamName";
+
private TextView name;
private Spinner difficulty, grave, flag, voice, fort;
private ImageView imgFort;
private ArrayList<ImageButton> hogDice = new ArrayList<ImageButton>();
private ArrayList<Spinner> hogHat = new ArrayList<Spinner>();
private ArrayList<EditText> hogName = new ArrayList<EditText>();
- private ImageButton back, save, voiceButton;
+ private ImageButton voiceButton;
private ScrollView scroller;
private MediaPlayer mp = null;
- private boolean settingsChanged = false;
- private boolean saved = false;
- private String fileName = null;
+ private boolean initComplete = false;
+
+ private String existingTeamName = null;
private final List<HashMap<String, ?>> flagsData = new ArrayList<HashMap<String, ?>>();
private final List<HashMap<String, ?>> typesData = new ArrayList<HashMap<String, ?>>();
@@ -76,6 +83,16 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ initComplete = false;
+
+ // Restore state and read parameters
+ if(savedInstanceState != null) {
+ existingTeamName = savedInstanceState.getString(PARAMETER_EXISTING_TEAMNAME);
+ } else {
+ existingTeamName = getIntent().getStringExtra(PARAMETER_EXISTING_TEAMNAME);
+ }
+
+ // Set up view
setContentView(R.layout.team_creation);
name = (TextView) findViewById(R.id.txtName);
@@ -87,15 +104,11 @@
imgFort = (ImageView) findViewById(R.id.imgFort);
- back = (ImageButton) findViewById(R.id.btnBack);
- save = (ImageButton) findViewById(R.id.btnSave);
voiceButton = (ImageButton) findViewById(R.id.btnPlay);
scroller = (ScrollView) findViewById(R.id.scroller);
- save.setOnClickListener(saveClicker);
- back.setOnClickListener(backClicker);
-
+ // Wire view elements
LinearLayout ll = (LinearLayout) findViewById(R.id.HogsContainer);
for (int i = 0; i < ll.getChildCount(); i++) {
RelativeLayout team_creation_entry = (RelativeLayout) ll.getChildAt(i);
@@ -108,107 +121,116 @@
.findViewById(R.id.txtTeam1));
}
- SimpleAdapter sa = new SimpleAdapter(this, gravesData,
- R.layout.spinner_textimg_entry, new String[] { "txt", "img" },
- new int[] { R.id.spinner_txt, R.id.spinner_img });
- sa.setDropDownViewResource(R.layout.spinner_textimg_dropdown_entry);
- sa.setViewBinder(viewBinder);
- grave.setAdapter(sa);
- grave.setOnFocusChangeListener(focusser);
-
- sa = new SimpleAdapter(this, flagsData, R.layout.spinner_textimg_entry,
- new String[] { "txt", "img" }, new int[] { R.id.spinner_txt,
- R.id.spinner_img });
- sa.setDropDownViewResource(R.layout.spinner_textimg_dropdown_entry);
- sa.setViewBinder(viewBinder);
- flag.setAdapter(sa);
- flag.setOnFocusChangeListener(focusser);
-
- sa = new SimpleAdapter(this, typesData, R.layout.spinner_textimg_entry,
- new String[] { "txt", "img" }, new int[] { R.id.spinner_txt,
- R.id.spinner_img });
- sa.setDropDownViewResource(R.layout.spinner_textimg_dropdown_entry);
- difficulty.setAdapter(sa);
- difficulty.setOnFocusChangeListener(focusser);
-
- sa = new SimpleAdapter(this, hatsData, R.layout.spinner_textimg_entry,
- new String[] { "txt", "img" }, new int[] { R.id.spinner_txt,
- R.id.spinner_img });
- sa.setDropDownViewResource(R.layout.spinner_textimg_dropdown_entry);
- sa.setViewBinder(viewBinder);
+ grave.setAdapter(createMapSpinnerAdapter(gravesData));
+ flag.setAdapter(createMapSpinnerAdapter(flagsData));
+ difficulty.setAdapter(createMapSpinnerAdapter(typesData));
+ SpinnerAdapter hatAdapter = createMapSpinnerAdapter(hatsData);
for (Spinner spin : hogHat) {
- spin.setAdapter(sa);
+ spin.setAdapter(hatAdapter);
}
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.listview_item, voicesData);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- voice.setAdapter(adapter);
- voice.setOnFocusChangeListener(focusser);
+
+ voice.setAdapter(createListSpinnerAdapter(voicesData));
voiceButton.setOnClickListener(voiceClicker);
- adapter = new ArrayAdapter<String>(this, R.layout.listview_item, fortsData);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- fort.setAdapter(adapter);
+ fort.setAdapter(createListSpinnerAdapter(fortsData));
fort.setOnItemSelectedListener(fortSelector);
- fort.setOnFocusChangeListener(focusser);
new Thread(this).start();
}
- public void run(){
- final ArrayList<HashMap<String, ?>> gravesDataNew = FrontendDataUtils.getGraves(this);
- this.runOnUiThread(new Runnable(){
- public void run() {
- copy(gravesData, gravesDataNew);
- ((SimpleAdapter)grave.getAdapter()).notifyDataSetChanged();
- }
- });
-
- final ArrayList<HashMap<String, ?>> flagsDataNew = FrontendDataUtils.getFlags(this);
- this.runOnUiThread(new Runnable(){
- public void run() {
- copy(flagsData, flagsDataNew);
- ((SimpleAdapter)flag.getAdapter()).notifyDataSetChanged();
- }
- });
-
- final ArrayList<HashMap<String, ?>> typesDataNew = FrontendDataUtils.getTypes(this);
- this.runOnUiThread(new Runnable(){
- public void run() {
- copy(typesData, typesDataNew);
- ((SimpleAdapter)difficulty.getAdapter()).notifyDataSetChanged();
- }
- });
-
- final ArrayList<HashMap<String, ?>> hatsDataNew = FrontendDataUtils.getHats(this);
- this.runOnUiThread(new Runnable(){
- public void run() {
- copy(hatsData, hatsDataNew);
- ((SimpleAdapter)hogHat.get(0).getAdapter()).notifyDataSetChanged();
- }
- });
-
- final ArrayList<String> voicesDataNew = FrontendDataUtils.getVoices(this);
- this.runOnUiThread(new Runnable(){
- public void run() {
- copy(voicesData, voicesDataNew);
- ((ArrayAdapter<String>)voice.getAdapter()).notifyDataSetChanged();
- }
- });
-
- final ArrayList<String> fortsDataNew = FrontendDataUtils.getForts(this);
- this.runOnUiThread(new Runnable(){
- public void run() {
- copy(fortsData, fortsDataNew);
- ((ArrayAdapter<String>)fort.getAdapter()).notifyDataSetChanged();
- }
- });
+ private SpinnerAdapter createMapSpinnerAdapter(List<? extends Map<String, ?>> data) {
+ SimpleAdapter sa = new SimpleAdapter(this, data,
+ R.layout.spinner_textimg_entry, new String[] { "txt", "img" },
+ new int[] { R.id.spinner_txt, R.id.spinner_img });
+ sa.setDropDownViewResource(R.layout.spinner_textimg_dropdown_entry);
+ sa.setViewBinder(viewBinder);
+ return sa;
+ }
+
+ private SpinnerAdapter createListSpinnerAdapter(List<String> data) {
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.listview_item, data);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ return adapter;
}
- private static <T> void copy(List<T> dest, List<T> src){
- for(T t: src) dest.add(t);
+ public void run(){
+ try {
+ final ArrayList<HashMap<String, ?>> gravesDataNew = FrontendDataUtils.getGraves(this);
+ runOnUiThread(new Runnable(){
+ public void run() {
+ gravesData.addAll(gravesDataNew);
+ ((SimpleAdapter)grave.getAdapter()).notifyDataSetChanged();
+ }
+ });
+
+ final ArrayList<HashMap<String, ?>> flagsDataNew = FrontendDataUtils.getFlags(this);
+ runOnUiThread(new Runnable(){
+ public void run() {
+ flagsData.addAll(flagsDataNew);
+ ((SimpleAdapter)flag.getAdapter()).notifyDataSetChanged();
+ }
+ });
+
+ final ArrayList<HashMap<String, ?>> typesDataNew = FrontendDataUtils.getTypes(this);
+ runOnUiThread(new Runnable(){
+ public void run() {
+ typesData.addAll(typesDataNew);
+ ((SimpleAdapter)difficulty.getAdapter()).notifyDataSetChanged();
+ }
+ });
+
+ final ArrayList<HashMap<String, ?>> hatsDataNew = FrontendDataUtils.getHats(this);
+ runOnUiThread(new Runnable(){
+ public void run() {
+ hatsData.addAll(hatsDataNew);
+ ((SimpleAdapter)hogHat.get(0).getAdapter()).notifyDataSetChanged();
+ }
+ });
+
+ final ArrayList<String> voicesDataNew = FrontendDataUtils.getVoices(this);
+ runOnUiThread(new Runnable(){
+ public void run() {
+ voicesData.addAll(voicesDataNew);
+ ((ArrayAdapter<?>)voice.getAdapter()).notifyDataSetChanged();
+ }
+ });
+
+ final ArrayList<String> fortsDataNew = FrontendDataUtils.getForts(this);
+ runOnUiThread(new Runnable(){
+ public void run() {
+ fortsData.addAll(fortsDataNew);
+ ((ArrayAdapter<?>)fort.getAdapter()).notifyDataSetChanged();
+ }
+ });
+
+ if(existingTeamName!=null) {
+ final Team loadedTeam = Team.load(Team.getTeamfileByName(getApplicationContext(), existingTeamName));
+ if(loadedTeam==null) {
+ existingTeamName = null;
+ } else {
+ runOnUiThread(new Runnable(){
+ public void run() {
+ setTeamValues(loadedTeam);
+ }
+ });
+ }
+ }
+ runOnUiThread(new Runnable(){
+ public void run() {
+ initComplete = true;
+ }
+ });
+ } catch(FileNotFoundException e) {
+ this.runOnUiThread(new Runnable(){
+ public void run() {
+ Toast.makeText(getApplicationContext(), R.string.error_missing_sdcard_or_files, Toast.LENGTH_LONG).show();
+ finish();
+ }
+ });
+ }
}
-
+
public void onDestroy() {
super.onDestroy();
if (mp != null) {
@@ -217,93 +239,88 @@
}
}
- private OnFocusChangeListener focusser = new OnFocusChangeListener() {
- public void onFocusChange(View v, boolean hasFocus) {
- settingsChanged = true;
- }
-
- };
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString(PARAMETER_EXISTING_TEAMNAME, existingTeamName);
+ }
public void onBackPressed() {
- onFinishing();
+ if(initComplete) {
+ saveTeam();
+ }
+ setResult(RESULT_OK);
super.onBackPressed();
-
}
- private OnClickListener backClicker = new OnClickListener() {
- public void onClick(View v) {
- onFinishing();
- finish();
+ private int getDifficultyLevelFromText(String text) {
+ if (text.equals(getString(R.string.human))) {
+ return 0;
+ } else if (text.equals(getString(R.string.bot5))) {
+ return 1;
+ } else if (text.equals(getString(R.string.bot4))) {
+ return 2;
+ } else if (text.equals(getString(R.string.bot3))) {
+ return 3;
+ } else if (text.equals(getString(R.string.bot2))) {
+ return 4;
+ } else {
+ return 5;
+ }
+ }
+
+ private String getTxtFromDifficulty(int level) {
+ switch(level) {
+ case 0: return getString(R.string.human);
+ case 1: return getString(R.string.bot5);
+ case 2: return getString(R.string.bot4);
+ case 3: return getString(R.string.bot3);
+ case 4: return getString(R.string.bot2);
+ default: return getString(R.string.bot1);
+ }
+ }
+
+ private void saveTeam() {
+ String teamName = name.getText().toString();
+ String teamFlag = (String)((Map<String, Object>) flag.getSelectedItem()).get("txt");
+ String teamFort = fort.getSelectedItem().toString();
+ String teamGrave = (String)((Map<String, Object>) grave.getSelectedItem()).get("txt");
+ String teamVoice = voice.getSelectedItem().toString();
+ String levelString = (String)((Map<String, Object>) difficulty.getSelectedItem()).get("txt");
+ int levelInt = getDifficultyLevelFromText(levelString);
+
+ List<Hog> hogs = new ArrayList<Hog>();
+ for (int i = 0; i < hogName.size(); i++) {
+ String name = hogName.get(i).getText().toString();
+ String hat = ((Map<String, Object>) hogHat.get(i).getSelectedItem()).get("txt").toString();
+ hogs.add(new Hog(name, hat, levelInt));
+ }
+
+ Team team = new Team(teamName, teamGrave, teamFlag, teamVoice, teamFort, hogs);
+ File teamsDir = new File(getFilesDir(), Team.DIRECTORY_TEAMS);
+ if (!teamsDir.exists()) teamsDir.mkdir();
+
+ File newFile = Team.getTeamfileByName(this, teamName);
+ File oldFile = null;
+ if(existingTeamName != null) {
+ oldFile = Team.getTeamfileByName(this, existingTeamName);
+ }
+ try {
+ team.save(newFile);
+ Toast.makeText(TeamCreatorActivity.this, R.string.saved, Toast.LENGTH_SHORT).show();
+ // If the team was renamed, delete the old file.
+ if(oldFile != null && oldFile.isFile() && !oldFile.equals(newFile)) {
+ oldFile.delete();
+ }
+ existingTeamName = teamName;
+ } catch(IOException e) {
+ Toast.makeText(getApplicationContext(), R.string.error_save_failed, Toast.LENGTH_SHORT).show();
}
};
- private void onFinishing() {
- if (settingsChanged) {
- setResult(RESULT_OK);
- } else {
- setResult(RESULT_CANCELED);
- }
- }
-
- private OnClickListener saveClicker = new OnClickListener() {
- public void onClick(View v) {
- String teamName = name.getText().toString();
- String teamFlag = (String)((Map<String, Object>) flag.getSelectedItem()).get("txt");
- String teamFort = fort.getSelectedItem().toString();
- String teamGrave = (String)((Map<String, Object>) grave.getSelectedItem()).get("txt");
- String teamVoice = voice.getSelectedItem().toString();
- String levelString = (String)((Map<String, Object>) difficulty.getSelectedItem()).get("txt");
- int levelInt;
- if (levelString.equals(getString(R.string.human))) {
- levelInt = 0;
- } else if (levelString.equals(getString(R.string.bot5))) {
- levelInt = 1;
- } else if (levelString.equals(getString(R.string.bot4))) {
- levelInt = 2;
- } else if (levelString.equals(getString(R.string.bot3))) {
- levelInt = 3;
- } else if (levelString.equals(getString(R.string.bot2))) {
- levelInt = 4;
- } else {
- levelInt = 5;
- }
-
- List<Hog> hogs = new ArrayList<Hog>();
- for (int i = 0; i < hogName.size(); i++) {
- String name = hogName.get(i).getText().toString();
- String hat = ((Map<String, Object>) hogHat.get(i).getSelectedItem()).get("txt").toString();
- hogs.add(new Hog(name, hat, levelInt));
- }
-
- Team team = new Team(teamName, teamGrave, teamFlag, teamVoice, teamFort, hogs);
- File teamsDir = new File(getFilesDir(), Team.DIRECTORY_TEAMS);
- if (!teamsDir.exists()) teamsDir.mkdir();
- if(fileName == null){
- fileName = createNewFilename(Utils.replaceBadChars(team.name));
- }
- try {
- team.save(new File(teamsDir, fileName));
- Toast.makeText(TeamCreatorActivity.this, R.string.saved, Toast.LENGTH_SHORT).show();
- saved = true;
- } catch(IOException e) {
- Toast.makeText(getApplicationContext(), R.string.error_save_failed, Toast.LENGTH_SHORT).show();
- }
- }
- };
-
- private String createNewFilename(String suggestedName){
- File f = new File(getFilesDir(), suggestedName);
- if(f.exists()){
- return createNewFilename(suggestedName + (int)(Math.random()*10));
- } else {
- return suggestedName + (int)(Math.random()*10);
- }
- }
-
private OnItemSelectedListener fortSelector = new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> arg0, View arg1,
int position, long arg3) {
- settingsChanged = true;
String fortName = (String) arg0.getAdapter().getItem(position);
Drawable fortIconDrawable = Drawable.createFromPath(Utils
.getDataPath(TeamCreatorActivity.this)
@@ -351,54 +368,48 @@
}
};
+ @SuppressWarnings("unchecked")
private void setTeamValues(Team t){
-
- if (t != null) {
+ if (t == null) {
+ return;
+ }
+
+ try {
name.setText(t.name);
- int position = ((ArrayAdapter<String>) voice.getAdapter()).getPosition(t.voice);
- voice.setSelection(position);
-
- position = ((ArrayAdapter<String>) fort.getAdapter()).getPosition(t.fort);
- fort.setSelection(position);
-
- position = 0;
- for (HashMap<String, ?> hashmap : typesData) {
- if (t.hogs.get(0) != null && hashmap.get("txt").equals(t.hogs.get(0).level)) {
- difficulty.setSelection(position);
- break;
- }
- }
-
- position = 0;
- for (HashMap<String, ?> hashmap : gravesData) {
- if (hashmap.get("txt").equals(t.grave)) {
- grave.setSelection(position);
- break;
- }
- }
-
- position = 0;
- for (HashMap<String, ?> hashmap : typesData) {
- if (hashmap.get("txt").equals(t.flag)) {
- flag.setSelection(position);
- break;
- }
- }
-
- for (int i = 0; i < Team.maxNumberOfHogs; i++) {
- position = 0;
- for (HashMap<String, ?> hashmap : hatsData) {
- if (hashmap.get("txt").equals(t.hogs.get(i).hat)) {
- hogHat.get(i).setSelection(position);
- }
- }
-
+ voice.setSelection(findPosition((ArrayAdapter<String>) voice.getAdapter(), t.voice));
+ fort.setSelection(findPosition((ArrayAdapter<String>) fort.getAdapter(), t.fort));
+ difficulty.setSelection(findPosition(typesData, getTxtFromDifficulty(t.hogs.get(0).level))); // TODO store actual difficulty int in typesData
+ grave.setSelection(findPosition(gravesData, t.grave));
+ flag.setSelection(findPosition(flagsData, t.flag));
+
+ for (int i = 0; i < Team.HEDGEHOGS_PER_TEAM; i++) {
+ hogHat.get(i).setSelection(findPosition(hatsData, t.hogs.get(i).hat));
hogName.get(i).setText(t.hogs.get(i).name);
}
- //this.fileName = t.file;
+ } catch(NoSuchElementException e) {
+ Toast.makeText(getApplicationContext(), R.string.error_team_attribute_not_found, Toast.LENGTH_LONG).show();
+ finish();
}
}
+ int findPosition(ArrayAdapter<String> adapter, String key) throws NoSuchElementException {
+ int position = adapter.getPosition(key);
+ if(position<0) {
+ throw new NoSuchElementException();
+ }
+ return position;
+ }
+
+ int findPosition(List<? extends Map<String, ?>> data, String txtValue) throws NoSuchElementException {
+ int position = 0;
+ for (Map<String, ?> map : data) {
+ if (map.get("txt").equals(txtValue)) {
+ return position;
+ }
+ position++;
+ }
+ throw new NoSuchElementException();
+ }
private SimpleAdapter.ViewBinder viewBinder = new SimpleAdapter.ViewBinder() {
@@ -413,5 +424,4 @@
}
}
};
-
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamSelectionActivity.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/TeamSelectionActivity.java Sun Aug 12 22:46:23 2012 +0200
@@ -19,23 +19,18 @@
package org.hedgewars.hedgeroid;
-import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
import org.hedgewars.hedgeroid.Datastructures.Team;
-import org.hedgewars.hedgeroid.Datastructures.TeamFile;
import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes;
import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
-import android.os.Parcelable;
-import android.util.Pair;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
@@ -46,7 +41,6 @@
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
-import android.widget.RelativeLayout;
import android.widget.SimpleAdapter;
import android.widget.SimpleAdapter.ViewBinder;
import android.widget.TextView;
@@ -54,10 +48,10 @@
public class TeamSelectionActivity extends Activity implements Runnable{
private static final int ACTIVITY_TEAMCREATION = 0;
- private static volatile List<Pair<TeamFile, TeamIngameAttributes>> activityParams;
- private static volatile List<Pair<TeamFile, TeamIngameAttributes>> activityReturn;
+ public static volatile List<TeamInGame> activityParams;
+ public static volatile List<TeamInGame> activityReturn;
- private ImageButton addTeam, back;
+ private ImageButton addTeam;
private ListView availableTeams, selectedTeams;
private List<HashMap<String, Object>> availableTeamsList, selectedTeamsList;
private TextView txtInfo;
@@ -68,12 +62,10 @@
setContentView(R.layout.team_selector);
addTeam = (ImageButton) findViewById(R.id.btnAdd);
- back = (ImageButton) findViewById(R.id.btnBack);
txtInfo = (TextView) findViewById(R.id.txtInfo);
selectedTeams = (ListView) findViewById(R.id.selectedTeams);
availableTeams = (ListView) findViewById(R.id.availableTeams);
addTeam.setOnClickListener(addTeamClicker);
- back.setOnClickListener(backClicker);
availableTeamsList = new ArrayList<HashMap<String, Object>>();
SimpleAdapter adapter = new SimpleAdapter(this, availableTeamsList, R.layout.team_selection_entry_simple, new String[]{"txt", "img"}, new int[]{R.id.txtName, R.id.imgDifficulty});
@@ -93,23 +85,33 @@
}
public void run(){
- List<HashMap<String, Object>> teamsList = getTeams(this);//teams from xml
- ArrayList<String> teamsStartGame = getIntent().getStringArrayListExtra("selectedTeamNames");
-
- for(HashMap<String, Object> hashmap : teamsList){
+ List<Team> teams = FrontendDataUtils.getTeams(this);
+ List<TeamInGame> existingTeams = activityParams;
+ final List<TeamInGame> newSelectedList = new ArrayList<TeamInGame>();
+ final List<Team> newAvailableList = new ArrayList<Team>();
+
+ for(Team team : teams){
boolean added = false;
- for(String teamName : teamsStartGame){
- if(((Team)hashmap.get("team")).name.equals(teamName)){ // add to available or add to selected
- selectedTeamsList.add(hashmap);
+ for(TeamInGame existingTeam : existingTeams){
+ if(team.name.equals(existingTeam.team.name)){ // add to available or add to selected
+ newSelectedList.add(new TeamInGame(team, existingTeam.ingameAttribs));
added = true;
break;
}
}
- if(!added) availableTeamsList.add(hashmap);
+ if(!added) newAvailableList.add(team);
}
this.runOnUiThread(new Runnable(){
public void run() {
+ availableTeamsList.clear();
+ selectedTeamsList.clear();
+ for(TeamInGame t : newSelectedList) {
+ selectedTeamsList.add(toMap(t));
+ }
+ for(Team t : newAvailableList) {
+ availableTeamsList.add(toMap(t));
+ }
((SimpleAdapter)selectedTeams.getAdapter()).notifyDataSetChanged();
((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged();
}
@@ -145,39 +147,36 @@
* Updates the list view when TeamCreationActivity is shutdown and the user returns to this point
*/
private void updateListViews(){
- unregisterForContextMenu(availableTeams);
- availableTeamsList = getTeams(this);
+ List<Team> teams = FrontendDataUtils.getTeams(this);
+ availableTeamsList.clear();
+ for(Team team : teams) {
+ availableTeamsList.add(toMap(team));
+ }
+
ArrayList<HashMap<String, Object>> toBeRemoved = new ArrayList<HashMap<String, Object>>();
+ ArrayList<HashMap<String, Object>> toBeRemovedFromSelected = new ArrayList<HashMap<String, Object>>();
for(HashMap<String, Object> hashmap : selectedTeamsList){
String name = (String)hashmap.get("txt");
-
+ boolean exists = false;
for(HashMap<String, Object> hash : availableTeamsList){
if(name.equals((String)hash.get("txt"))){
toBeRemoved.add(hash);
+ exists = true;
+ break;
}
}
+ if(!exists) {
+ toBeRemovedFromSelected.add(hashmap);
+ }
}
for(HashMap<String, Object> hash: toBeRemoved) availableTeamsList.remove(hash);
-
- SimpleAdapter adapter = new SimpleAdapter(this, availableTeamsList, R.layout.team_selection_entry, new String[]{"txt", "img"}, new int[]{R.id.txtName, R.id.imgDifficulty});
- availableTeams.setAdapter(adapter);
- registerForContextMenu(availableTeams);
- availableTeams.setOnItemClickListener(availableClicker);
-
-
+ for(HashMap<String, Object> hash: toBeRemovedFromSelected) selectedTeamsList.remove(hash);
+ ((SimpleAdapter)selectedTeams.getAdapter()).notifyDataSetChanged();
+ ((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged();
}
- private void setTeamColor(int position, int color){
- View iv = ((RelativeLayout)selectedTeams.getChildAt(position)).findViewById(R.id.teamCount);
- setTeamColor(iv, color);
- }
- private void setTeamColor(View iv, int color){
- iv.setBackgroundColor(0xFF000000 + color);
- }
-
- private void setTeamHogCount(int position, int count){
- ImageView iv = (ImageView)((RelativeLayout)selectedTeams.getChildAt(position)).findViewById(R.id.teamCount);
- setTeamHogCount(iv, count);
+ private void setTeamColor(View iv, int colorIndex){
+ iv.setBackgroundColor(0xFF000000 + TeamIngameAttributes.TEAM_COLORS[colorIndex]);
}
private void setTeamHogCount(ImageView iv, int count){
@@ -227,13 +226,6 @@
}
};
- private OnClickListener backClicker = new OnClickListener(){
- public void onClick(View v){
- returnTeams();
- finish();
- }
- };
-
private OnItemClickListener availableClicker = new OnItemClickListener(){
public void onItemClick(AdapterView<?> arg0, View arg1, int position,long arg3) {
selectAvailableTeamsItem(position);
@@ -260,19 +252,19 @@
public boolean onContextItemSelected(MenuItem item){
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
int position = menuInfo.position;
- TeamFile teamfile = (TeamFile)availableTeamsList.get(position).get("teamfile");
+ Team team = (Team)availableTeamsList.get(position).get("team");
switch(item.getItemId()){
case 0://select
selectAvailableTeamsItem(position);
return true;
case 1://delete
- teamfile.file.delete();
+ Team.getTeamfileByName(getApplicationContext(), team.name).delete();
availableTeamsList.remove(position);
((SimpleAdapter)availableTeams.getAdapter()).notifyDataSetChanged();
return true;
case 2://edit
Intent i = new Intent(TeamSelectionActivity.this, TeamCreatorActivity.class);
- i.putExtra("teamfile", teamfile.file);
+ i.putExtra(TeamCreatorActivity.PARAMETER_EXISTING_TEAMNAME, team.name);
startActivityForResult(i, ACTIVITY_TEAMCREATION);
return true;
}
@@ -281,14 +273,12 @@
private void selectAvailableTeamsItem(int position){
HashMap<String, Object> hash = (HashMap<String, Object>) availableTeamsList.get(position);
- Team t = (Team)hash.get("team");
int[] illegalcolors = new int[selectedTeamsList.size()];
for(int i = 0; i < selectedTeamsList.size(); i++){
- illegalcolors[i] = ((Team)selectedTeamsList.get(i).get("team")).color;
+ illegalcolors[i] = (Integer)selectedTeamsList.get(i).get("color");
}
- t.setRandomColor(illegalcolors);
- hash.put("color", t.color);
- hash.put("count", t.hogCount);
+ hash.put("color", TeamIngameAttributes.randomColorIndex(illegalcolors));
+ hash.put("count", TeamIngameAttributes.DEFAULT_HOG_COUNT);
selectedTeamsList.add(hash);
availableTeamsList.remove(position);
@@ -298,47 +288,36 @@
txtInfo.setText(String.format(getResources().getString(R.string.teams_info_template), selectedTeamsList.size()));
}
- private void returnTeams(){
- int teamsCount = selectedTeamsList.size();
- Intent i = new Intent();
- Parcelable[] teams = new Parcelable[teamsCount];
- for(int x = 0 ; x < teamsCount; x++){
- teams[x] = (Team)selectedTeamsList.get(x).get("team");
+ private void returnTeams() {
+ List<TeamInGame> result = new ArrayList<TeamInGame>();
+ for(HashMap<String, Object> item : selectedTeamsList) {
+ result.add(new TeamInGame((Team)item.get("team"), new TeamIngameAttributes("Player", (Integer)item.get("color"), (Integer)item.get("count"), false)));
}
- i.putExtra("teams", teams);
- setResult(Activity.RESULT_OK, i);
-
- }
-
- private static List<HashMap<String, Object>> getTeams(Context c){
- List<HashMap<String, Object>> ret = new ArrayList<HashMap<String, Object>>();
- List<TeamFile> teamfiles = FrontendDataUtils.getTeamFiles(c);
- for(TeamFile tf : teamfiles) {
- ret.add(teamfileToMap(tf));
- }
- return ret;
+ activityReturn = result;
+ setResult(Activity.RESULT_OK);
}
private static final int[] botlevelDrawables = new int[] {
R.drawable.human, R.drawable.bot5, R.drawable.bot4, R.drawable.bot3, R.drawable.bot2, R.drawable.bot1
};
-
- private static HashMap<String, Object> teamfileToMap(TeamFile tf){
- HashMap<String, Object> hashmap = new HashMap<String, Object>();
- Team t = tf.team;
- hashmap.put("team", t);
- hashmap.put("teamfile", tf);
- hashmap.put("txt", t.name);
- hashmap.put("color", t.color);
- hashmap.put("count", t.hogCount);
+ private static HashMap<String, Object> toMap(Team t) {
+ HashMap<String, Object> map = new HashMap<String, Object>();
+ map.put("team", t);
+ map.put("txt", t.name);
int botlevel = t.hogs.get(0).level;
if(botlevel<0 || botlevel>=botlevelDrawables.length) {
- hashmap.put("img", R.drawable.bot1);
+ map.put("img", R.drawable.bot1);
} else {
- hashmap.put("img", botlevelDrawables[botlevel]);
- }
- return hashmap;
- return null;
+ map.put("img", botlevelDrawables[botlevel]);
+ }
+ return map;
+ }
+
+ private static HashMap<String, Object> toMap(TeamInGame t) {
+ HashMap<String, Object> map = toMap(t.team);
+ map.put("color", t.ingameAttribs.colorIndex);
+ map.put("count", t.ingameAttribs.hogCount);
+ return map;
}
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java Sun Aug 12 22:46:23 2012 +0200
@@ -54,7 +54,7 @@
* get the path to which we should download all the data files
* @param c context
* @return The directory
- * @throws FileNotFoundException if external storage is not avaliable at the moment
+ * @throws FileNotFoundException if external storage is not available at the moment
*/
public static File getCachePath(Context c) throws FileNotFoundException {
File cachePath = null;
@@ -105,37 +105,19 @@
}
/**
- * Get files from dirName, dir name is relative to {@link getDownloadPath}
- * @param dirName
- * @param c context
- * @return string of files
- */
- public static String[] getFileNamesFromRelativeDir(Context c, String dirName){
- String prefix = getDataPath(c);
- File f = new File(prefix + dirName);
-
- if(f.exists() && f.isDirectory()) return f.list();
- else{
-
- Log.e("Utils::", "Couldn't find dir: " + dirName);
- return new String[0];
- }
- }
-
- /**
* Return a File array with all the files from dirName
* @param c
* @param dirName
* @return
+ * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dirName" does not exist
*/
- public static File[] getFilesFromRelativeDir(Context c, String dirName){
- String prefix = getDataPath(c);
- File f = new File(prefix + dirName);
+ public static File[] getFilesFromRelativeDir(Context c, String dirName) throws FileNotFoundException {
+ File f = new File(getDataPathFile(c), dirName);
- if(f.exists() && f.isDirectory()) return f.listFiles();
- else {
- Log.e("Utils::", "Dir not found: " + dirName);
- return new File[0];
+ if(f.isDirectory()) {
+ return f.listFiles();
+ } else {
+ throw new FileNotFoundException("Directory "+dirName+" does not exist.");
}
}
@@ -161,8 +143,9 @@
* @param path
* @param fileSuffix
* @return
+ * @throws FileNotFoundException If the sdcard is not available or the subdirectory "path" does not exist
*/
- public static List<String> getDirsWithFileSuffix(Context c, String path, String fileSuffix){
+ public static List<String> getDirsWithFileSuffix(Context c, String path, String fileSuffix) throws FileNotFoundException{
File[] files = getFilesFromRelativeDir(c,path);
ArrayList<String> ret = new ArrayList<String>();
@@ -174,16 +157,13 @@
/**
* Get all files from directory dir which have the given suffix
- * @param c
- * @param dir
- * @param suffix
- * @param removeSuffix
- * @return
+ * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dir" does not exist
*/
- public static ArrayList<String> getFilesFromDirWithSuffix(Context c, String dir, String suffix, boolean removeSuffix){
- String[] files = Utils.getFileNamesFromRelativeDir(c, dir);
+ public static ArrayList<String> getFileNamesFromDirWithSuffix(Context c, String dir, String suffix, boolean removeSuffix) throws FileNotFoundException{
+ File[] files = Utils.getFilesFromRelativeDir(c, dir);
ArrayList<String> ret = new ArrayList<String>();
- for(String s : files){
+ for(File file : files){
+ String s = file.getName();
if(s.endsWith(suffix)){
if(removeSuffix) ret.add(s.substring(0, s.length()-suffix.length()));
else ret.add(s);
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java Sun Aug 12 22:46:23 2012 +0200
@@ -1,4 +1,5 @@
package org.hedgewars.hedgeroid.frontlib;
+import java.io.UnsupportedEncodingException;
import java.nio.Buffer;
import java.util.ArrayList;
import java.util.HashMap;
@@ -6,15 +7,17 @@
import java.util.Map;
import org.hedgewars.hedgeroid.Datastructures.Hog;
+import org.hedgewars.hedgeroid.Datastructures.MapRecipe;
import org.hedgewars.hedgeroid.Datastructures.MetaScheme;
import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Mod;
import org.hedgewars.hedgeroid.Datastructures.MetaScheme.Setting;
+import org.hedgewars.hedgeroid.Datastructures.GameConfig;
import org.hedgewars.hedgeroid.Datastructures.RoomlistRoom;
import org.hedgewars.hedgeroid.Datastructures.Scheme;
import org.hedgewars.hedgeroid.Datastructures.Team;
import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes;
-import org.hedgewars.hedgeroid.EngineProtocol.GameConfig;
+import org.hedgewars.hedgeroid.Datastructures.Weaponset;
import com.sun.jna.Callback;
import com.sun.jna.Library;
@@ -23,56 +26,126 @@
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.Structure;
+import com.sun.jna.ptr.IntByReference;
+/**
+ * Here is an introduction to the most important aspects of the JNA code.
+ *
+ * This interface permits access to the Hedgewars frontend library (frontlib)
+ * from Java. Each function directly contained in the Frontlib interface
+ * represents a mapped C function. The Structure classes (ending in -Struct) are
+ * mappings of C structs, and the PointerType classes (ending in -Ptr) represent
+ * pointers to structs.
+ *
+ * Quick notes for USING these classes from outside this package:
+ *
+ * Usage should be fairly straightforward, but there are a few surprising
+ * gotchas. First, when you implement callbacks, YOU are responsible for
+ * ensuring that the callback objects are not garbage-collected while they might
+ * still be called! So make sure you keep them in member variables or similar,
+ * because Java will not know if there are still native references to them.
+ *
+ * When using Frontlib from outside its package, you only interact with structs
+ * via the PointerType classes. They allow you to get at the data of the struct
+ * with a function called deref(), which creates a plain normal Java object
+ * representing the data (e.g. SchemePtr.deref() will give you a Scheme object).
+ *
+ * Remember that you usually have to destroy structs that you receive from the
+ * library, because they are owned by the native code, not Java. For example, if
+ * you obtain a {@link MetaschemePtr} metaPtr using flib_metascheme_from_ini,
+ * you have to call flib_metascheme_release(metaPtr) after you are done using
+ * it. The recommended pattern for most cases is to call deref() on the pointer
+ * to get a Java object (that you can keep as long as you like), and then
+ * immediately destroy the struct if it needs destroying. To find out whether
+ * and how the struct needs to be destroyed, see the library's documentation of
+ * the function that you got the struct from.
+ *
+ * To pass new structs to the library, you can use the static createJavaOwned()
+ * function in each PointerType, which creates a new struct from the Java object
+ * you provide, and returns a pointer to that struct that you can pass to
+ * library functions. This new structure's memory is owned and managed by Java
+ * code, so do not destroy it with frontlib functions!
+ *
+ * There is a slight mismatch between the data model for the game setup. The
+ * frontlib supports setting initial health and weaponset per-hog, because the
+ * engine allows for that, but currently neither the networking protocol nor the
+ * PC frontend support this feature, so the Android version does not take
+ * advantage of it either and treats both as per-game settings. The initial
+ * health is contained in the game scheme, the weaponset is explicitly part of
+ * the GameConfig. When converting GameConfig to a native flib_gamesetup, both
+ * are automatically copied to all hogs in the game, and for the reverse
+ * conversion the weaponset of the first hog of the first team is used as the
+ * GameConfig weaponset. This means that GameConfig.weaponset will be null if
+ * there are no teams in the game.
+ *
+ * When starting a network game, you only need to query the GameSetupPtr from
+ * the netconn and use it to create the gameconn - this is preferable to using
+ * your own recreation of the game setup, because that way the same piece of
+ * code is used to determine the game setup on all platforms.
+ *
+ * The "context" parameter of the callbacks is never needed here because JNA
+ * generates function code for each callback object. Don't worry about it, just
+ * pass null for context and ignore the context parameter in the callbacks.
+ *
+ * Finally, the library functions are documented in the actual library, not
+ * here, so check the docs there to find out what exactly each function does!
+ *
+ * Notes about the structure of this class (for the next one who has to touch
+ * this...):
+ *
+ * Java/C interop is quite fiddly and error-prone, so as long as things work,
+ * try to stick to the established patterns.
+ *
+ * Structure types should always be hidden from the outside world, because they
+ * can be misused too easily. For example, if you get a Structure from the
+ * library, change a String value in there and pass it back, JNA will re-write
+ * that string using Java-owned memory without freeing the old native-owned
+ * string, which causes a memory leak and possibly a double-free or other Bad
+ * Things (tm). To avoid problems like this, Structure types are only used
+ * internally, to map existing structures to Java types (without modifying them)
+ * or to create brand-new, Java-owned structures. Both operations are exposed to
+ * the outside through the PointerType classes corresponding to the structures
+ * in question.
+ *
+ * Since all of the struct mapping happens in Java, it is never checked against
+ * the actual struct declarations in the library. That means strange things can
+ * start happening at runtime if the frontlib structs are modified without
+ * changing the mappings here to match. This also applies to the function
+ * signatures: JNA checks whether the functions actually exist when loading the
+ * library, but it has no way of knowing whether the signatures are correct. If
+ * the signatures here deviate from those in the frontlib, you might get stack
+ * corruption.
+ *
+ * In order to check at least the function signatures, take a look at the file
+ * extra/jnacontrol.c in the frontlib sources. You can validate whether the
+ * function signatures are still correct by copy-pasting them into jnaControl.c
+ * and compiling it against the frontlib headers. The typedefs and #defines in
+ * that file will make the compiler see the Java method signatures as C function
+ * declarations. Since the same functions are already declared in the frontlib
+ * headers, the compiler will give you errors if the signatures don't match.
+ */
public interface Frontlib extends Library {
static final int NATIVE_INT_SIZE = 4;
static final int NATIVE_BOOL_SIZE = 1;
- static final int NETCONN_STATE_CONNECTING = 0;
- static final int NETCONN_STATE_LOBBY = 1;
- static final int NETCONN_STATE_ROOM = 2;
- static final int NETCONN_STATE_INGAME = 3;
- static final int NETCONN_STATE_DISCONNECTED = 10;
-
- static final int NETCONN_DISCONNECT_NORMAL = 0;
- static final int NETCONN_DISCONNECT_SERVER_TOO_OLD = 1;
- static final int NETCONN_DISCONNECT_AUTH_FAILED = 2;
- static final int NETCONN_DISCONNECT_CONNLOST = 3;
- static final int NETCONN_DISCONNECT_INTERNAL_ERROR = 100;
-
- static final int NETCONN_ROOMLEAVE_ABANDONED = 0;
- static final int NETCONN_ROOMLEAVE_KICKED = 1;
-
- static final int NETCONN_MSG_TYPE_PLAYERINFO = 0;
- static final int NETCONN_MSG_TYPE_SERVERMESSAGE = 1;
- static final int NETCONN_MSG_TYPE_WARNING = 2;
- static final int NETCONN_MSG_TYPE_ERROR = 3;
-
- static final int NETCONN_MAPCHANGE_FULL = 0;
- static final int NETCONN_MAPCHANGE_MAP = 1;
- static final int NETCONN_MAPCHANGE_MAPGEN = 2;
- static final int NETCONN_MAPCHANGE_DRAWNMAP = 3;
- static final int NETCONN_MAPCHANGE_MAZE_SIZE = 4;
- static final int NETCONN_MAPCHANGE_TEMPLATE = 5;
- static final int NETCONN_MAPCHANGE_THEME = 6;
- static final int NETCONN_MAPCHANGE_SEED = 7;
-
- static final int GAME_END_FINISHED = 0;
- static final int GAME_END_INTERRUPTED = 1;
- static final int GAME_END_HALTED = 2;
- static final int GAME_END_ERROR = 3;
-
- static final int HEDGEHOGS_PER_TEAM = 8;
-
public static class NetconnPtr extends PointerType { }
public static class MapconnPtr extends PointerType { }
public static class GameconnPtr extends PointerType { }
- public static class MetaschemePtr extends PointerType { }
+
+ // TODO avoid code duplication in the pointer types
+ public static class MetaschemePtr extends PointerType {
+ public MetaScheme deref() {
+ return deref(getPointer());
+ }
+
+ public static MetaScheme deref(Pointer p) {
+ MetaschemeStruct struct = new MetaschemeStruct(p);
+ struct.read();
+ return struct.toMetaScheme();
+ }
+ }
public static class RoomArrayPtr extends PointerType {
- /**
- * Returns the (native-owned) rooms in this list
- */
public RoomlistRoom[] getRooms(int count) {
Pointer ptr = getPointer();
if(ptr == null) {
@@ -88,65 +161,123 @@
}
public static class RoomPtr extends PointerType {
- public RoomPtr() { super(); }
- public RoomPtr(Pointer ptr) { super(ptr); }
-
public RoomlistRoom deref() {
return deref(getPointer());
}
public static RoomlistRoom deref(Pointer p) {
- RoomStruct r = new RoomStruct(p);
- r.read();
- return new RoomlistRoom(r.name, r.map, r.scheme, r.weapons, r.owner, r.playerCount, r.teamCount, r.inProgress);
+ RoomStruct struct = new RoomStruct(p);
+ struct.read();
+ return struct.toRoomlistRoom();
}
}
public static class TeamPtr extends PointerType {
+ private TeamStruct javaOwnedInstance;
+
public TeamInGame deref() {
- return deref(getPointer());
+ TeamStruct struct = new TeamStruct(getPointer());
+ struct.read();
+ return struct.toTeamInGame();
}
- public static TeamInGame deref(Pointer p) {
- TeamStruct ts = new TeamStruct(p);
- ts.read();
- List<Hog> hogs = new ArrayList<Hog>();
- for(int i=0; i<ts.hogs.length; i++) {
- HogStruct hog = ts.hogs[i];
- hogs.add(new Hog(hog.name, hog.hat, hog.difficulty));
- }
- Team team = new Team(ts.name, ts.grave, ts.flag, ts.voicepack, ts.fort, hogs);
- TeamIngameAttributes attrs = new TeamIngameAttributes(ts.ownerName, ts.colorIndex, ts.hogsInGame, ts.remoteDriven);
- return new TeamInGame(team, attrs);
- }
-
public static TeamPtr createJavaOwned(Team t) {
return createJavaOwned(new TeamInGame(t, null));
}
public static TeamPtr createJavaOwned(TeamInGame ingameTeam) {
- TeamStruct ts = TeamStruct.from(ingameTeam.team, ingameTeam.ingameAttribs);
- ts.write();
TeamPtr result = new TeamPtr();
- result.setPointer(ts.getPointer());
+ result.javaOwnedInstance = new TeamStruct();
+ result.javaOwnedInstance.fillFrom(ingameTeam.team, ingameTeam.ingameAttribs);
+ result.javaOwnedInstance.autoWrite();
+ result.setPointer(result.javaOwnedInstance.getPointer());
+ return result;
+ }
+ }
+
+ public static class WeaponsetPtr extends PointerType {
+ private WeaponsetStruct javaOwnedInstance;
+
+ public Weaponset deref() {
+ WeaponsetStruct struct = new WeaponsetStruct(getPointer());
+ struct.read();
+ return struct.toWeaponset();
+ }
+
+ public static WeaponsetPtr createJavaOwned(Weaponset weaponset) {
+ WeaponsetPtr result = new WeaponsetPtr();
+ result.javaOwnedInstance = new WeaponsetStruct();
+ result.javaOwnedInstance.fillFrom(weaponset);
+ result.javaOwnedInstance.autoWrite();
+ result.setPointer(result.javaOwnedInstance.getPointer());
return result;
}
}
- public static class WeaponsetPtr extends PointerType { }
- public static class MapRecipePtr extends PointerType { }
- public static class SchemePtr extends PointerType { }
+ public static class WeaponsetListPtr extends PointerType {
+ private WeaponsetListStruct javaOwnedInstance;
+
+ public List<Weaponset> deref() {
+ WeaponsetListStruct struct = new WeaponsetListStruct(getPointer());
+ struct.read();
+ return struct.toWeaponsetList();
+ }
+
+ public static WeaponsetListPtr createJavaOwned(List<Weaponset> list) {
+ WeaponsetListPtr result = new WeaponsetListPtr();
+ result.javaOwnedInstance = new WeaponsetListStruct();
+ result.javaOwnedInstance.fillFrom(list);
+ result.javaOwnedInstance.autoWrite();
+ result.setPointer(result.javaOwnedInstance.getPointer());
+ return result;
+ }
+ }
+
+ public static class MapRecipePtr extends PointerType {
+ private MapRecipeStruct javaOwnedInstance;
+
+ public MapRecipe deref() {
+ MapRecipeStruct struct = new MapRecipeStruct(getPointer());
+ struct.read();
+ return struct.toMapRecipe();
+ }
+
+ public static MapRecipePtr createJavaOwned(MapRecipe recipe) {
+ MapRecipePtr result = new MapRecipePtr();
+ result.javaOwnedInstance = new MapRecipeStruct();
+ result.javaOwnedInstance.fillFrom(recipe);
+ result.javaOwnedInstance.autoWrite();
+ result.setPointer(result.javaOwnedInstance.getPointer());
+ return result;
+ }
+ }
+
+ public static class SchemePtr extends PointerType {
+ private SchemeStruct javaOwnedInstance;
+
+ public Scheme deref() {
+ SchemeStruct struct = new SchemeStruct(getPointer());
+ struct.read();
+ return struct.toScheme();
+ }
+
+ public static SchemePtr createJavaOwned(Scheme scheme) {
+ SchemePtr result = new SchemePtr();
+ result.javaOwnedInstance = new SchemeStruct();
+ result.javaOwnedInstance.fillFrom(scheme);
+ result.javaOwnedInstance.autoWrite();
+ result.setPointer(result.javaOwnedInstance.getPointer());
+ return result;
+ }
+ }
+
public static class SchemelistPtr extends PointerType {
private SchemelistStruct javaOwnedInstance;
public List<Scheme> deref() {
- return deref(getPointer());
- }
-
- public static List<Scheme> deref(Pointer p) {
- SchemelistStruct sls = new SchemelistStruct(p);
- sls.read();
- return sls.toSchemeList();
+ SchemelistStruct struct = new SchemelistStruct(getPointer());
+ struct.read();
+ return struct.toSchemeList();
}
public static SchemelistPtr createJavaOwned(List<Scheme> schemes) {
@@ -160,11 +291,20 @@
}
public static class GameSetupPtr extends PointerType {
+ private GameSetupStruct javaOwnedInstance;
+
+ public GameConfig deref() {
+ GameSetupStruct struct = new GameSetupStruct(getPointer());
+ struct.read();
+ return struct.toGameConfig();
+ }
+
public static GameSetupPtr createJavaOwned(GameConfig conf) {
- GameSetupStruct gss = GameSetupStruct.from(conf);
- gss.write();
GameSetupPtr result = new GameSetupPtr();
- result.setPointer(gss.getPointer());
+ result.javaOwnedInstance = new GameSetupStruct();
+ result.javaOwnedInstance.fillFrom(conf);
+ result.javaOwnedInstance.autoWrite();
+ result.setPointer(result.javaOwnedInstance.getPointer());
return result;
}
}
@@ -177,14 +317,14 @@
public HogStruct() { super(); setFieldOrder(FIELD_ORDER); }
public HogStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
- public static HogStruct from(Hog hog) {
- HogStruct hs = new HogStruct();
- hs.difficulty = hog.level;
- hs.hat = hog.hat;
- hs.name = hog.name;
- // TODO weaponset
- // TODO initialHealth
- return hs;
+ public void fillFrom(Hog hog) {
+ difficulty = hog.level;
+ hat = hog.hat;
+ name = hog.name;
+ }
+
+ public Hog toHog() {
+ return new Hog(name, hat, difficulty);
}
public String name;
@@ -198,7 +338,7 @@
public int difficulty;
public int initialHealth;
- public WeaponsetPtr weaponset;
+ public WeaponsetStruct.ByRef weaponset;
}
static class TeamStruct extends Structure {
@@ -209,32 +349,55 @@
public TeamStruct() { super(); setFieldOrder(FIELD_ORDER); }
public TeamStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
- public static TeamStruct from(Team team, TeamIngameAttributes attrs) {
- TeamStruct ts = new TeamStruct();
+ public void fillFrom(Team team, TeamIngameAttributes attrs) {
if(team != null) {
- ts.name = team.name;
- ts.grave = team.grave;
- ts.flag = team.flag;
- ts.voicepack = team.voice;
- ts.fort = team.fort;
- if(team.hogs.size() != HEDGEHOGS_PER_TEAM) {
+ name = team.name;
+ grave = team.grave;
+ flag = team.flag;
+ voicepack = team.voice;
+ fort = team.fort;
+ if(team.hogs.size() != Team.HEDGEHOGS_PER_TEAM) {
throw new IllegalArgumentException();
}
- for(int i=0; i<ts.hogs.length; i++) {
- ts.hogs[i] = HogStruct.from(team.hogs.get(i));
+ for(int i=0; i<hogs.length; i++) {
+ hogs[i] = new HogStruct();
+ hogs[i].fillFrom(team.hogs.get(i));
}
}
if(attrs != null) {
- ts.hogsInGame = attrs.hogCount;
- ts.ownerName = attrs.ownerName;
- ts.colorIndex = attrs.colorIndex;
- ts.remoteDriven = attrs.remoteDriven;
+ hogsInGame = attrs.hogCount;
+ ownerName = attrs.ownerName;
+ colorIndex = attrs.colorIndex;
+ remoteDriven = attrs.remoteDriven;
}
- return ts;
+ }
+
+ public void fillFrom(TeamInGame team, WeaponsetStruct.ByRef weaponset, int initialHealth) {
+ fillFrom(team.team, team.ingameAttribs);
+ for(int i=0; i<hogs.length; i++) {
+ hogs[i].initialHealth = initialHealth;
+ hogs[i].weaponset = weaponset;
+ }
}
- public HogStruct[] hogs = new HogStruct[HEDGEHOGS_PER_TEAM];
+ public Team toTeam() {
+ List<Hog> hogList = new ArrayList<Hog>();
+ for(int i=0; i<hogs.length; i++) {
+ hogList.add(hogs[i].toHog());
+ }
+ return new Team(name, grave, flag, voicepack, fort, hogList);
+ }
+
+ public TeamIngameAttributes toTeamIngameAttributes() {
+ return new TeamIngameAttributes(ownerName, colorIndex, hogsInGame, remoteDriven);
+ }
+
+ public TeamInGame toTeamInGame() {
+ return new TeamInGame(toTeam(), toTeamIngameAttributes());
+ }
+
+ public HogStruct[] hogs = new HogStruct[Team.HEDGEHOGS_PER_TEAM];
public String name;
public String grave;
public String fort;
@@ -254,6 +417,106 @@
public String ownerName;
}
+ static class WeaponsetStruct extends Structure {
+ public static class ByVal extends WeaponsetStruct implements Structure.ByValue {}
+ public static class ByRef extends WeaponsetStruct implements Structure.ByReference {}
+ private static String[] FIELD_ORDER = new String[] {"_referenceCount", "loadout", "crateprob", "crateammo", "delay", "name"};
+
+ public WeaponsetStruct() { super(); setFieldOrder(FIELD_ORDER); }
+ public WeaponsetStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+
+ public void fillFrom(Weaponset weaponset) {
+ _referenceCount = 0;
+ fillWeaponInfo(loadout, weaponset.loadout);
+ fillWeaponInfo(crateprob, weaponset.crateProb);
+ fillWeaponInfo(crateammo, weaponset.crateAmmo);
+ fillWeaponInfo(delay, weaponset.delay);
+ name = weaponset.name;
+ }
+
+ private static void fillWeaponInfo(byte[] array, String str) {
+ for(int i=0; i<array.length-1; i++) {
+ array[i] = (byte) (i<str.length() ? str.charAt(i) : '0');
+ }
+ array[array.length-1] = (byte)0;
+ }
+
+ public Weaponset toWeaponset() {
+ return new Weaponset(name, weaponInfoToString(loadout), weaponInfoToString(crateprob), weaponInfoToString(crateammo), weaponInfoToString(delay));
+ }
+
+ private static String weaponInfoToString(byte[] array) {
+ try {
+ return new String(array, 0, array.length-1, "ASCII");
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError();
+ }
+ }
+
+ public int _referenceCount;
+ public byte[] loadout = new byte[Weaponset.WEAPONS_COUNT+1];
+ public byte[] crateprob = new byte[Weaponset.WEAPONS_COUNT+1];
+ public byte[] crateammo = new byte[Weaponset.WEAPONS_COUNT+1];
+ public byte[] delay = new byte[Weaponset.WEAPONS_COUNT+1];
+ public String name;
+ }
+
+ /**
+ * Represents a flib_weaponset*, for use as part of a flib_weaponset**
+ */
+ static class WeaponsetPointerByReference extends Structure implements Structure.ByReference {
+ private static String[] FIELD_ORDER = new String[] {"weaponset"};
+
+ public WeaponsetPointerByReference() { super(); setFieldOrder(FIELD_ORDER); }
+ public WeaponsetPointerByReference(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+
+ public WeaponsetStruct.ByRef weaponset;
+ }
+
+ static class WeaponsetListStruct extends Structure {
+ public static class ByVal extends WeaponsetListStruct implements Structure.ByValue {}
+ public static class ByRef extends WeaponsetListStruct implements Structure.ByReference {}
+ private static String[] FIELD_ORDER = new String[] {"weaponsetCount", "weaponsets"};
+
+ public WeaponsetListStruct() { super(); setFieldOrder(FIELD_ORDER); }
+ public WeaponsetListStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+
+ public void fillFrom(List<Weaponset> list) {
+ weaponsetCount = list.size();
+ weaponsets = new WeaponsetPointerByReference();
+ Structure[] structs = weaponsets.toArray(weaponsetCount);
+
+ for(int i=0; i<weaponsetCount; i++) {
+ WeaponsetPointerByReference pstruct = (WeaponsetPointerByReference)structs[i];
+ pstruct.weaponset = new WeaponsetStruct.ByRef();
+ pstruct.weaponset.fillFrom(list.get(i));
+ }
+ }
+
+ /**
+ * Only use on native-owned structs!
+ * Calling this method on a Java-owned struct could cause garbage collection of referenced
+ * structures.
+ */
+ public List<Weaponset> toWeaponsetList() {
+ if(weaponsetCount<=0) {
+ return new ArrayList<Weaponset>();
+ } else {
+ List<Weaponset> list = new ArrayList<Weaponset>(weaponsetCount);
+ Structure[] structs = weaponsets.toArray(weaponsetCount);
+
+ for(int i=0; i<weaponsetCount; i++) {
+ WeaponsetPointerByReference pstruct = (WeaponsetPointerByReference)structs[i];
+ list.add(pstruct.weaponset.toWeaponset());
+ }
+ return list;
+ }
+ }
+
+ public int weaponsetCount;
+ public WeaponsetPointerByReference weaponsets;
+ }
+
static class RoomStruct extends Structure {
public static class ByVal extends RoomStruct implements Structure.ByValue {}
public static class ByRef extends RoomStruct implements Structure.ByReference {}
@@ -261,6 +524,10 @@
public RoomStruct() { super(); setFieldOrder(FIELD_ORDER); }
public RoomStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+
+ public RoomlistRoom toRoomlistRoom() {
+ return new RoomlistRoom(name, map, scheme, weapons, owner, playerCount, teamCount, inProgress);
+ }
public boolean inProgress;
public String name;
@@ -275,18 +542,44 @@
static class MapRecipeStruct extends Structure {
public static class ByVal extends MapRecipeStruct implements Structure.ByValue {}
public static class ByRef extends MapRecipeStruct implements Structure.ByReference {}
- private static String[] FIELD_ORDER = new String[] {"_referenceCount", "mapgen", "name", "seed", "theme", "drawData", "drawDataSize", "templateFilter", "mazeSize"};
+ private static String[] FIELD_ORDER = new String[] {"mapgen", "name", "seed", "theme", "drawData", "drawDataSize", "templateFilter", "mazeSize"};
public MapRecipeStruct() { super(); setFieldOrder(FIELD_ORDER); }
public MapRecipeStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
- public int _referenceCount;
+ public void fillFrom(MapRecipe map) {
+ mapgen = map.mapgen;
+ name = map.name;
+ seed = map.seed;
+ theme = map.theme;
+ byte[] buf = map.getDrawData();
+ if(buf != null) {
+ drawData = new Memory(buf.length);
+ drawData.write(0, buf, 0, buf.length);
+ drawDataSize = new NativeLong(buf.length);
+ } else {
+ drawData = null;
+ drawDataSize = new NativeLong(0);
+ }
+ templateFilter = map.templateFilter;
+ mazeSize = map.mazeSize;
+ }
+
+ public MapRecipe toMapRecipe() {
+ byte[] buf = null;
+ if(drawData != null && drawDataSize.intValue()>0) {
+ buf = new byte[drawDataSize.intValue()];
+ drawData.read(0, buf, 0, drawDataSize.intValue());
+ }
+ return new MapRecipe(mapgen, templateFilter, mazeSize, name, seed, theme, buf);
+ }
+
public int mapgen;
public String name;
public String seed;
public String theme;
public Pointer drawData;
- public int drawDataSize;
+ public NativeLong drawDataSize;
public int templateFilter;
public int mazeSize;
}
@@ -408,7 +701,7 @@
static class SchemeStruct extends Structure {
public static class ByVal extends SchemeStruct implements Structure.ByValue {}
public static class ByRef extends SchemeStruct implements Structure.ByReference {}
- private static String[] FIELD_ORDER = new String[] {"_referenceCount", "meta", "name", "settings", "mod"};
+ private static String[] FIELD_ORDER = new String[] {"meta", "name", "settings", "mod"};
public SchemeStruct() { super(); setFieldOrder(FIELD_ORDER); }
public SchemeStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
@@ -442,7 +735,6 @@
return new Scheme(metaScheme, name, settingsMap, modsMap);
}
- public int _referenceCount;
public MetaschemeStruct.ByRef meta;
public String name;
public Pointer settings;
@@ -469,6 +761,18 @@
public SchemelistStruct() { super(); setFieldOrder(FIELD_ORDER); }
public SchemelistStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+ public void fillFrom(List<Scheme> schemeList) {
+ schemeCount = schemeList.size();
+ schemes = new SchemePointerByReference();
+ Structure[] schemePtrStructs = schemes.toArray(schemeCount);
+
+ for(int i=0; i<this.schemeCount; i++) {
+ SchemePointerByReference spbr = (SchemePointerByReference)schemePtrStructs[i];
+ spbr.scheme = new SchemeStruct.ByRef();
+ spbr.scheme.fillFrom(schemeList.get(i));
+ }
+ }
+
/**
* Only use on native-owned structs!
* Calling this method on a Java-owned struct could cause garbage collection of referenced
@@ -490,32 +794,60 @@
}
}
- public void fillFrom(List<Scheme> schemeList) {
- schemeCount = schemeList.size();
- schemes = new SchemePointerByReference();
- Structure[] schemePtrStructs = schemes.toArray(schemeCount);
-
- for(int i=0; i<this.schemeCount; i++) {
- SchemePointerByReference spbr = (SchemePointerByReference)schemePtrStructs[i];
- spbr.scheme = new SchemeStruct.ByRef();
- spbr.scheme.fillFrom(schemeList.get(i));
- }
- }
-
public int schemeCount;
public SchemePointerByReference schemes;
}
+ /**
+ * Represents a flib_team*, for use as part of a flib_team**
+ */
+ static class TeamPointerByReference extends Structure implements Structure.ByReference {
+ private static String[] FIELD_ORDER = new String[] {"team"};
+
+ public TeamPointerByReference() { super(); setFieldOrder(FIELD_ORDER); }
+ public TeamPointerByReference(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+
+ public TeamStruct.ByRef team;
+ }
+
static class TeamlistStruct extends Structure {
public static class ByVal extends TeamlistStruct implements Structure.ByValue {}
public static class ByRef extends TeamlistStruct implements Structure.ByReference {}
+
private static String[] FIELD_ORDER = new String[] {"teamCount", "teams"};
public TeamlistStruct() { super(); setFieldOrder(FIELD_ORDER); }
public TeamlistStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
+ public void fillFrom(List<TeamInGame> teamList, WeaponsetStruct.ByRef weaponset, int initialHealth) {
+ teamCount = teamList.size();
+ teams = new TeamPointerByReference();
+ Structure[] teamPtrStructs = teams.toArray(teamCount);
+
+ for(int i=0; i<this.teamCount; i++) {
+ TeamPointerByReference tpbr = (TeamPointerByReference)teamPtrStructs[i];
+ tpbr.team = new TeamStruct.ByRef();
+ tpbr.team.fillFrom(teamList.get(i), weaponset, initialHealth);
+ }
+ }
+
+ public List<TeamInGame> toTeamInGameList() {
+ if(teamCount<=0) {
+ return new ArrayList<TeamInGame>();
+ } else {
+ List<TeamInGame> result = new ArrayList<TeamInGame>(teamCount);
+ Structure[] structs = teams.toArray(teamCount);
+
+ for(int i=0; i<teamCount; i++) {
+ TeamPointerByReference struct = (TeamPointerByReference)structs[i];
+ result.add(struct.team.toTeamInGame());
+ }
+ return result;
+ }
+ }
+
public int teamCount;
- public Pointer teams;
+ public TeamPointerByReference teams;
}
static class GameSetupStruct extends Structure {
@@ -526,16 +858,35 @@
public GameSetupStruct() { super(); setFieldOrder(FIELD_ORDER); }
public GameSetupStruct(Pointer ptr) { super(ptr); setFieldOrder(FIELD_ORDER); }
- public static GameSetupStruct from(GameConfig conf) {
- GameSetupStruct gss = new GameSetupStruct();
- gss.gamescheme = new SchemeStruct.ByRef();
- gss.gamescheme.fillFrom(conf.scheme);
- gss.map = new MapRecipeStruct.ByRef();
- // TODO gss.map.fillFrom(conf.map, conf.seed, conf.theme);
- gss.script = conf.style;
- gss.teamlist = new TeamlistStruct.ByRef();
- // TODO gss.teamlist.fillFrom(conf.teams, conf.weapon);
- return gss;
+ public void fillFrom(GameConfig conf) {
+ script = conf.style;
+ gamescheme = new SchemeStruct.ByRef();
+ gamescheme.fillFrom(conf.scheme);
+ map = new MapRecipeStruct.ByRef();
+ map.fillFrom(conf.map);
+
+ /*
+ * At this point we deviate from the usual copying pattern because the frontlib
+ * expects per-hog weapons and initial health, but the UI models them as per-
+ * game, so we extract them from the config here and pass them on to be included
+ * in each hog.
+ */
+ WeaponsetStruct.ByRef wss = new WeaponsetStruct.ByRef();
+ wss.fillFrom(conf.weaponset);
+ int initialHealth = conf.scheme.getHealth();
+
+ teamlist = new TeamlistStruct.ByRef();
+ teamlist.fillFrom(conf.teams, wss, initialHealth);
+ }
+
+ public GameConfig toGameConfig() {
+ Scheme scheme = gamescheme != null ? gamescheme.toScheme() : null;
+ MapRecipe mapRecipe = map != null ? map.toMapRecipe() : null;
+ List<TeamInGame> teams = teamlist != null ? teamlist.toTeamInGameList() : null;
+
+ WeaponsetStruct weaponsetStruct = teamlist != null && teamlist.teamCount>0 ? teamlist.teams.team.hogs[0].weaponset : null;
+ Weaponset weaponset = weaponsetStruct != null ? weaponsetStruct.toWeaponset() : null;
+ return new GameConfig(script, scheme, mapRecipe, teams, weaponset);
}
public String script;
@@ -544,6 +895,12 @@
public TeamlistStruct.ByRef teamlist;
}
+ /*
+ * Callback interfaces. The context parameter is never needed here and
+ * should always be ignored. Be sure to keep a reference to each callback
+ * for as long as they might be called by native code, to avoid premature
+ * garbage collection.
+ */
public static interface VoidCallback extends Callback {
void callback(Pointer context);
}
@@ -620,15 +977,50 @@
void callback(int level, String logMessage);
}
+ // frontlib.h
int flib_init();
void flib_quit();
+ // hwconsts.h
+ int flib_get_teamcolor(int colorIndex);
+ int flib_get_teamcolor_count();
+ int flib_get_hedgehogs_per_team();
+ int flib_get_weapons_count();
+
+ // net/netconn.h
+ static final int NETCONN_STATE_CONNECTING = 0;
+ static final int NETCONN_STATE_LOBBY = 1;
+ static final int NETCONN_STATE_ROOM = 2;
+ static final int NETCONN_STATE_DISCONNECTED = 10;
+
+ static final int NETCONN_DISCONNECT_NORMAL = 0;
+ static final int NETCONN_DISCONNECT_SERVER_TOO_OLD = 1;
+ static final int NETCONN_DISCONNECT_AUTH_FAILED = 2;
+ static final int NETCONN_DISCONNECT_CONNLOST = 3;
+ static final int NETCONN_DISCONNECT_INTERNAL_ERROR = 100;
+
+ static final int NETCONN_ROOMLEAVE_ABANDONED = 0;
+ static final int NETCONN_ROOMLEAVE_KICKED = 1;
+
+ static final int NETCONN_MSG_TYPE_PLAYERINFO = 0;
+ static final int NETCONN_MSG_TYPE_SERVERMESSAGE = 1;
+ static final int NETCONN_MSG_TYPE_WARNING = 2;
+ static final int NETCONN_MSG_TYPE_ERROR = 3;
+
+ static final int NETCONN_MAPCHANGE_FULL = 0;
+ static final int NETCONN_MAPCHANGE_MAP = 1;
+ static final int NETCONN_MAPCHANGE_MAPGEN = 2;
+ static final int NETCONN_MAPCHANGE_DRAWNMAP = 3;
+ static final int NETCONN_MAPCHANGE_MAZE_SIZE = 4;
+ static final int NETCONN_MAPCHANGE_TEMPLATE = 5;
+ static final int NETCONN_MAPCHANGE_THEME = 6;
+ static final int NETCONN_MAPCHANGE_SEED = 7;
+
NetconnPtr flib_netconn_create(String playerName, MetaschemePtr meta, String dataDirPath, String host, int port);
void flib_netconn_destroy(NetconnPtr conn);
void flib_netconn_tick(NetconnPtr conn);
boolean flib_netconn_is_chief(NetconnPtr conn);
- boolean flib_netconn_is_in_room_context(NetconnPtr conn);
String flib_netconn_get_playername(NetconnPtr conn);
GameSetupPtr flib_netconn_create_gamesetup(NetconnPtr conn);
int flib_netconn_send_quit(NetconnPtr conn, String quitmsg);
@@ -644,7 +1036,7 @@
int flib_netconn_send_toggleReady(NetconnPtr conn);
int flib_netconn_send_addTeam(NetconnPtr conn, TeamPtr team);
int flib_netconn_send_removeTeam(NetconnPtr conn, String teamname);
- int flib_netconn_send_engineMessage(NetconnPtr conn, Buffer message, NativeLong size); // TODO check if NativeLong==size_t
+ int flib_netconn_send_engineMessage(NetconnPtr conn, Buffer message, NativeLong size);
int flib_netconn_send_teamHogCount(NetconnPtr conn, String teamname, int hogcount);
int flib_netconn_send_teamColor(NetconnPtr conn, String teamname, int colorIndex);
int flib_netconn_send_weaponset(NetconnPtr conn, WeaponsetPtr weaponset);
@@ -702,7 +1094,12 @@
void flib_netconn_onAdminAccess(NetconnPtr conn, VoidCallback callback, Pointer context);
void flib_netconn_onServerVar(NetconnPtr conn, StrStrCallback callback, Pointer context);
- // Gameconn
+ // ipc/gameconn.h
+ static final int GAME_END_FINISHED = 0;
+ static final int GAME_END_INTERRUPTED = 1;
+ static final int GAME_END_HALTED = 2;
+ static final int GAME_END_ERROR = 3;
+
GameconnPtr flib_gameconn_create(String playerName, GameSetupPtr setup, boolean netgame);
GameconnPtr flib_gameconn_create_playdemo(Buffer demo, NativeLong size);
GameconnPtr flib_gameconn_create_loadgame(String playerName, Buffer save, NativeLong size);
@@ -715,6 +1112,7 @@
int flib_gameconn_send_enginemsg(GameconnPtr conn, Buffer data, NativeLong len);
int flib_gameconn_send_textmsg(GameconnPtr conn, int msgtype, String msg);
int flib_gameconn_send_chatmsg(GameconnPtr conn, String playername, String msg);
+ int flib_gameconn_send_quit(GameconnPtr conn);
void flib_gameconn_onConnect(GameconnPtr conn, VoidCallback callback, Pointer context);
void flib_gameconn_onDisconnect(GameconnPtr conn, IntCallback callback, Pointer context);
@@ -723,7 +1121,7 @@
void flib_gameconn_onGameRecorded(GameconnPtr conn, BytesBoolCallback callback, Pointer context);
void flib_gameconn_onEngineMessage(GameconnPtr conn, BytesCallback callback, Pointer context);
- // MapConn
+ // ipc/mapconn.h
MapconnPtr flib_mapconn_create(MapRecipePtr mapdesc);
void flib_mapconn_destroy(MapconnPtr conn);
int flib_mapconn_getport(MapconnPtr conn);
@@ -731,11 +1129,7 @@
void flib_mapconn_onFailure(MapconnPtr conn, StrCallback callback, Pointer context);
void flib_mapconn_tick(MapconnPtr conn);
- // GameSetup
- void flib_gamesetup_destroy(GameSetupPtr gamesetup);
- GameSetupPtr flib_gamesetup_copy(GameSetupPtr gamesetup);
-
- // MapRecipe
+ // model/map.h
public static final int MAPGEN_REGULAR = 0;
public static final int MAPGEN_MAZE = 1;
public static final int MAPGEN_DRAWN = 2;
@@ -754,33 +1148,28 @@
public static final int MAZE_SIZE_SMALL_ISLANDS = 3;
public static final int MAZE_SIZE_MEDIUM_ISLANDS = 4;
public static final int MAZE_SIZE_LARGE_ISLANDS = 5;
-
- MapRecipePtr flib_map_create_regular(String seed, String theme, int templateFilter);
- MapRecipePtr flib_map_create_maze(String seed, String theme, int mazeSize);
- MapRecipePtr flib_map_create_named(String seed, String name);
- MapRecipePtr flib_map_create_drawn(String seed, String theme, Buffer drawData, NativeLong drawDataSize);
- MapRecipePtr flib_map_copy(MapRecipePtr map);
- MapRecipePtr flib_map_retain(MapRecipePtr map);
- void flib_map_release(MapRecipePtr map);
-
- // Metascheme
+
+ // model/scheme.h
MetaschemePtr flib_metascheme_from_ini(String filename);
MetaschemePtr flib_metascheme_retain(MetaschemePtr metainfo);
void flib_metascheme_release(MetaschemePtr metainfo);
- // Scheme lists
+ // model/schemelist.h
SchemelistPtr flib_schemelist_from_ini(MetaschemePtr meta, String filename);
int flib_schemelist_to_ini(String filename, SchemelistPtr list);
void flib_schemelist_destroy(SchemelistPtr list);
- // Team
- void flib_team_destroy(TeamPtr team);
+ // model/team.h
TeamPtr flib_team_from_ini(String filename);
int flib_team_to_ini(String filename, TeamPtr team);
- void flib_team_set_weaponset(TeamPtr team, WeaponsetPtr set);
- void flib_team_set_health(TeamPtr team, int health);
+ void flib_team_destroy(TeamPtr team);
- // Logging
+ // model/weapon.h
+ WeaponsetListPtr flib_weaponsetlist_from_ini(String filename);
+ int flib_weaponsetlist_to_ini(String filename, WeaponsetListPtr weaponsets);
+ void flib_weaponsetlist_destroy(WeaponsetListPtr list);
+
+ // util/logging.h
public static final int FLIB_LOGLEVEL_ALL = -100;
public static final int FLIB_LOGLEVEL_DEBUG = -1;
public static final int FLIB_LOGLEVEL_INFO = 0;
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Netplay.java Sun Aug 12 22:46:23 2012 +0200
@@ -2,10 +2,13 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.util.Map;
+import java.util.TreeMap;
import org.hedgewars.hedgeroid.R;
import org.hedgewars.hedgeroid.Utils;
import org.hedgewars.hedgeroid.Datastructures.RoomlistRoom;
+import org.hedgewars.hedgeroid.Datastructures.Team;
import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes;
import org.hedgewars.hedgeroid.frontlib.Flib;
@@ -82,6 +85,7 @@
public final MessageLog lobbyChatlog;
public final MessageLog roomChatlog;
public final Teamlist roomTeamlist = new Teamlist();
+ private final Map<String, Team> roomRequestedTeams = new TreeMap<String, Team>();
public Netplay(Context appContext) {
this.appContext = appContext;
@@ -133,6 +137,13 @@
public void sendCreateRoom(String name) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_CREATE_ROOM, name); }
public void sendLeaveRoom(String message) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_LEAVE_ROOM, message); }
public void sendKick(String player) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_KICK, player); }
+ public void sendAddTeam(Team newTeam) {
+ roomRequestedTeams.put(newTeam.name, newTeam);
+ sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_ADD_TEAM, newTeam);
+ }
+ public void sendRemoveTeam(String teamName) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_REMOVE_TEAM, teamName); }
+ public void sendTeamColorIndex(String teamName, int colorIndex) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_TEAM_COLOR_INDEX, colorIndex, teamName); }
+ public void sendTeamHogCount(String teamName, int hogCount) { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_SEND_TEAM_HOG_COUNT, hogCount, teamName); }
public void disconnect() { sendToNet(ThreadedNetConnection.ToNetHandler.MSG_DISCONNECT, "User Quit"); }
@@ -202,18 +213,17 @@
}
private boolean sendToNet(int what) {
- if(connection != null) {
- Handler handler = connection.toNetHandler;
- return handler.sendMessage(handler.obtainMessage(what));
- } else {
- return false;
- }
+ return sendToNet(what, 0, null);
}
private boolean sendToNet(int what, Object obj) {
+ return sendToNet(what, 0, obj);
+ }
+
+ private boolean sendToNet(int what, int arg1, Object obj) {
if(connection != null) {
Handler handler = connection.toNetHandler;
- return handler.sendMessage(handler.obtainMessage(what, obj));
+ return handler.sendMessage(handler.obtainMessage(what, arg1, 0, obj));
} else {
return false;
}
@@ -338,6 +348,7 @@
roomChatlog.clear();
roomPlayerlist.clear();
roomTeamlist.clear();
+ roomRequestedTeams.clear();
changeState(State.ROOM);
chief = (Boolean)msg.obj;
Intent intent = new Intent(ACTION_ENTERED_ROOM_FROM_LOBBY);
@@ -358,7 +369,14 @@
break;
}
case MSG_TEAM_ADDED: {
- roomTeamlist.addTeamWithNewId((TeamInGame)msg.obj);
+ Team newTeam = (Team)msg.obj;
+ TeamIngameAttributes attrs = new TeamIngameAttributes(playerName, roomTeamlist.getUnusedOrRandomColorIndex(), TeamIngameAttributes.DEFAULT_HOG_COUNT, false);
+ TeamInGame tig = new TeamInGame(newTeam, attrs);
+ roomTeamlist.addTeamWithNewId(tig);
+ if(chief) {
+ sendTeamColorIndex(newTeam.name, attrs.colorIndex);
+ sendTeamHogCount(newTeam.name, attrs.hogCount);
+ }
break;
}
case MSG_TEAM_DELETED: {
@@ -366,7 +384,18 @@
break;
}
case MSG_TEAM_ACCEPTED: {
- // TODO depends: adding teams
+ Team requestedTeam = roomRequestedTeams.remove(msg.obj);
+ if(requestedTeam!=null) {
+ TeamIngameAttributes attrs = new TeamIngameAttributes(playerName, roomTeamlist.getUnusedOrRandomColorIndex(), TeamIngameAttributes.DEFAULT_HOG_COUNT, false);
+ TeamInGame tig = new TeamInGame(requestedTeam, attrs);
+ roomTeamlist.addTeamWithNewId(tig);
+ if(chief) {
+ sendTeamColorIndex(requestedTeam.name, attrs.colorIndex);
+ sendTeamHogCount(requestedTeam.name, attrs.hogCount);
+ }
+ } else {
+ Log.e("Netplay", "Got accepted message for team that was never requested.");
+ }
break;
}
case MSG_TEAM_COLOR_CHANGED: {
@@ -412,7 +441,7 @@
private final Context appContext;
private final FromNetHandler fromNetHandler;
private final TickHandler tickHandler;
-
+
/**
* conn can only be null while connecting (the first thing in the thread), and directly after disconnecting,
* in the same message (the looper is shut down on disconnect, so there will be no messages after that).
@@ -589,7 +618,7 @@
private final TeamCallback teamAddedCb = new TeamCallback() {
public void callback(Pointer context, TeamPtr team) {
- sendFromNet(FromNetHandler.MSG_TEAM_ADDED, team.deref());
+ sendFromNet(FromNetHandler.MSG_TEAM_ADDED, team.deref().team);
}
};
@@ -674,8 +703,11 @@
public static final int MSG_SEND_CREATE_ROOM = 8;
public static final int MSG_SEND_LEAVE_ROOM = 9;
public static final int MSG_SEND_KICK = 10;
-
- public static final int MSG_DISCONNECT = 11;
+ public static final int MSG_SEND_ADD_TEAM = 11;
+ public static final int MSG_SEND_REMOVE_TEAM = 12;
+ public static final int MSG_DISCONNECT = 13;
+ public static final int MSG_SEND_TEAM_COLOR_INDEX = 14;
+ public static final int MSG_SEND_TEAM_HOG_COUNT = 15;
public ToNetHandler(Looper looper) {
super(looper);
@@ -697,7 +729,7 @@
break;
}
case MSG_SEND_ROOMLIST_REQUEST: {
- FLIB.flib_netconn_send_request_roomlist(conn); // TODO restrict to lobby state?
+ FLIB.flib_netconn_send_request_roomlist(conn);
break;
}
case MSG_SEND_PLAYER_INFO_REQUEST: {
@@ -732,11 +764,33 @@
FLIB.flib_netconn_send_kick(conn, (String)msg.obj);
break;
}
+ case MSG_SEND_ADD_TEAM: {
+ FLIB.flib_netconn_send_addTeam(conn, TeamPtr.createJavaOwned((Team)msg.obj));
+ break;
+ }
+ case MSG_SEND_REMOVE_TEAM: {
+ if(FLIB.flib_netconn_send_removeTeam(conn, (String)msg.obj)==0) {
+ sendFromNet(FromNetHandler.MSG_TEAM_DELETED, msg.obj);
+ }
+ break;
+ }
case MSG_DISCONNECT: {
FLIB.flib_netconn_send_quit(conn, (String)msg.obj);
shutdown(false, "User quit");
break;
}
+ case MSG_SEND_TEAM_COLOR_INDEX: {
+ if(FLIB.flib_netconn_send_teamColor(conn, (String)msg.obj, msg.arg1)==0) {
+ sendFromNet(FromNetHandler.MSG_TEAM_COLOR_CHANGED, msg.arg1, msg.obj);
+ }
+ break;
+ }
+ case MSG_SEND_TEAM_HOG_COUNT: {
+ if(FLIB.flib_netconn_send_teamHogCount(conn, (String)msg.obj, msg.arg1)==0) {
+ sendFromNet(FromNetHandler.MSG_HOG_COUNT_CHANGED, msg.arg1, msg.obj);
+ }
+ break;
+ }
default: {
Log.e("ToNetHandler", "Unknown message type: "+msg.what);
break;
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomActivity.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomActivity.java Sun Aug 12 22:46:23 2012 +0200
@@ -1,6 +1,7 @@
package org.hedgewars.hedgeroid.netplay;
import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.Datastructures.Team;
import org.hedgewars.hedgeroid.netplay.Netplay.State;
import org.hedgewars.hedgeroid.netplay.NetplayStateFragment.NetplayStateListener;
@@ -10,7 +11,7 @@
import android.widget.TabHost;
import android.widget.Toast;
-public class RoomActivity extends FragmentActivity implements NetplayStateListener {
+public class RoomActivity extends FragmentActivity implements NetplayStateListener, TeamAddDialog.Listener {
private TabHost tabHost;
private Netplay netplay;
@@ -72,4 +73,8 @@
throw new IllegalStateException("Unknown connection state: "+newState);
}
}
+
+ public void onTeamAddDialogSubmitted(Team newTeam) {
+ netplay.sendAddTeam(newTeam);
+ }
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomListAdapter.java Sun Aug 12 22:46:23 2012 +0200
@@ -39,7 +39,7 @@
private static CharSequence formatExtra(Resources res, RoomlistRoom room) {
String ownermsg = res.getString(R.string.roomlist_owner, room.owner);
- String mapmsg = res.getString(R.string.roomlist_map, RoomlistRoom.formatMapName(res, room.map));
+ String mapmsg = res.getString(R.string.roomlist_map, room.formatMapName(res));
String scheme = room.scheme.equals(room.weapons) ? room.scheme : room.scheme + " / " + room.weapons;
String schememsg = res.getString(R.string.roomlist_scheme, scheme);
return ownermsg + ". " + mapmsg + ", " + schememsg;
@@ -74,7 +74,7 @@
teamCountView.setText(String.valueOf(room.teamCount));
}
ownerView.setText(room.owner);
- mapView.setText(RoomlistRoom.formatMapName(context.getResources(), room.map));
+ mapView.setText(room.formatMapName(context.getResources()));
schemeView.setText(room.scheme);
weaponView.setText(room.weapons);
} else {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TeamAddDialog.java Sun Aug 12 22:46:23 2012 +0200
@@ -0,0 +1,92 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.Datastructures.FrontendDataUtils;
+import org.hedgewars.hedgeroid.Datastructures.Team;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+
+public class TeamAddDialog extends DialogFragment {
+ private static final String STATE_TEAMS_ALREADY_IN_GAME = "teamAlreadyInGame";
+ private ArrayList<String> teamsAlreadyInGame;
+ private List<Team> availableTeams;
+ private Listener listener;
+
+ public static interface Listener {
+ void onTeamAddDialogSubmitted(Team newTeam);
+ }
+
+ public TeamAddDialog() {
+ // Only for reflection-based instantiation by the framework
+ }
+
+ TeamAddDialog(Collection<String> teamsAlreadyInGame) {
+ this.teamsAlreadyInGame = new ArrayList<String>(teamsAlreadyInGame);
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ try {
+ listener = (Listener) activity;
+ } catch(ClassCastException e) {
+ throw new ClassCastException("Activity " + activity + " must implement TeamAddDialog.Listener to use TeamAddDialog.");
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ listener = null;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if(savedInstanceState != null) {
+ teamsAlreadyInGame = savedInstanceState.getStringArrayList(STATE_TEAMS_ALREADY_IN_GAME);
+ }
+ availableTeams = new ArrayList<Team>();
+ List<Team> teams = FrontendDataUtils.getTeams(getActivity());
+ for(Team team : teams) {
+ if(!teamsAlreadyInGame.contains(team.name)) {
+ availableTeams.add(team);
+ }
+ }
+ Collections.sort(availableTeams, Team.NAME_ORDER);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.dialog_addteam_title);
+ builder.setIcon(R.drawable.human);
+ String[] teamNames = new String[availableTeams.size()];
+ for(int i=0; i<availableTeams.size(); i++) {
+ teamNames[i] = availableTeams.get(i).name;
+ }
+ builder.setItems(teamNames, new OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ listener.onTeamAddDialogSubmitted(availableTeams.get(which));
+ }
+ });
+ return builder.create();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putStringArrayList(STATE_TEAMS_ALREADY_IN_GAME, teamsAlreadyInGame);
+ }
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Teamlist.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Teamlist.java Sun Aug 12 22:46:23 2012 +0200
@@ -1,6 +1,9 @@
package org.hedgewars.hedgeroid.netplay;
+import java.util.Collection;
+
import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+import org.hedgewars.hedgeroid.Datastructures.TeamIngameAttributes;
import android.util.Pair;
@@ -10,4 +13,15 @@
public void addTeamWithNewId(TeamInGame team) {
put(team.team.name, Pair.create(team, nextId++));
}
+
+ public int getUnusedOrRandomColorIndex() {
+ Collection<Pair<TeamInGame, Long>> teams = getMap().values();
+ int[] illegalColors = new int[teams.size()];
+ int i=0;
+ for(Pair<TeamInGame, Long> item : teams) {
+ illegalColors[i] = item.first.ingameAttribs.colorIndex;
+ i++;
+ }
+ return TeamIngameAttributes.randomColorIndex(illegalColors);
+ }
}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TeamlistFragment.java Sun Aug 12 22:37:57 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TeamlistFragment.java Sun Aug 12 22:46:23 2012 +0200
@@ -1,17 +1,31 @@
package org.hedgewars.hedgeroid.netplay;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
import org.hedgewars.hedgeroid.R;
+import org.hedgewars.hedgeroid.Datastructures.Team;
+import org.hedgewars.hedgeroid.Datastructures.TeamInGame;
+import android.database.DataSetObserver;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView;
+import android.widget.Button;
-public class TeamlistFragment extends ListFragment {
+public class TeamlistFragment extends ListFragment implements OnItemClickListener {
private Netplay netplay;
private TeamlistAdapter adapter;
-
+ private Button addTeamButton;
+ private DataSetObserver teamlistObserver;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -24,12 +38,48 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- return inflater.inflate(R.layout.fragment_teamlist, container, false);
+ View v = inflater.inflate(R.layout.fragment_teamlist, container, false);
+ addTeamButton = (Button)v.findViewById(R.id.addTeamButton);
+ addTeamButton.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ new TeamAddDialog(getCurrentTeamNames()).show(getFragmentManager(), "team_add_dialog");
+ }
+ });
+
+ teamlistObserver = new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ addTeamButton.setEnabled(netplay.roomTeamlist.getMap().size() < Team.maxNumberOfTeams);
+ }
+ };
+ netplay.roomTeamlist.registerObserver(teamlistObserver);
+ teamlistObserver.onChanged();
+
+ return v;
}
@Override
public void onDestroy() {
super.onDestroy();
adapter.invalidate();
+ netplay.roomTeamlist.unregisterObserver(teamlistObserver);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ getListView().setOnItemClickListener(this);
+ }
+
+ private Collection<String> getCurrentTeamNames() {
+ List<String> names = new ArrayList<String>();
+ for(Pair<TeamInGame, Long> teamWithId : netplay.roomTeamlist.getMap().values()) {
+ names.add(teamWithId.first.team.name);
+ }
+ return names;
+ }
+
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ netplay.sendRemoveTeam(adapter.getItem(position).team.name);
}
}