adamgosikwolfe / androminion

Automatically exported from code.google.com/p/androminion
0 stars 0 forks source link

Multiplayer #582

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I know this is a duplicate issue, but I wanted to be sure that someone saw it.

I have been working on making this multiplayer in a local fork of the code, and 
I have a pretty good sense of how to make it work.  The problem is that to 
really do it right, it'll be a pretty major change.  I would like to contribute 
the changes back to this project so that others can benefit from it, as I am 
benefiting from the work done so far (and so that I don't have an incompatible 
fork that misses out on new features, like the Guilds branch that's currently 
in development).  So I wanted to get buy-in from the maintainers of this code 
before making this major change.

As I look at the code, the main barrier to making this into a nice multiplayer 
app is the strong coupling between the client and the server.  The RemotePlayer 
and VDomServer really should be inside the vdom code, not the androminion code. 
 That way you can start a server anywhere that can run the java code (like, 
say, from a PC or linux machine), and just connect to it with a client that 
knows the protocol (like the Androminion app) (and, of course, Androminion can 
just start the server itself, for local play).

The problem with moving RemotePlayer and VDomServer into the vdom code is that 
they rely on the android framework, because the protocol between the client and 
server is with localized strings - the server directly sends the strings that 
should show up in the client's UI.  So in order to do this right, you need to 
change the protocol.  The server shouldn't have to know anything about 
localization, but as long as it sends strings directly to the client, it does.

So, the roadmap I would put to making this work is the following:

1. Rework the protocol into something more sane.  The server should not be 
sending UI commands to the client.  The code already has things like 
NoblesOption, and those should be used as the protocol, while the client 
decides how to render the options to the user (so, for instance, you could 
build a web client that speaks the same protocol with a different UI - I have 
the beginnings of such a web client that I would like to attach, incidentally).

2. Once the protocol has been changed, move the RemotePlayer and VDomServer 
code from under androminion/ into vdom/, so that the vdom code has server 
capabilities on its own and can be run as a server from anywhere, not just 
android.

3. Add in some code for selecting which server to talk to (local, in which case 
we go to the same new game activity that's there now, or specify a host and 
port, in which case we just go straight to the game).

Does this sound reasonable?  If I do this (and assuming I do it well), will the 
changes be accepted?  Does anyone want to help me with it?

Original issue reported on code.google.com by drai...@gmail.com on 3 Aug 2013 at 11:37

