diff --git a/generator/src/main/java/bwmirror/generator/c/Bind.java b/generator/src/main/java/bwmirror/generator/c/Bind.java index 33c9a90..e81bdd7 100644 --- a/generator/src/main/java/bwmirror/generator/c/Bind.java +++ b/generator/src/main/java/bwmirror/generator/c/Bind.java @@ -30,165 +30,152 @@ public class Bind { this.context = context; } - private void implementConnectionRoutine() { - out.println("\t\t\t\tprintln(\"Waiting...\");\n" + - "while ( !Broodwar->isInGame() )\n" + - " {\n" + - " BWAPI::BWAPIClient.update();\n" + - " if (!BWAPI::BWAPIClient.isConnected())\n" + - " {\n" + - " println(\"Reconnecting...\");\n" + - " reconnect();\n" + - " }\n" + - " }"); - } - - - private void implementGameStart() { - out.println("println(\"Connecting to Broodwar...\");\n" + - "\t\treconnect();\n" + - "\t\tprintln(\"Connection successful, starting match...\");\n" + - "\n" + - "\t\tcls = env->GetObjectClass(obj);\n" + - "\t\tjclass gamecls = env->FindClass(\"L" + context.getPackageName() + "/Game;\");\n" + - "\t\tjclass unitCls = env->FindClass(\"L" + context.getPackageName() + "/Unit;\");\n" + - "\t\tjclass playerCls = env->FindClass(\"L" + context.getPackageName() + "/Player;\");\n" + - "\t\tjclass posCls = env->FindClass(\"L" + context.getPackageName() + "/Position;\");\n" + - "\t\tjobject moduleObj = env->GetObjectField(obj, env->GetFieldID(cls, \"module\", \"L" + context.getPackageName() + "/AIModule;\"));\n" + - "\t\tjclass moduleCls = env->GetObjectClass(moduleObj);\n" + - "\t\tenv->SetObjectField(obj, env->GetFieldID(cls, \"game\", \"L" + context.getPackageName() + "/Game;\"), " + - "env->CallStaticObjectMethod(gamecls, env->GetStaticMethodID(gamecls, \"get\", \"(J)L" + context.getPackageName() + "/Game;\"), (long)BroodwarPtr));\n" + - "\n" + - "\t\tjmethodID updateMethodID = env->GetMethodID(env->GetObjectClass(obj), \"update\", \"()V\");"); - - out.println("\t\tjmethodID matchStartCallback = env->GetMethodID(moduleCls, \"onStart\", \"()V\");\n" + - "\t\tjmethodID matchEndCallback = env->GetMethodID(moduleCls, \"onEnd\", \"(Z)V\");\n" + - "\t\tjmethodID matchFrameCallback = env->GetMethodID(moduleCls, \"onFrame\", \"()V\");\n" + - "\t\tjmethodID sendTextCallback = env->GetMethodID(moduleCls, \"onSendText\", \"(Ljava/lang/String;)V\");\n" + - "\t\tjmethodID receiveTextCallback = env->GetMethodID(moduleCls, \"onReceiveText\", \"(L" + context.getPackageName() + "/Player;Ljava/lang/String;)V\");\n" + - "\t\tjmethodID playerLeftCallback = env->GetMethodID(moduleCls, \"onPlayerLeft\", \"(L" + context.getPackageName() + "/Player;)V\");\n" + - "\t\tjmethodID nukeDetectCallback = env->GetMethodID(moduleCls, \"onNukeDetect\", \"(L" + context.getPackageName() + "/Position;)V\");\n" + - "\t\tjmethodID unitDiscoverCallback = env->GetMethodID(moduleCls, \"onUnitDiscover\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID unitEvadeCallback = env->GetMethodID(moduleCls, \"onUnitEvade\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID unitShowCallback = env->GetMethodID(moduleCls, \"onUnitShow\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID unitHideCallback = env->GetMethodID(moduleCls, \"onUnitHide\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID unitCreateCallback = env->GetMethodID(moduleCls, \"onUnitCreate\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID unitDestroyCallback = env->GetMethodID(moduleCls, \"onUnitDestroy\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID unitMorphCallback = env->GetMethodID(moduleCls, \"onUnitMorph\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID unitRenegadeCallback = env->GetMethodID(moduleCls, \"onUnitRenegade\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID saveGameCallback = env->GetMethodID(moduleCls, \"onSaveGame\", \"(Ljava/lang/String;)V\");\n" + - "\t\tjmethodID unitCompleteCallback = env->GetMethodID(moduleCls, \"onUnitComplete\", \"(L" + context.getPackageName() + "/Unit;)V\");\n" + - "\t\tjmethodID playerDroppedCallback = env->GetMethodID(moduleCls, \"onPlayerDropped\", \"(L" + context.getPackageName() + "/Player;)V\");"); - - out.println("\t\twhile (true) {\n"); - implementConnectionRoutine(); - out.println("\t\t\tprintln(\"Game ready!!!\");\n" + - "\n" + - "\t\t\twhile (Broodwar->isInGame()) {\n" + - "\t\t\t\t\n" + - "\t\t\t\tenv->CallVoidMethod(obj, updateMethodID);\n"); - out.println("\n" + - "\t\t\t\tfor(std::list::const_iterator it = Broodwar->getEvents().begin(); it!=Broodwar->getEvents().end(); it++)\n" + - "\t\t\t\t {\n" + - "\t\t\t\t\t switch (it->getType()) {\n" + - - "\t\t\t\t\t\t case EventType::MatchStart:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, matchStartCallback);\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::MatchEnd:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, matchEndCallback, it->isWinner());\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::MatchFrame:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, matchFrameCallback);\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::SendText:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, sendTextCallback, env->NewStringUTF(it->getText().c_str()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::ReceiveText:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, receiveTextCallback, env->CallStaticObjectMethod(playerCls, env->GetStaticMethodID(playerCls, \"get\", \"(J)L" + context.getPackageName() + "/Player;\"), (jlong)it->getPlayer()), env->NewStringUTF(it->getText().c_str()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::PlayerLeft:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, playerLeftCallback, env->CallStaticObjectMethod(playerCls, env->GetStaticMethodID(playerCls, \"get\", \"(J)L" + context.getPackageName() + "/Player;\"), (jlong)it->getPlayer()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::NukeDetect:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, nukeDetectCallback, env->NewObject(posCls, env->GetMethodID(posCls,\"\", \"(II)V\"), it->getPosition().x, it->getPosition().y));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitDiscover:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitDiscoverCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitEvade:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitEvadeCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitShow:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitShowCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitHide:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitHideCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitCreate:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitCreateCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitDestroy:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitDestroyCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitMorph:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitMorphCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitRenegade:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitRenegadeCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::SaveGame:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, saveGameCallback, env->NewStringUTF(it->getText().c_str()));\n" + - "\t\t\t\t\t\t break;\n" + - "\t\t\t\t\t\t case EventType::UnitComplete:\n" + - "\t\t\t\t\t\t\t env->CallVoidMethod(moduleObj, unitCompleteCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)L" + context.getPackageName() + "/Unit;\"), (jlong)it->getUnit()));\n" + - "\t\t\t\t\t\t break;\n" + - "\n" + - "\t\t\t\t\t }\n" + - "\t\t\t\t }"); - out.println( - "\t\t\t\tBWAPIClient.update();\n" + - "\t\t\t\tif (!BWAPI::BWAPIClient.isConnected()) {\n" + - "\t\t\t\t\t\tprintln(\"Reconnecting...\");\n" + - "\t\t\t\t\t\treconnect();\n" + - "\t\t\t\t}\n" + - "\t\t\t}\n" + - "println(\"Match ended.\");" + - "\t\t}"); - } - private void implementHelpers() { - out.println("void reconnect()\n" + - "{\n" + - "\twhile (!BWAPIClient.connect()) {\n" + - " std::this_thread::sleep_for(std::chrono::milliseconds{ 1000 });\n" + - " }\n" + - "}\n" + - "\n" + - "\n"); - out.println( "void flushPrint(const char * text){\n" + - "\tprintf(text);\n" + - "\tfflush(stdout); \n" + - "}\n" + - "\n" + - "void println(const char * text){\n" + - "\tprintf(text);\n" + - "\tflushPrint(\"\\n\");\n" + - "}\n"); + " printf(text);\n" + + " fflush(stdout); \n" + + "}\n" + + "\n" + + "void println(const char * text){\n" + + " printf(text);\n" + + " flushPrint(\"\\n\");\n" + + "}\n" + ); + out.println(); } - private void implementMirrorInit(List declarationList) { - implementHelpers(); - out.println("JNIEXPORT void JNICALL Java_" + context.getPackageName() + "_Mirror_startGame(JNIEnv * env, jobject obj){"); + private void implementMirror_initTables(List declarationList) { + out.println("JNIEXPORT void JNICALL Java_" + context.getPackageName() + "_Mirror_initTables(JNIEnv * env, jclass jclz){"); + out.println(" println(\"Initializing constants tables\");"); implementVariablesBind(declarationList); - implementGameStart(); out.println("}"); out.println(); } + private void implementMirror_getInternalGame() { + out.println( + "JNIEXPORT jobject JNICALL Java_" + context.getPackageName() + "_Mirror_getInternalGame(JNIEnv * env, jobject obj){\n" + + " jclass gamecls = env->FindClass(\"Lbwapi/Game;\");\n" + + " jmethodID getMethodID = env->GetStaticMethodID(gamecls, \"get\", \"(J)Lbwapi/Game;\");\n" + + " return env->CallStaticObjectMethod(gamecls, getMethodID, (long)BroodwarPtr);\n" + + "}\n" + ); + out.println(); + } + + private void implementMirror_processGameEvents() { + out.println( + "JNIEXPORT void JNICALL Java_" + context.getPackageName() + "_Mirror_processGameEvents(JNIEnv * env, jobject obj){\n" + + " jclass cls = env->GetObjectClass(obj);\n" + + " jobject moduleObj = env->GetObjectField(obj, env->GetFieldID(cls, \"module\", \"Lbwapi/AIModule;\"));\n" + + " jclass moduleCls = env->GetObjectClass(moduleObj);\n" + + "\n" + + " jclass unitCls = env->FindClass(\"Lbwapi/Unit;\");\n" + + " jclass playerCls = env->FindClass(\"Lbwapi/Player;\");\n" + + " jclass posCls = env->FindClass(\"Lbwapi/Position;\");\n" + + "\n" + + " jmethodID matchStartCallback = env->GetMethodID(moduleCls, \"onStart\", \"()V\");\n" + + " jmethodID matchEndCallback = env->GetMethodID(moduleCls, \"onEnd\", \"(Z)V\");\n" + + " jmethodID matchFrameCallback = env->GetMethodID(moduleCls, \"onFrame\", \"()V\");\n" + + " jmethodID sendTextCallback = env->GetMethodID(moduleCls, \"onSendText\", \"(Ljava/lang/String;)V\");\n" + + " jmethodID receiveTextCallback = env->GetMethodID(moduleCls, \"onReceiveText\", \"(Lbwapi/Player;Ljava/lang/String;)V\");\n" + + " jmethodID playerLeftCallback = env->GetMethodID(moduleCls, \"onPlayerLeft\", \"(Lbwapi/Player;)V\");\n" + + " jmethodID nukeDetectCallback = env->GetMethodID(moduleCls, \"onNukeDetect\", \"(Lbwapi/Position;)V\");\n" + + " jmethodID unitDiscoverCallback = env->GetMethodID(moduleCls, \"onUnitDiscover\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID unitEvadeCallback = env->GetMethodID(moduleCls, \"onUnitEvade\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID unitShowCallback = env->GetMethodID(moduleCls, \"onUnitShow\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID unitHideCallback = env->GetMethodID(moduleCls, \"onUnitHide\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID unitCreateCallback = env->GetMethodID(moduleCls, \"onUnitCreate\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID unitDestroyCallback = env->GetMethodID(moduleCls, \"onUnitDestroy\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID unitMorphCallback = env->GetMethodID(moduleCls, \"onUnitMorph\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID unitRenegadeCallback = env->GetMethodID(moduleCls, \"onUnitRenegade\", \"(Lbwapi/Unit;)V\");\n" + + " jmethodID saveGameCallback = env->GetMethodID(moduleCls, \"onSaveGame\", \"(Ljava/lang/String;)V\");\n" + + " jmethodID unitCompleteCallback = env->GetMethodID(moduleCls, \"onUnitComplete\", \"(Lbwapi/Unit;)V\");\n" + + "\n" + + " for (std::list::const_iterator it = Broodwar->getEvents().begin(); it != Broodwar->getEvents().end(); it++)\n" + + " {\n" + + " switch (it->getType()) {\n" + + " case EventType::MatchStart:\n" + + " env->CallVoidMethod(moduleObj, matchStartCallback);\n" + + " break;\n" + + " case EventType::MatchEnd:\n" + + " env->CallVoidMethod(moduleObj, matchEndCallback, it->isWinner());\n" + + " break;\n" + + " case EventType::MatchFrame:\n" + + " env->CallVoidMethod(moduleObj, matchFrameCallback);\n" + + " break;\n" + + " case EventType::SendText:\n" + + " env->CallVoidMethod(moduleObj, sendTextCallback, env->NewStringUTF(it->getText().c_str()));\n" + + " break;\n" + + " case EventType::ReceiveText:\n" + + " env->CallVoidMethod(moduleObj, receiveTextCallback, env->CallStaticObjectMethod(playerCls, env->GetStaticMethodID(playerCls, \"get\", \"(J)Lbwapi/Player;\"), (jlong)it->getPlayer()), env->NewStringUTF(it->getText().c_str()));\n" + + " break;\n" + + " case EventType::PlayerLeft:\n" + + " env->CallVoidMethod(moduleObj, playerLeftCallback, env->CallStaticObjectMethod(playerCls, env->GetStaticMethodID(playerCls, \"get\", \"(J)Lbwapi/Player;\"), (jlong)it->getPlayer()));\n" + + " break;\n" + + " case EventType::NukeDetect:\n" + + " env->CallVoidMethod(moduleObj, nukeDetectCallback, env->NewObject(posCls, env->GetMethodID(posCls, \"\", \"(II)V\"), it->getPosition().x, it->getPosition().y));\n" + + " break;\n" + + " case EventType::UnitDiscover:\n" + + " env->CallVoidMethod(moduleObj, unitDiscoverCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::UnitEvade:\n" + + " env->CallVoidMethod(moduleObj, unitEvadeCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::UnitShow:\n" + + " env->CallVoidMethod(moduleObj, unitShowCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::UnitHide:\n" + + " env->CallVoidMethod(moduleObj, unitHideCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::UnitCreate:\n" + + " env->CallVoidMethod(moduleObj, unitCreateCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::UnitDestroy:\n" + + " env->CallVoidMethod(moduleObj, unitDestroyCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::UnitMorph:\n" + + " env->CallVoidMethod(moduleObj, unitMorphCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::UnitRenegade:\n" + + " env->CallVoidMethod(moduleObj, unitRenegadeCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " case EventType::SaveGame:\n" + + " env->CallVoidMethod(moduleObj, saveGameCallback, env->NewStringUTF(it->getText().c_str()));\n" + + " break;\n" + + " case EventType::UnitComplete:\n" + + " env->CallVoidMethod(moduleObj, unitCompleteCallback, env->CallStaticObjectMethod(unitCls, env->GetStaticMethodID(unitCls, \"get\", \"(J)Lbwapi/Unit;\"), (jlong)it->getUnit()));\n" + + " break;\n" + + " }\n" + + " }\n" + + "}\n" + ); + out.println(); + } + + private void implementMirror_BWAPIClientGetters() { + out.println( + "JNIEXPORT jboolean JNICALL Java_bwapi_Mirror_isConnected(JNIEnv * env, jclass jclz){\n" + + " return BWAPI::BWAPIClient.isConnected();\n" + + "}\n" + + "\n" + + "JNIEXPORT jboolean JNICALL Java_bwapi_Mirror_connect(JNIEnv * env, jclass jclz){\n" + + " return BWAPI::BWAPIClient.connect();\n" + + "}\n" + + "\n" + + "JNIEXPORT void JNICALL Java_bwapi_Mirror_disconnect(JNIEnv * env, jclass jclz){\n" + + " BWAPI::BWAPIClient.disconnect();\n" + + "}\n" + + "\n" + + "JNIEXPORT void JNICALL Java_bwapi_Mirror_update(JNIEnv * env, jclass jclz){\n" + + " BWAPI::BWAPIClient.update();\n" + + "}\n" + ); + out.println(); + } + private void implementVariablesBind(List declarationList) { out.println("jclass cls;"); out.println("jmethodID getId;"); @@ -251,7 +238,12 @@ public class Bind { } public void implementBind(List declarationList) { - implementMirrorInit(declarationList); + implementHelpers(); + implementMirror_initTables(declarationList); + implementMirror_getInternalGame(); + implementMirror_processGameEvents(); + implementMirror_BWAPIClientGetters(); + } } diff --git a/manual-bwapi-src/Mirror.java b/manual-bwapi-src/Mirror.java index b311b5a..165469d 100644 --- a/manual-bwapi-src/Mirror.java +++ b/manual-bwapi-src/Mirror.java @@ -1,15 +1,11 @@ package bwapi; -import bwapi.AIModule; -import bwapi.BWEventListener; - import java.io.*; import java.io.File; import java.lang.Exception; import java.lang.UnsupportedOperationException; import java.util.*; import java.util.regex.Pattern; -import java.util.zip.*; public class Mirror { @@ -17,10 +13,6 @@ public class Mirror { private AIModule module = new AIModule(); - private FrameCallback frameCallback; - - private static final boolean EXTRACT_JAR = true; - private static void extractResourceFile(String resourceFilename, String outputFilename) throws Exception { InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceFilename); if (in == null) @@ -94,6 +86,8 @@ public class Mirror { System.exit(1); if (!extractBwtaDataFiles()) System.exit(1); + + initTables(); } public Game getGame() { @@ -105,26 +99,90 @@ public class Mirror { } /** - * Starts the API, initializes all constants ( {@link UnitType}, {@link WeaponType} ) and the {@link Game} object. - * This method blocks until the end of game. + * Initializes all BWAPI constant lookup tables. */ - public native void startGame(); + private static native void initTables(); - private void update() { - if (frameCallback != null) { - frameCallback.update(); + /** + * Initializes a connection to Broodwar, initializes the a {@link Game} object, and dispatches + * events to your listener as long as Broodwar is in a game. If this method is called before + * Broodwar is running, it will keep retrying until an initial connection can be established. + * + * The {@link Game} instance returned by {@link #getGame()} is only valid while this method + * is running. If your code holds a copy of this object anywhere else, do not try to use it + * again after this method returns. + * + * @param autoReconnect + * If true, will run an infinite loop allowing you to keep your bot running as many + * subsequent matches as desired. Will automatically reconnect to a Broodwar instance + * if the connection is interrupted. + * If false, will disconnect from Broodwar and return after the first match ends + * (regardless of how it ended). Will not attempt to reconnect to Broodwar if the + * connection is interrupted once the first match has been started. You can call + * {@link #startGame} again to run another match as needed. + */ + public void startGame(boolean autoReconnect) { + try + { + System.out.println("Connecting to Broodwar..."); + reconnect(); + System.out.println("Connection successful, starting match..."); + + game = getInternalGame(); + + do { + System.out.println("Waiting..."); + while (!game.isInGame()) { + update(); + if (!isConnected()) { + System.out.println("Reconnecting..."); + reconnect(); + } + } + + System.out.println("Game ready!!!"); + + while (game.isInGame()) { + processGameEvents(); + + update(); + if (!isConnected()) { + System.out.println("Reconnecting..."); + reconnect(); + } + } + + System.out.println("Match ended."); + } while(autoReconnect); + + System.out.println("Finished. Disconnecting from Broodwar..."); + } catch (InterruptedException e) { + System.out.println("Interrupted. Disconnecting from Broodwar..."); + } + if (isConnected()) + disconnect(); + + game = null; + } + + private void reconnect() throws InterruptedException { + while (!connect()) { + Thread.sleep(1000); } } - /*public void setFrameCallback(bwapi.Mirror.FrameCallback frameCallback) { - this.frameCallback = frameCallback; - } */ + /** + * Returns the current connection state to a running Broodwar instance. + */ + public static native boolean isConnected(); - /** - * The simplest interface to receive update event from Broodwar. The {@link #update()} method is called once each frame. - * For a simple bot and implementation of this interface is enough, to receive all in game events, implement {@link BWEventListener}. - */ - /*public*/ private interface FrameCallback { - public void update(); - } -} \ No newline at end of file + private static native boolean connect(); + + private static native void disconnect(); + + private static native void update(); + + private native Game getInternalGame(); + + private native void processGameEvents(); +}