diff -r d70a5b0d1190 -r 0481bd74267c project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/frontlib/Frontlib.java --- 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 hogs = new ArrayList(); - for(int i=0; i deref() { + WeaponsetListStruct struct = new WeaponsetListStruct(getPointer()); + struct.read(); + return struct.toWeaponsetList(); + } + + public static WeaponsetListPtr createJavaOwned(List 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 deref() { - return deref(getPointer()); - } - - public static List 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 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 hogList = new ArrayList(); + for(int i=0; i list) { + weaponsetCount = list.size(); + weaponsets = new WeaponsetPointerByReference(); + Structure[] structs = weaponsets.toArray(weaponsetCount); + + for(int i=0; i toWeaponsetList() { + if(weaponsetCount<=0) { + return new ArrayList(); + } else { + List list = new ArrayList(weaponsetCount); + Structure[] structs = weaponsets.toArray(weaponsetCount); + + for(int i=0; i0) { + 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 schemeList) { + schemeCount = schemeList.size(); + schemes = new SchemePointerByReference(); + Structure[] schemePtrStructs = schemes.toArray(schemeCount); + + for(int i=0; i schemeList) { - schemeCount = schemeList.size(); - schemes = new SchemePointerByReference(); - Structure[] schemePtrStructs = schemes.toArray(schemeCount); - - for(int i=0; i teamList, WeaponsetStruct.ByRef weaponset, int initialHealth) { + teamCount = teamList.size(); + teams = new TeamPointerByReference(); + Structure[] teamPtrStructs = teams.toArray(teamCount); + + for(int i=0; i toTeamInGameList() { + if(teamCount<=0) { + return new ArrayList(); + } else { + List result = new ArrayList(teamCount); + Structure[] structs = teams.toArray(teamCount); + + for(int i=0; i 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;