Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

DarkBASIC Discussion / Sigh... Multiplayer Help

Author
Message
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 12th Dec 2007 04:29
Yup. I need multiplayer help. Wait, wait, stop the flaming and stuff. Not a MMORPG, not a MORPG, not a online RTS, no, no, no. It's far simpler than that. But, even though I've read every manual, searched the forum down to posts made years ago, completed any tutorial... I just can't get any MP to work.

A turnbased game, multiplayer type 2 (server-client) in which up to four players can play their turns simultaneously WITHOUT seeing eachother. Exactly. No position sending or so, no difficult interpolation things... No.

I've got four arrays, of which certain data needs to be synchronized over all players when ALL players end their turn. I've tried memblocks, loose integers, well, anything. Just can't get my head understanding the system.

I need three triggers, that do stuff:
- Turn End (sends to the server that a player is done with a turn, and sends the array data described below to the server to sync it with the others when ALL TURNS ARE ENDED).
- Turn Start (players get 15 seconds to decide for Move, Skip or War. If after 15 seconds, no choice is send to the server, the server sends the client a skip turn signal, and triggers the Turn End trigger on that client).
- Vendetta (player send another player a combat invitation. This can be accepted or rejected. If accepted, I'll need to set up a MP combat system, but I hope I'll understand everything after getting this to work. If rejected, I want to run some code. If requesting or accepting the vendetta, the Turn End trigger is set.)

The array data is:
pnr = player number
player(pnr,2,[1-6])
player(pnr,3,[1,3])

At game start, I'd need to sync this data:
names$(pnr,[1-2])
game([1-3])

If a Vendetta is triggered, I'd need to sync this between the two players:
gangsters(pnr,[1-player(pnr,2,6)],[1-8])

Is anyone NOT as confused as I am? I really tried for four-five days, now, but I just can't. It's as if some invisible wall stops me from understanding it. I tried to write it into these functions:

PREGAME:
StartData() | Sends the names$ array at game start to the host.
RecieveStartData() | Checks for incoming StartData()
SyncStartData() | Sends all StarData() as soon as all StartData() is in.