GoogleCodeExporter commented 9 years ago
Hi, sorry for the late comment (I saw Defect/Multiplayer and didn't open it). 
Your plan sounds good, and if you are still interested in implementing it, I 
might be able to help. I've looked at separating the VDomServer object from the 
Android client before, but got lost in the information exchange parts. If you 
wouldn't mind uploading the code, I'd like to look at it and help if possible. 
I haven't been contributing much lately since most of the issues reported 
seemed to be fixed in current version, but I'm interested in looking at the 
Guilds expansion.

Original comment by tkden...@gmail.com on 24 Aug 2013 at 7:17

GoogleCodeExporter commented 9 years ago
Id be interested in helping out too for this feature. It's  java a while since 
I've done java. Could you upload your changes?

Original comment by e2theneg...@gmail.com on 25 Aug 2013 at 1:55

GoogleCodeExporter commented 9 years ago
Great, I'm glad that others are interested in helping.  I've been a little 
slower on this than I was hoping, as I recently had my appendix out.  But 
pretty soon I'll be able to put more energy into making this work.

The code I have done so far should probably be scrapped - I was just seeing if 
I could get it to work, and I totally broke the internationalization in the 
process.  I did step 2 without having done step 1, and that's not desirable for 
something that'll be integrated into the main project.

So the first order of business is finalizing a protocol.  Ankur mentioned to me 
(in an email) that using XML for the protocol would probably be good.  So when 
I get more time and energy to work on this, I will update this thread with some 
ideas for the protocol.  If any of you have some, feel free to add them here.  
Once we have that decided upon, fixing the code should be relatively 
straightforward.

Original comment by drai...@gmail.com on 26 Aug 2013 at 3:47

GoogleCodeExporter commented 9 years ago
I, too, am interested in helping out with this. I'll look over the code today 
and try to determine what all would need to be included in the protocol to help 
start developing it. I'm very familiar with Java, so I can help on the 
server/VDomServer side as well as helping out if we end up making a web UI.

One question on how we want to set it up:

Is the goal to split VDomServer off into a full-fledged Server? Specifically, 
should we have any sort of concept of a "lobby", or should we just stick with a 
single server is a single game?

(To me, it makes more sense to do the latter if the server plans on primarily 
running from a phone/tablet, but more sense to do the former if the server 
plans on primarily running on a dedicated server.)

Original comment by Nicholas...@gmail.com on 26 Aug 2013 at 2:55

GoogleCodeExporter commented 9 years ago
I'm an android developer and I'd like to help as well. I'm not sure how much 
free time I'll have, but I think that we should definitely work on getting any 
missing cards in the game and updating the UI a bit (just making it cleaner)

Original comment by cheney.h...@gmail.com on 26 Aug 2013 at 2:57

GoogleCodeExporter commented 9 years ago
Sent to me in an email by Nicholas (copying it here so that the discussion is 
public and documented, in case others have input):

"Looking through the code, I'm somewhat confused as to what your first step of 
reworking the network protocol would be. It seems like there's essentially two 
packages that you'd want - a DominionServer package, which contains all of the 
general communication and game logic (and which could be run from a non-Android 
device), and an AndrominionClient package.

"However, the current code looks to be split into the Androminion and VDom 
packages, with client/server code mixed between each. Is there any central 
"server" file that handles requests/responses, from which we can start the 
mapping of client/server interactions to build a protocol?"

So, first, responding to comment #4 by Nicholas, I think the first step is to 
just plan on one server per game.  Once we have that working correctly, it 
should be straightforward to change the server to allow for more than one game 
per server, but we shouldn't worry about that at first, I would say.

Second, responding to the email pasted in this comment.

There are three main files that we need to move from the Androminion package to 
the VDom package: VDomServer.java, IndirectPlayer.java, and RemotePlayer.java 
(and probably also DominionServer.java, though I haven't looked at that one as 
much).  Basically, the server/ package should be in VDom, not Androminion.  In 
order to do that, we need to break the dependency on the android framework, 
including the internationalization libraries.

As I understand the code, the entirety of the current client/server 
communication resides in the Androminion package, except for Comms.java, which 
is defined in the VDom package but never used there.  Comms is the interface 
that messages are sent over.  If you look in Indirectlayer.java, you'll see 
individual methods for each kind of game event (e.g., 
torturer_attack_chooseOption).  Those methods use a few low-level methods that 
send an event to the GameActivity through the comms object.  The low-level 
methods involve sending localized strings that the GameActivity should display, 
and that's the problem.  Instead, we should basically take the TorturerOption 
enum (and all similar ones), encode them in XML or some other reasonable 
protocol, and have the client (GameActivity) define its own low-level methods 
for choosing strings.

So, basically, we should move all of the *Options enum values into the EType 
enum in comms/Event.java, replacing GETSTRING and similar options.  I haven't 
looked at the Comms class, but maybe its current protocol is good enough and 
all we need to do is enrich the Event class.  Then the GameActivity will handle 
displaying the localized strings for each event type.

Does this make sense?  Is there anything I'm missing?  Probably the thing to do 
is pick a single card and implement it this way, through the Event class, and 
be sure it works.  I will probably have time to try that on Saturday, if no one 
else tries it first.  To be really clear: all you really need to do is add one 
more event type in the EType enum, change the corresponding method in 
IndirectPlayer to send that event type instead of a GETSTRING event, and add 
some handling code in GameActivity to display the localized strings (moving the 
localization code from IndirectPlayer to GameActivity, or some other class that 
GameActivity uses, if we want to separate the classes a bit - I haven't thought 
about that too much).  Then we should even be able to do this incrementally, 
until we've done it all and can actually move the server code into the VDom 
package.

Original comment by drai...@gmail.com on 26 Aug 2013 at 10:19

GoogleCodeExporter commented 9 years ago
Issue 312 has been merged into this issue.

Original comment by drai...@gmail.com on 27 Aug 2013 at 6:43

GoogleCodeExporter commented 9 years ago

Original comment by drai...@gmail.com on 27 Aug 2013 at 6:44

GoogleCodeExporter commented 9 years ago
I think this is an interesting enhancement to Androminion. If you want to 
improve multiplayer gaming later on, you could add:
- Local hotseat mode
- Multiplayer @ Adhoc Wifi / Bluetooth or using an open standard like XMPP, so 
that no dedicated server is needed to play against a friend locally or over the 
internet

I might help out a bit whith the code or UI, but I have other projects to work 
on right now and will be unavailable later this year, so it might take quite a 
long time before I can participate in Androminion again.

But anyways: Thumbs up for taking Androminion one step further.

Original comment by eiko.wag...@gmail.com on 8 Sep 2013 at 7:23

GoogleCodeExporter commented 9 years ago
Ok, I finally made some time to get started on this (sorry to take so long - 
life as a PhD student with a wife and two kids is really busy).

If you're interested in helping with the code (or want to give input on my 
method for implementing it), please take a look at r806.  As I mentioned 
earlier, I found a way to change the API incrementally, so we can work on this 
and still have a working APK at each step.  I tested r806 and it works for me.  
So, if you want to help, you can keep moving methods from IndirectPlayer to 
RemotePlayer (because the comms object and query method are in RemotePlayer), 
fixing the client/server API as you go, as seen in r806.  And if you have any 
feedback about a better way to do this, leave it in a comment here.  And if you 
are planning on changing the code, it'd be nice to leave a note here, so that I 
don't duplicate work you're planning on doing.

