From 4f963c21db4113082102b4e871e508e091193b86 Mon Sep 17 00:00:00 2001 From: Mimerme Date: Sun, 25 Jan 2015 11:13:01 -0500 Subject: [PATCH 01/24] Basic Replay Support Notes - Only singles supported - Unstable for other replays - user cannot choose their own replay to watch --- .../app/BattleFieldActivity.java | 6 + .../com/pokemonshowdown/replays/Replay.java | 199 ++++++++++++++++++ .../replays/ReplayFragment.java | 89 ++++++++ .../replays/ResponseHandler.java | 5 + .../replays/RetrieveReplayTask.java | 60 ++++++ app/src/main/res/layout/fragment_replay.xml | 31 +++ .../res/layout/fragment_replay_battle.xml | 10 + 7 files changed, 400 insertions(+) create mode 100644 app/src/main/java/com/pokemonshowdown/replays/Replay.java create mode 100644 app/src/main/java/com/pokemonshowdown/replays/ReplayFragment.java create mode 100644 app/src/main/java/com/pokemonshowdown/replays/ResponseHandler.java create mode 100644 app/src/main/java/com/pokemonshowdown/replays/RetrieveReplayTask.java create mode 100644 app/src/main/res/layout/fragment_replay.xml create mode 100644 app/src/main/res/layout/fragment_replay_battle.xml diff --git a/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java b/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java index b8ad31c6..3888f77e 100644 --- a/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java +++ b/app/src/main/java/com/pokemonshowdown/app/BattleFieldActivity.java @@ -27,6 +27,7 @@ import com.pokemonshowdown.data.CommunityLoungeData; import com.pokemonshowdown.data.MyApplication; import com.pokemonshowdown.data.Onboarding; +import com.pokemonshowdown.replays.ReplayFragment; import org.json.JSONException; import org.json.JSONObject; @@ -230,6 +231,10 @@ private void selectItem(int position) { mPosition = 1; fragment = CommunityLoungeFragment.newInstance(); break; + case 2: + mPosition = 2; + fragment = ReplayFragment.newInstance(); + break; case 3: mPosition = 3; fragment = CreditsFragment.newInstance(); @@ -237,6 +242,7 @@ private void selectItem(int position) { default: mPosition = 2; fragment = new PlaceHolderFragment(); + break; } FragmentManager fm = getSupportFragmentManager(); diff --git a/app/src/main/java/com/pokemonshowdown/replays/Replay.java b/app/src/main/java/com/pokemonshowdown/replays/Replay.java new file mode 100644 index 00000000..cf80b72b --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/Replay.java @@ -0,0 +1,199 @@ +package com.pokemonshowdown.replays; + +import android.os.Handler; +import android.support.v4.app.Fragment; +import android.util.Log; + +import java.util.ArrayList; + +/** + * Replay instance + * Returns events and such + */ +public class Replay { + Fragment BattleFragment; + + //Each step is an seprate event in-game + //unformated steps for BattleMessage.java + ArrayList mFormatedSteps = new ArrayList(); + //Speed in milliseconds at which each event of the replay will last + //if Battle fragment does not handle messages fast enough, possibility of an exception being thrown + public long speed; + + private String mPlayer1; + private String mPlayer1rank; + private String mPlayer2; + private String mPlayer2rank; + private String mGameType; + private String mTier; + private boolean mRated; + + public ArrayList rules = new ArrayList(); + public ArrayList p1Pokemon = new ArrayList(); + public ArrayList p2Pokemon = new ArrayList(); + public ArrayList turns = new ArrayList(); + + private com.pokemonshowdown.app.BattleFragment mReplayBattleFragment; + private int mCurrentStep; + + public String getPlayer1(){return mPlayer1;} + public String getPlayer2(){return mPlayer2;} + public ArrayList getSteps(){return mFormatedSteps;} + + public static ArrayList getSteps(String replayData){ + String [] unformatedSteps; + ArrayList formatedSteps = new ArrayList(); + unformatedSteps = replayData.split(System.getProperty("line.separator")); + for(String str : unformatedSteps){ + formatedSteps.add(/*str.replaceFirst("\\W", "")*/ str); + } + return formatedSteps; + } + + + public Replay(String replayData, com.pokemonshowdown.app.BattleFragment replayBattleFragment){ + mReplayBattleFragment = replayBattleFragment; + mFormatedSteps.add(""); + String[] mReplayData = replayData.split("::"); + for(String str : mReplayData){ + mFormatedSteps.add(reformat(str).replaceFirst("\\W", "")); + } + } + + //Converts the script.log to everything the battle message can understand + public static String reformat(String mLine){ + String args[] = mLine.split("\\|"); + //Houses temporary splits when string is reformated + String temp[]; + + String command; + if(args.length < 2){ + return ""; + } + command = args[1]; + Log.i("Command", command); + switch(command){ + case "player": + break; + case "poke": + break; + case "switch": + mLine = mLine.replace(",", ", L100,"); + mLine = mLine.replace("(", ""); + mLine = mLine.replace(")", ""); + mLine = mLine.replace("\\", ""); + //mLine = mLine.replace(" 100/100", "100/100"); + mLine = fixp1p2(mLine); + args = mLine.split("\\|"); + temp = args[4].split(" "); + temp[0] = ""; + args[4] = temp[1]; + mLine = rebuildString(args); + break; + case "-damage": + mLine = mLine.replace("(" , ""); + mLine = mLine.replace(")" , ""); + mLine = mLine.replace("\\" , ""); + mLine = fixp1p2(mLine); + args = mLine.split("\\|"); + temp = args[3].split(" "); + temp[0] = ""; + args[3] = temp[1]; + mLine = rebuildString(args); + break; + case "-heal": + mLine = mLine.replace("(" , ""); + mLine = mLine.replace(")" , ""); + mLine = mLine.replace("\\" , ""); + mLine = fixp1p2(mLine); + args = mLine.split("\\|"); + temp = args[3].split(" "); + temp[0] = ""; + args[3] = temp[1]; + mLine = rebuildString(args); + break; + default: + mLine = mLine.replace("(" , ""); + mLine = mLine.replace(")" , ""); + mLine = mLine.replace("\\" , ""); + mLine = fixp1p2(mLine); + break; + } + return mLine; + } + + static String fixp1p2(String in){ + in = in.replaceAll("p1", "p1a"); + in = in.replaceAll("p2", "p2a"); + return in; + } + + private void runClock(){ + new Handler().postDelayed(new Runnable() { + + @Override + public void run() { + getStep(); + } + }, speed); + Log.i("Replay Next Step #", Integer.toString(mCurrentStep)); + } + + private void getStep(){ + if(mFormatedSteps.get(mCurrentStep).equalsIgnoreCase("callback|decision")){ + speed = 1000; + mCurrentStep++; + mReplayBattleFragment.processServerMessage(mFormatedSteps.get(mCurrentStep)); + Log.i("Replay Next Step", mFormatedSteps.get(mCurrentStep)); + runClock(); + return; + } + mReplayBattleFragment.processServerMessage(mFormatedSteps.get(mCurrentStep)); + mCurrentStep++; + Log.i("Replay Next Step", mFormatedSteps.get(mCurrentStep)); + runClock(); + return; + } + + /* BattleFragment. + + new CountDownTimer(3000, 1000) { + + public void onTick(long millisUntilFinished) { + //Random thing needed + } + + public void onFinish() { + Log.i("test", "reached"); + } + }.start();*/ + + //Pause the replay + public void Pause(){ + + } + //Skip the turn + public void Skip(){ + + } + //Play the replay + public void Play() { + /*if (p1Pokemon.isEmpty() || p2Pokemon.isEmpty() || turns.isEmpty()) { + Log.e("Replay Error", "Not all replay values have been specified. Are you sure you calle" + + "d the methods in the right order?"); + return; + }*/ + runClock(); + return; + } + public static String rebuildString(String[] s){ + String v = ""; + for (String string : s) { + v += string; + v += "|"; + } + return v; + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/pokemonshowdown/replays/ReplayFragment.java b/app/src/main/java/com/pokemonshowdown/replays/ReplayFragment.java new file mode 100644 index 00000000..bd4089c0 --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/ReplayFragment.java @@ -0,0 +1,89 @@ +package com.pokemonshowdown.replays; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentTransaction; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import com.pokemonshowdown.app.BattleFragment; +import com.pokemonshowdown.app.R; +import com.pokemonshowdown.data.BattleFieldData; + +public class ReplayFragment extends android.support.v4.app.Fragment implements View.OnClickListener{ + + public ProgressDialog mWaitingDialog; + + public static ReplayFragment newInstance() { + ReplayFragment fragment = new ReplayFragment(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + public ReplayFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View v = inflater.inflate(R.layout.fragment_replay, container, false); + v.setFocusableInTouchMode(true); + Button submit = (Button) v.findViewById(R.id.submit); + submit.setOnClickListener(this); + return v; + } + + @Override + public void onDetach() { + super.onDetach(); + } + + public void showReplay(View view) { + EditText mEditText = (EditText) view.findViewById(R.id.replayInput); + + RetrieveReplayTask getReplayTask = new RetrieveReplayTask(){ + public void OnResponseRecived(Object obj) { + String battleLog = (String) obj; + //If replay was not retrieved correctly + if(battleLog == null){ + Toast toast = Toast.makeText(getActivity().getApplicationContext(), "Error fetching replay", Toast.LENGTH_LONG); + toast.show(); + return; + } + setUpReplayBattle(battleLog); + } + }; + getReplayTask.execute("http://pokemonshowdown.com/replay/exeggutorboldalakazam"); + } + + @Override + public void onClick(View view) { + showReplay(view); + } + + private void setUpReplayBattle(String replayString){ + + //Create BattleFragment (Basically the same thing as watching replays) + BattleFragment replayBattleFragment; + replayBattleFragment = BattleFragment.newInstance("replay"); + Replay currentReplay = new Replay(replayString, replayBattleFragment); + BattleFieldData fieldData = BattleFieldData.get(getActivity().getApplicationContext()); + fieldData.joinRoom("replay",false); + FragmentManager fm = getFragmentManager(); + FragmentTransaction ft = fm.beginTransaction(); + ft.replace(R.id.fragmentContainer, replayBattleFragment).commit(); + currentReplay.Play(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pokemonshowdown/replays/ResponseHandler.java b/app/src/main/java/com/pokemonshowdown/replays/ResponseHandler.java new file mode 100644 index 00000000..c0c1e284 --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/ResponseHandler.java @@ -0,0 +1,5 @@ +package com.pokemonshowdown.replays; + +public interface ResponseHandler { + public void OnResponseRecived(Object result); +} diff --git a/app/src/main/java/com/pokemonshowdown/replays/RetrieveReplayTask.java b/app/src/main/java/com/pokemonshowdown/replays/RetrieveReplayTask.java new file mode 100644 index 00000000..5872e0b2 --- /dev/null +++ b/app/src/main/java/com/pokemonshowdown/replays/RetrieveReplayTask.java @@ -0,0 +1,60 @@ +package com.pokemonshowdown.replays; + +import android.os.AsyncTask; +import android.util.Log; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Battle log of all events are stored in + * TODO : Allow cached copies of replays + */ +public abstract class RetrieveReplayTask extends AsyncTask implements ResponseHandler { + String html = ""; + + @Override + protected String doInBackground(String... url) { + Log.i("Getting Replay", url[0]); + try { + HttpClient client = new DefaultHttpClient(); + HttpGet request = new HttpGet(url[0]); + HttpResponse response = client.execute(request); + + InputStream in = response.getEntity().getContent(); + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + StringBuilder str = new StringBuilder(); + String line = null; + while((line = reader.readLine()) != null) + { + str.append("::" + line); + } + in.close(); + html = str.toString(); + html = html.substring(html.indexOf("")); + Log.i("Sauce",html); + } catch (IOException e) { + e.printStackTrace(); + } + + return html; + } + + @Override + protected void onPostExecute(String element) { + OnResponseRecived(element); + return; + } + + @Override + public abstract void OnResponseRecived(Object result); + +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_replay.xml b/app/src/main/res/layout/fragment_replay.xml new file mode 100644 index 00000000..beec1027 --- /dev/null +++ b/app/src/main/res/layout/fragment_replay.xml @@ -0,0 +1,31 @@ + + + + + + + + +