INGAME:
SendEndTurn() | END TURN TRIGGER
SendStartTurn(#) | # = 1: Skip, 2: Move, 2+pnr: Vendetta against pnr.
UpdateAll() | Synchronize all data (!)
RecieveTrig() | Check for triggers, should be done on the server only. It stores the trigger in a hypothetical array DIM Trig(4), which if all fields (players) are 1 (TRUE), triggers UpdateAll().

So, can anyone help me out on how I'd do this? As said, I can program well enough to grasp the idea if I see it, but with MP I just need a big extra hand...


A mod has been erased by your signature because it was larger than 600x120
luke810
18
Years of Service
User Offline
Joined: 4th Sep 2006
Location: United States
Posted: 12th Dec 2007 04:51
If you look at the rollerbug multiplayer program tutorial that comes in the boxed version of DB it has everything you need. Actually more since it is played in real-time instead of being turn based.
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 12th Dec 2007 04:54
Do you have the source for it, because my DB was boxed but didn't have anything but the game with the scorpion that could push a sphere around? It might be that, unlike all the other tutorials and source I've looked at, it will make me understand it.


A mod has been erased by your signature because it was larger than 600x120
luke810
18
Years of Service
User Offline
Joined: 4th Sep 2006
Location: United States
Posted: 12th Dec 2007 05:06
It has some media files with it for the rollerbug model and the music, am I allowed to post those here?
Jmahmood
18
Years of Service
User Offline
Joined: 3rd Apr 2007
Location: not sure
Posted: 12th Dec 2007 06:16
i cant help with the four players...i can only code for two.

Visit http://eternity.freeweb7.com for product demonstration,Downloads,Screenshots and Public forum
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 12th Dec 2007 21:26
@tha_rami
Also maybe checkout tempest...

tempest

Enjoy your day.
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 12th Dec 2007 22:15
Same thing happens with Tempest. I just can't grasp it. I'm so certain that once I get it, I can code all of it, but I can't! I hate the feeling - it's almost like a coders block. Crap.


A mod has been erased by your signature because it was larger than 600x120
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 14th Dec 2007 18:09


For some reason, any player that's not the first of the last cannot enter his name. I can't figure it out.

global(1) = player number
game(1) = Maximum Reputation (not relevant)
game(2) = Maximum players
game(4) = MP or not / player number


A mod has been erased by your signature because it was larger than 600x120
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 15th Dec 2007 07:39


Still doesn't work. Have made some workarounds for small problems, but the main problem still exists. A point of interest: all players are called player 2.


A mod has been erased by your signature because it was larger than 600x120
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 15th Dec 2007 18:37
Can you walk through a basic explanation of the code? What is the logical process going on in your mind? For example:

First I'm checking to see if the game is being joined or hosted,
Then I'm going to the kitchen to get some snacks...

If you can speak what the steps are you are trying to take, it may track down where the logic isn't working.

what is the array game()?

Something confusing to me, what are these variables and their similarity begs for a typo:
name$
Gname$
names$()

Enjoy your day.
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 15th Dec 2007 19:54 Edited at: 15th Dec 2007 19:55
The name$ array is a 4*2 array in which the top row is the gang name and the bottom row the player name - (1,2) is the name of player 1.

The game array is:
game(1) = Maximum Reputation (not relevant)
game(2) = Maximum players
game(3) = Current Game Turn
game(4) = MP or not / player number

Okay:

* The game lets the HOST enter the number of players, the maximum reputation and establish the game.
* The CLIENTS join the game.
* The HOST shares the game() array.
* When all players have joined, the HOST is allowed to enter his name (name$), then his gangs name (Gname$) as soon as all players join. In the meanwhile, the clients see a message which player number they are.
* The CLIENTS are then allowed to enter their gang name and name (this goes wrong, the clients don't get to this step. It appears the trigger = 255 statement goes wrong, making me assume that it does not send correctly.)
* Now, the CLIENTS send their name to the host. This information is stored into the names$() array.
* Then the HOST synchronizes name$() amongst all clients.
* Game start.


A mod has been erased by your signature because it was larger than 600x120
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 16th Dec 2007 00:42
let's see...

names$(1,2) The maximum index seems to be 1. In the snippet, names$(1,1) and name$(1,2) is used for both the Host and the player. How are you storing multiple names? Wouldn't they all just be over written? (thus only the first or the last would be recorded). Don't you need to store each name in a different index?

player1 = names$(1,2)
player2 = names$(2,2)
player3 = names$(3,2)
etc.

Or are you assigning names$() to another variable with one of the functions? Are they being assigned to multiplayer$() ?

As far as trigger = 255, well, hard to say... If the DLL you are using uses the data type char to identify a byte in trigger = NetGetByte()(if it was written in C), it could be ranging from -128 to 127 unless they used unsiged char in which case it would range from 0 to 255 - when you say it goes wrong, do you mean the loop never ends? If that is the case, put some code in there to check the value of trigger each iteration through the repeat loop. You'll at least be able to tell how the value is being updated.

You should put some debugging code in the areas that are giving you trouble - like the name assignment. This means having some kind of output of the values of the variables as they run. You can save it to a file or send it to the screen.

Also just to try out the functions, do some testing with a 1 dimensional array. Hard code some values and try sending the values using the net commands. Before coding triggers that respond to events, set up a loop that sends the values every 500 ms or so. See if the values are transmitted and received. If they are, change 500ms to a wait key command. When you press a key are the values transmitted and received? Then try setting it to a specific key press.

As far as ending a turn - since you have so few players, it's pretty easy to can use a binary system to keep track of who hasn't finished their turn. Let's say you have a variable called turns. If turns=0 then all players haven't finished their turn. The thing to do is to assign a binary value to a player:
Player1 = 2^0 = 1
Player2 = 2^1 = 2
Player3 = 2^2 = 4
Player4 = 2^3 = 8
etc.

Now when a player is finished with their turn, their player value is transmitted and added to turns on the host. If they haven't finished their turn 0 is transmitted so if Player1 and Player2 are finished, turns=3.

At anytime you can check turns to see which player has completed their turn with a little binary logic:

if turns & player1 = 1 then player1 is finished
if turns & player2 = 2 then player2 is finished
if turns & player3 = 4 then player3 is finished
if turns & player4 = 8 then player4 is finished

The symbol & - ANDs the bit values of the two variables. If any of the bits match exactly, then the value returned is the value of the matching bits. So if turns=5, when you & it against all of the players one at a time, you'll see that the value returned is zero except when anded against player1 and player3 in which case you will get 1 then 4 so you know player1 and player3 are done. So as far as the host managing the turns, for DBC you could store up to 32 player's status in a single variable.

Enjoy your day.
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 16th Dec 2007 04:23
name$() is actually 4x2, as can be seen here in the code:

if NetGetMessage() = 1
for x = 1 to 4
for y = 1 to 2
sync : text 0,15,"Connecting....."
names$(x,y) = NetGetString()
next y
next x
done = 1
endif

I like your player status thing. I'll try that. But for now, the connecting still doesn't work.


A mod has been erased by your signature because it was larger than 600x120
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 16th Dec 2007 06:58
Isn't the name being assigned by the player with:



The only indexes for names$() is 1,1 or 1,2. When do you actually assign any of the other indexes for any other player except 1?

Doesn't the code you just posted return whatever has been assigned to names$()? I don't see where you are assigning a name beyond the first index.

Enjoy your day.
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 16th Dec 2007 07:57
No, the name$(1,x) data is sent by the clients to the Host. The Host puts the data into the correct slot of the array with:




A mod has been erased by your signature because it was larger than 600x120
Latch
18
Years of Service
User Offline
Joined: 23rd Jul 2006
Location:
Posted: 17th Dec 2007 00:03
Oh well, I tried... I'm not familiar enough with the net commands to provide any real help.

Enjoy your day.
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 17th Dec 2007 06:08 Edited at: 17th Dec 2007 06:26
Thank you, Latch, honestly. You've been of great assistance to me in the past - and no doubt will be in the future. I admire how you try to help out everyone, even if it be only with general ideas if you don't know the exact answer.

In case you didn't notice, you're still in the credits of every one-man project I work on.

In any case, if anyone knows the answer, I'd be much obliged.


A mod has been erased by your signature because it was larger than 600x120
Diggsey
19
Years of Service
User Offline
Joined: 24th Apr 2006
Location: On this web page.
jason p sage
17
Years of Service
User Offline
Joined: 10th Jun 2007
Location: Ellington, CT USA
Posted: 17th Dec 2007 20:02
@the_rami -
Quote: "I just can't grasp it. I'm so certain that once I get it, I can code all of it, but I can't! I hate the feeling - it's almost like a coders block. Crap."


I know I've felt that before! (Currently fighting with an algorythm I know SHOULD be easy...) I usually just switch to something else a while and look at the thing with new eyes.

What is it about multi-player that is messing you up specifically - what makes your head spin about it?

I agree with you - in that once it clicks you'll probably be able to start running again.

Ortu
DBPro Master
17
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 18th Dec 2007 03:57
where you've got

if NetGetMessage() = 1
for x = 1 to 4
for y = 1 to 2
sync : text 0,15,"Connecting....."
names$(x,y) = NetGetString()
next y
next x
done = 1
endif

instead of using for/next x to set the player # index, you should use msgfrom=NetMessageFrom() right after NetGetMessage() then you can do:

if NetGetMessage()=1
msgfrom=netmessagefrom()
for y=1 to 2
name$(msgfrom,y)=netgetstring()
next y
done=1
endif

this way the data is filed to the array to the correct player slot no matter whether the message receiving order gets thrown off... its still kind of clumsy though in that it is pretty strict on message receiving timing/order I would have the clients send in a packet with all the data at once and start it with a byte to indicate what is being sent:

client:
input playername$
input gangname$
`build the packet assuming type of message flag=1 for name assignment
newmsg$="1|"+playername$+"|"+gangname$
netputstring(newmsg$)
netsend(0)

`lets say the user inputed "bob" for playername$ and "thugs" for gangname$ then the message actually sent would look like "1|bob|thugs|" the | is a flag for the host's decoding function to tell it when it has finished reading a data field. itll then extract the data to a variable and reduce the string to the unread portion. when the string is empty the decode is finished and you can grab a string from the next player.

`once you get to the main game processes clients can send in messages for actions they are taking by prefixing with a different value and the host can use that to direct the decoding 1=names, 2=move, 3=skip, 4=war, 5=end of turn

host:
do
`check for messages
if newmsg$>""
newmsg$=decodemsg(newmsg$,msgfrom)
else
if netgetmessage()>0
newmsg$=netgetstring()
msgfrom=netmessagefrom()
endif
endif
`check for all players named
for p=1 to 4
if name$(p,1)>""
nameok=1
else
nameok=0
endif
next p
`direct to main game if all are named
if nameok=1
`main game
.....
endif
loop
end

decodemsg(newmsg$,msgfrom)
if msgtype$="1"
if playername$>""
`extract gangname
if mid$(newmsg$,cur)="|"
gangname$=left$(newmsg$,cur-1) : newmsg$=right$(newmsg$,(len(newmsg$)-cur)) : cur=1
else
cur=cur+1
endif
else
`extract playername
if mid$(newmsg$,cur)="|"
playername$=left$(newmsg$,cur-1) : newmsg$=right$(newmsg$,(len(newmsg$)-cur)) : cur=1
else
cur=cur+1
endif
endif
`fill the name$ array
if gangname$>""
name$(msgfrom,1)=playername$
name$(msgfrom,2)=gangname$
`here you can send a message back to the client notifying of successful name registry then clear your temp variables to ready for the next player
newmsg$="" : msgfrom=0 : playername$="" : gangname$="" : cur=1
endif
`extract message type
else
if mid$(newmsg$,cur)="|"
msgtype$=left$(newmsg$,cur-1) : newmsg$=right$(newmsg$,(len(newmsg$)-cur)) : cur=1
else
cur=cur+1
if cur>len(newmsg$)
`bad message, kick it
msgtype$="" : cur=1 : newmsg$="" : msgfrom=0
endif
endif
endfunction newmsg$

Benjamin
22
Years of Service
User Offline
Joined: 24th Nov 2002
Location: France
Posted: 18th Dec 2007 08:08 Edited at: 18th Dec 2007 08:10
@tha_rami: Try writing a simplified client/server that just does the connection (in a similar manner to the way you handle it in this, of course). If you can't get that working, I'll take a look at the code and see what I can do.

I've just tested my DBC example on this PC, and for some odd reason the server crashes when I close it. Do you experience this also? Was just wondering, as you never mentioned it. It's not related to your problem.

Tempest (DBP/DBCe)
Multisync V1 (DBP/DBCe)
tha_rami
19
Years of Service
User Offline
Joined: 25th Mar 2006
Location: Netherlands
Posted: 18th Dec 2007 14:44
Yes, my DBC crashes after closing down the program.

Thanks for the help everyone, I think I've got it working after starting a total rewrite. Also special thanks to Ortu for having me use a part of his code; Benjamin for Multisync as a whole and everyone else who tried to help!

In other words: it works!


A mod has been erased by your signature because it was larger than 600x120
demons breath
21
Years of Service
User Offline
Joined: 4th Oct 2003
Location: Surrey, UK
Posted: 18th Dec 2007 21:00
WOOO! Now you can continue with your gangstery thing!

Ortu
DBPro Master
17
Years of Service
User Offline
Joined: 21st Nov 2007
Location: Austin, TX
Posted: 19th Dec 2007 03:35
Glad I could help, realized only after i hit post that i'd forgotten to stick it in a snippet <shrug>

multisync is definately a nice tool

Login to post a reply

Server time is: 2025-06-02 10:12:27
Your offset time is: 2025-06-02 10:12:27