Original comment by drai...@gmail.com on 23 Sep 2013 at 12:43

GoogleCodeExporter commented 9 years ago
See r808 for a second pass at fixing the API for GETSTRING.  It's now cleaner 
than it was in r806, and should be pretty easy to migrate the rest of the 
methods that use GETSTRING.  I also added a Card variable to the Event object, 
which we should be able to use to remove the need for other Event types to pass 
literal strings.  In general, anything that uses R.* in IndirectPlayer should 
be moved to server/Strings.java, and ui/GameTable.java should be calling 
server.Strings, not IndirectPlayer.

Original comment by drai...@gmail.com on 29 Sep 2013 at 2:50

GoogleCodeExporter commented 9 years ago
Alright, I've passed a major milestone in getting this implemented.  See r839.  
I successfully moved IndirectPlayer.java from the androminion code to the vdom 
code.  This involved changing the display code for almost every single card, 
and I am not able to test all of them myself to make sure it's all working 
properly.  So if you want to help, the most helpful thing you could do right 
now is build the app off of the tip of the multiplayer branch, and play some 
games, checking carefully to be sure everything is working right (especially 
that the strings display as they are supposed to).  If something is not right, 
file a bug (and feel free to assign it to me).  Oh, and note that I introduced 
a regression with Wishing Well and similar cards, in that you can't name 
individual Ruins or Knights.  I'll fix that soon, along with Doctor and 
Journeyman (see Issue 593) - so don't file a new bug for that one.

I think I'll let this simmer a few days or a week and try to be sure it's free 
of bugs.  Then it's on to the next step of similarly moving RemotePlayer and 
VDomServer into the vdom code.

Original comment by drai...@gmail.com on 23 Oct 2013 at 2:25

GoogleCodeExporter commented 9 years ago
Is there a short guide somewhere how to download and build?

Original comment by ras.na...@gmail.com on 23 Oct 2013 at 12:23

GoogleCodeExporter commented 9 years ago
I should add one...  Here are some brief instructions, though - let me know if 
they aren't sufficient.

Make sure you have the android SDK installed (here is a good guide: 
http://developer.android.com/training/basics/firstapp/index.html), with 
whatever target is found in the project.properties under androminion/ and 
actionbarsherlock/ (in both the multiplayer branch and trunk, that is 
android-14 for actionbarsherlock/project.properties, and android-15 for 
androminion/project.properties; so, using the SDK manager that you'll find when 
you get the android SDK, be sure you install the "SDK Platform" for both API 
level 14 and API level 15).

With the SDK installed, you can just use ant to build the app (I think you can 
also run the app through Eclipse, but I don't know much about how that works - 
the guide linked above might help you if that's what you want to do).  So make 
sure you have the tip of the multiplayer branch checkout out, cd into the 
androminion/ directory, then run the following two commands:

ant vdom_lib
ant debug

The first command builds the vdom library code and puts a .jar file in the 
androminion directory, and the second command builds the app (including the 
actionbarsherlock code) in debug mode.  There's probably a way to change the 
build files so you only need one command, but I didn't look hard enough to 
figure it out.

Once you've built the app, you can install it on your device using adb.  There 
are instructions for that on the page linked above, too.  The command, though, 
is

adb install -r bin/Androminion-debug.apk

The -r means "please overwrite any version already there".  But it will 
probably fail the first time if you already have androminion installed from the 
play store, as it's signed by a different certificate.  So you'll have to 
uninstall the version from the play store, then run the command.

Once it's installed, if you see a crash, you can get the log output by running

adb logcat

This could be long and obnoxious; what I like to do is run 

adb logcat -c
adb logcat -d |less

The -c in the first command clears the log (you do this just before doing 
something on the app that you know will crash it), and the -d in the second 
command dumps the log and exits, instead of continuously showing messages as 
they come in.

If running the adb logcat stuff is too complicated, you can just file a bug 
report containing what you did to cause a crash, and I (or someone else) can 
find the exact error with adb.  Note, though, that at this point I'm also 
looking for errors that show incorrect strings, which will not cause a crash - 
if you see those errors, there's no need for adb, just file a bug report.

Original comment by drai...@gmail.com on 23 Oct 2013 at 3:16

GoogleCodeExporter commented 9 years ago
hm. sounds complex. :(

what about committing the apk to svn? then we can download it and test it.

Original comment by ras.na...@gmail.com on 24 Oct 2013 at 6:20

GoogleCodeExporter commented 9 years ago
Ok, I committed an APK, though I don't promise that it will stay updated.  It's 
bin/Androminion-debug.apk, on the multiplayer branch.

Original comment by drai...@gmail.com on 24 Oct 2013 at 12:44

GoogleCodeExporter commented 9 years ago
Downloaded and installed.

Freezes in 1st turn. Galaxy S2, Android 4.1.2

Preset, Arts and Crafts (Guilds). Drew+Earl. Start. Freezes when playing money.

Looks OK with random base game same AIs though.

Original comment by ras.na...@gmail.com on 27 Oct 2013 at 5:51

GoogleCodeExporter commented 9 years ago
The problem is likely cased by coin token. If I play treasures and have coin 
token the app crashes.

Original comment by ras.na...@gmail.com on 27 Oct 2013 at 7:39

GoogleCodeExporter commented 9 years ago
Great, thanks for finding that.  It should be fixed now, if you download the 
APK I just uploaded (in the same place).  In the future, I would recommend 
starting a new issue with these bugs, instead of adding to this one.  It's just 
easier to keep track of things that way.

Original comment by drai...@gmail.com on 28 Oct 2013 at 11:54

GoogleCodeExporter commented 9 years ago
OK. I will write separate tickets. 

BTW played quite an amount of base games, and it was OK with those.

Please specify more what do you mean exactly on "strings displaying correctly". 
I am not sure that I know what should I look for.

Original comment by ras.na...@gmail.com on 28 Oct 2013 at 1:38

GoogleCodeExporter commented 9 years ago
By "strings displaying correctly", I mean three places:

- The buttons that show up when you're selecting cards (I don't expect that 
there are any problems here, but it's good to check just in case).
- The text above the buttons, at any point in the game (For instance, "Pick up 
to 4 treasure cards from your hand ..."), but particularly after playing an 
action card.
- The text that shows up when you have a selection between a few options, like 
when someone plays a torturer and you have to pick to discard two cards or take 
a curse, or when you have a moat in your hand and someone plays an attack card. 
 The thing to be sure of is that the right strings show up, and when you click 
on a string, that the option you expected happened.

Original comment by drai...@gmail.com on 28 Oct 2013 at 2:06

GoogleCodeExporter commented 9 years ago

Original comment by drai...@gmail.com on 28 Oct 2013 at 2:07

GoogleCodeExporter commented 9 years ago
(created separate ticket about Spy issue)

Original comment by ras.na...@gmail.com on 28 Oct 2013 at 4:07

GoogleCodeExporter commented 9 years ago
there are quite an amount of random freezes (~every 8th game). Is there any way 
to give you debug info, when playing on Android phone?

Original comment by ras.na...@gmail.com on 30 Oct 2013 at 2:25

GoogleCodeExporter commented 9 years ago
I noticed some random freezes myself, but they were hard to reproduce.  The 
best you can do, I think, is tell me what you did immediately prior to the game 
freezing.  Unless you want to plug your phone into a computer and get log 
output using adb, as described above.

Original comment by drai...@gmail.com on 30 Oct 2013 at 2:29

GoogleCodeExporter commented 9 years ago
do I have to plug it before the crash, or is it OK after?

The errors are pretty random, some happenned when playing fools golds, but
I was not able to consistently reproduce.

Also I think that the state of the game was lost afer I did some web
browsing in teh foreground.

Original comment by ras.na...@gmail.com on 30 Oct 2013 at 3:25

GoogleCodeExporter commented 9 years ago
Right after you see the crash, plug it into a computer and run

adb logcat -d >logfile.txt

The end of the file should contain the error.  Put the error into a bug report, 
either by copying and pasting just the error, or by uploading the file in the 
bug report (though I'm not sure what kinds of privacy things might be leaked by 
uploading the whole file - just the error is fine, if you can find it).

Original comment by drai...@gmail.com on 30 Oct 2013 at 3:29

GoogleCodeExporter commented 9 years ago
Just a note for those of you looking for bugs on the multiplayer branch (and 
thanks a lot, again, for all of your help!): I have started working on the next 
step, which is moving RemotePlayer into the vdom code.  I expect that a lot of 
the revisions that are committed will be unstable, and the apk may not even run 
- I will fix those, and when I think it's to a point where I could use help 
looking at it again, I'll let you know.  So it's great to keep looking for bugs 
in what I've already done, but you can stick to the r857 apk, unless there's a 
later one that I've said that I think is stable and ok to test.

Original comment by drai...@gmail.com on 6 Nov 2013 at 12:55

GoogleCodeExporter commented 9 years ago
Ok, the most recent APK (r875) should be stable, and is ready for more general 
testing.  In particular, the things that I changed that should be looked at are 
the strings that appear in the game log along the bottom - the events that show 
up as people play and buy cards, and whatnot.  The hope is that there is no 
difference between trunk and the multiplayer branch in those strings.  In the 
(very limited) testing that I've done, things look ok.  There's also a 
possibility that some other strings broke, like card descriptions, but those 
look ok to me.

In short, we are _very_ close to being able to move all of the server code into 
vdom, at which point we can actually start implementing multiplayer.  I think 
the only thing that's left is a single call to Strings in VDomServer.

Original comment by drai...@gmail.com on 7 Nov 2013 at 9:49

GoogleCodeExporter commented 9 years ago
Major milestone: step 1 is completed.  As of r884, I have successfully moved 
all of the necessary server code into vdom.  It should now be possible to run a 
VDom server on something other than android, and connect to it with a client 
that speaks the right protocol.  Now we just need to make a few small 
modifications to the GameActivity and other places to allow for a server 
running somewhere other than the current device.  Luckily, it looks like a lot 
of the necessary code is already there (e.g., there's a JoinGameDialog that 
appears to be currently unused), we just need to hook into it.  If everything 
goes well, it should just be a few days' work before there's an apk that will 
be able to run multiplayer, connecting to an external server.

Of course, I'm still not completely certain that my modifications are free of 
bugs, so please continue to keep your eyes open when using this apk for 
anything that looks wrong.  And thanks again to everyone that's helped me find 
the problems.

Original comment by drai...@gmail.com on 11 Nov 2013 at 1:26

GoogleCodeExporter commented 9 years ago
Ok, I've spent a couple of hours poring over the code.  I'm not that familiar 
with Android UI code, and I'm having a really hard time navigating the mess of 
intents, fragments and activities that make the game work.  I'm hoping that 
there's someone here that can do the little bit of UI / activity work that's 
left, or at least point me in the right direction.

Here's what's needed (as of r892):

You can run `ant run` from the vdom/ directory to start a game with a remote 
player.  The remote player spits out the port that it's listening on.  We just 
need a way to enter the host and port that the remote player's listening on, 
and get the GameActivity to send a HELLO event to that port.  If we can do 
that, I'm hopeful that things will just work.  I just don't know how to get the 
host and port to the GameActivity in the right place.

I put a "Join Game" button in the MenuActivity, with the idea of having that 
pop up some dialog that then starts a GameActivity in the right state to have 
it send a HELLO to the remote player.  I see that there's already a file called 
ui/JoinGameDialog.java, but that takes a GameActivity object in its 
constructor, so I'm not sure how to use it here.  I think all that we really 
need is to implement MenuActivity.onClickJoinGameView in the right way, 
possibly also modifying the GameActivity to work correctly for this use case.

Any help?  It's frustrating to be so very close and not know how to proceed.

Original comment by drai...@gmail.com on 12 Nov 2013 at 1:30

GoogleCodeExporter commented 9 years ago
Alright, I did some more searching, and reading some Android documentation, and 
I think I know how to finish this.  I added a note to the code (in r895) 
explaining how it should work.  This week is pretty busy for me, though, so it 
might be a few days before I can get to it.

Original comment by drai...@gmail.com on 15 Nov 2013 at 1:18

GoogleCodeExporter commented 9 years ago
With r897, I have successfully played a multiplayer game.  The interface to get 
it started is not pretty, but it works.  Steps to run the game:

In the vdom/ directory, type `ant run` (or just start com.vdom.core.Game with 
whatever arguments you want - the build file has some default arguments).  Be 
sure you know the host name or ip address for the machine that's running the 
game server, and that the player ports (by default 2255 and 2256) aren't 
blocked by your machine's firewall.

Open the app on two separate devices.  Use the "join game" dialog to enter your 
name, the host name or ip address of the machine running the server, then the 
port that shows up in the terminal where you're running the server.  Once the 
first player connects, a second port will show up; enter that one in on the 
second device (should be 2255 and 2256).  The interface for the first player 
that connects will be missing a lot of stuff until the second player connects, 
but once both players are there, things work fine.

I'm officially calling this finished, at least for me, for now.  I've spent 
most of my free time in the last couple of months working on this, and I'm 
taking a break.  If you want this to be more pretty, or to work with just two 
android devices instead of a separate machine running the server, I think it 
won't be that hard, but someone else will have to do it.  Have fun =).

I'm closing this feature request.  I recommend starting a new one for further 
enhancements to the multiplayer functionality.

Original comment by drai...@gmail.com on 16 Nov 2013 at 1:14