[SORRY TO ANYONE WHO MAY HAVE TRIED THIS OVER THE PAST FEW DAYS TO FIND THAT IT DIDN'T WORK. BUT, ALL IS FIXED NOW AND I HAVE TESTED THE CODE POSTED HERE WITH THE HELP OF SHADOW AND IT WORKS NOW]
I have made many improvements to my code, and I think I can now say that I have created my perfect multiplayer system. This example can take you as far as it can without requiring any downloads of media or any DLL's. All you need to run this is DBPro.
This example consists of:
(1)Multiple servers on one connection.
(2)Non-Dedicated and True Dedicated hosting.
(3)Player id, coordinates, and orientation, sent via memblocks.
(4)Chat messages sent via net strings. Remote dedicated hosts can
also send and receive chat messages. Dedicated hosts, are
not counted as a player and all information is routed through
that host to increase speed of game. Note: host has option of
not being dedicated, and can therefore participate in the game.
(5)Map data stored in memblocks for loading and creating new maps
with ease. I even include a simple map maker to create maps
for use with my example multiplayer system.
(6)All maps are "SERVER SIDE". This means that only the host is
required to have a copy of the map. All clients, do not need
to have the map to play it.
Here is the multiplayer code:
Rem Project: multiplayer2
Rem Created: 8/5/2005 9:31:07 PM
Rem ***** Main Source File *****
print "Searching for connections..."
perform checklist for net connections
for i=1 to checklist quantity()
if checklist string$(i)="Internet TCP/IP Connection For DirectPlay" then netsel=i
next i
print " connection found"
print ""
input "Please enter address: ",ip$
print ""
print "Connecting..."
set net connection netsel,ip$
print " connected"
print ""
print "Searching for server..."
perform checklist for net sessions
print " server found" : cls
print "[ ",checklist quantity()," ] SERVERS FOUND"
for i=1 to checklist quantity()
print i,". ",checklist string$(i)
next i
print "" : input "(1)JOIN / (2)CREATE: ",netsel
if netsel=1
host=0 : flag=1
input "Join which server?: ",s
input "Player name: ",name$
join net game s,name$
cls : print "Joining..."
endif
if netsel=2
host=1
input "Server name: ",s$
input "Player name: ",name$
input "Max # of players: ",num
input "Dedicated? (0)NO / (1)YES ",flag : inc flag
create net game s$,name$,num,flag
cls : print "Creating..."
endif
print " done"
if host=1
input "Name of map to load: ",map$
open to read 1,map$
make memblock from file 3,1
close file 1
tc=get memblock size(3)
if flag=1 then gosub _build
endif
if host=0
mymessage$="sr"
send net message string 0,mymessage$
t=0
repeat
get net message
if net message exists()=1
if net message type()=3
message$=net message string$()
if left$(message$,2)="sm"
t$=right$(message$,len(message$)-2)
tc$=""
tt$=""
do
tc$=left$(t$,1)
t$=right$(t$,len(t$)-1)
if tc$="," then exit
tt$=tt$+tc$
loop
tt=val(tt$)
tc=val(t$)
make memblock 3,tc
th=0
repeat
get net message
if net message exists()=1
if net message type()=4
net message memblock 3
if memblock byte(3,0)=tt
gosub _build
th=1
endif
endif
endif
until th=1
t=1
endif
endif
endif
until t=1
endif
print "get id."
id=1
if flag=2 then id=17
if flag=1
dim players(16)
for x=1 to 16
players(x)=0
next x
mymessage$="ss"
send net message string 0,mymessage$
wait 5000
_id:
get net message
if net message exists()=1
if net message type()=3
message$=net message string$()
if left$(message$,2)="si"
t$=right$(message$,len(message$)-2)
t=val(t$)
players(t)=1
endif
endif
goto _id
endif
for x=1 to 16
if players(x)=1
make object cube x,10
endif
next x
for x=1 to 16
if players(x)=0
id=x
exit
endif
next x
players(id)=1
endif
sync on : sync rate 30 : autocam off : hide mouse
dim messages$(10)
m=1
mymessage$="[ "+name$+" ] HAS JOINED THE SERVER."
messages$(0)=mymessage$
mymessage$="m"+mymessage$
send net message string 0,mymessage$
make memblock 1,17
make memblock 2,17
if flag=1
do
rotate camera 0,camera angle x(0)+mousemovey(),camera angle y(0)+mousemovex(),0
if keystate(17)=1 then move camera 0,1
if keystate(31)=1 then move camera 0,-1
if keystate(32)=1 then yrotate camera 0,camera angle y(0)+90 : move camera 0,1 : yrotate camera 0,camera angle y(0)-90
if keystate(30)=1 then yrotate camera 0,camera angle y(0)-90 : move camera 0,1 : yrotate camera 0,camera angle y(0)+90
if keystate(20)=1
sync off
for x=0 to 9
text 10,10+(x*20),messages$(x)
next x
set cursor 10,300
input "Say: ",mymessage$
repeat : until returnkey()=0
mymessage$=name$+": "+mymessage$
if m=10
for x=0 to 8
messages$(x)=messages$(x+1)
next x
messages$(9)=mymessage$
else
messages$(m)=mymessage$ : inc m
endif
mymessage$="m"+mymessage$
send net message string 0,mymessage$
sync on : sync rate 30
endif
x#=camera position x(0)
z#=camera position z(0)
position camera 0,x#,5,z#
ax#=camera angle x(0)
ay#=camera angle y(0)
write memblock byte 1,0,id
write memblock float 1,1,x#
write memblock float 1,5,z#
write memblock float 1,9,ax#
write memblock float 1,13,ay#
send net message memblock 0,1,0
_new:
get net message
if net message exists()=1
messagetype=net message type()
if messagetype=4
net message memblock 2
player=memblock byte(2,0)
if player<17
if player>0
if object exist(player)=0
make object cube player,10
endif
if players(player)=0
show object player
players(player)=1
endif
endif
endif
x#=memblock float(2,1)
z#=memblock float(2,5)
ax#=memblock float(2,9)
ay#=memblock float(2,13)
if player<17
if player>0
position object player,x#,5,z#
rotate object player,ax#,ay#,0
endif
endif
endif
if messagetype=3
message$=net message string$()
if message$>""
if left$(message$,1)="s"
if left$(message$,2)="ss"
mymessage$="si"+str$(id)
send net message string 0,mymessage$
endif
if left$(message$,2)="sl"
t$=right$(message$,1)
t=val(t$)
hide object t
players(t)=0
endif
if left$(message$,2)="sr"
if host=1
mymessage$="sm"+str$(id)+","+str$(get memblock size(3))
send net message string 0,mymessage$
write memblock byte 3,0,id
send net message memblock 0,3,0
endif
endif
endif
if left$(message$,1)="m"
message$=right$(message$,len(message$)-1)
if m=10
for x=0 to 8
messages$(x)=messages$(x+1)
next x
messages$(9)=message$
else
messages$(m)=message$ : inc m
endif
endif
endif
endif
goto _new
endif
for x=0 to 9
text 10,10+(x*20),messages$(x)
next x
sync : loop
endif
if flag=2
show mouse : show window : set window on : set window size 640,480
set window title "RUNNING: "+s$+" - DEDICATED"
cls
messages$(1)="Game started."
messages$(2)="type 'say<space>message to send a message to players."
m=3
clear entry buffer
do : cls
hostmessage$=entry$()
text 10,300,hostmessage$
if returnkey()=1
repeat : until returnkey()=0
hostmessage$="<remoteHost: "+name$+"> "+hostmessage$
if m=10
for x=0 to 8
messages$(x)=messages$(x+1)
next x
messages$(9)=hostmessage$
else
messages$(m)=hostmessage$ : inc m
endif
hostmessage$="m"+hostmessage$
send net message string 0,hostmessage$
clear entry buffer
endif
_hostmessages:
get net message
if net message exists()=1
if net message type()=3
message$=net message string$()
if left$(message$,2)="sr"
if host=1
hostmessage$="sm"+str$(id)+","+str$(get memblock size(3))
send net message string 0,hostmessage$
write memblock byte 3,0,id
send net message memblock 0,3,0
endif
endif
if left$(message$,1)="m"
message$=right$(message$,len(message$)-1)
if m=10
for x=0 to 8
messages$(x)=messages$(x+1)
next x
messages$(9)=message$
else
messages$(m)=message$ : inc m
endif
endif
endif
endif
for x=0 to 9
text 10,10+(x*20),messages$(x)
next x
sync : loop
endif
_build:
done=0
x=1
repeat
obj=memblock byte(3,x) : inc x
select obj
case 1
n=memblock byte(3,x) : inc x
w#=memblock float(3,x) : x=x+4
h#=memblock float(3,x) : x=x+4
x#=memblock float(3,x) : x=x+4
y#=memblock float(3,x) : x=x+4
z#=memblock float(3,x) : x=x+4
ax#=memblock float(3,x) : x=x+4
ay#=memblock float(3,x) : x=x+4
az#=memblock float(3,x) : x=x+4
make object plain n,w#,h#
position object n,x#,y#,z#
rotate object n,ax#,ay#,az#
endcase
case 2
n=memblock byte(3,x) : inc x
s#=memblock float(3,x) : x=x+4
x#=memblock float(3,x) : x=x+4
y#=memblock float(3,x) : x=x+4
z#=memblock float(3,x) : x=x+4
ax#=memblock float(3,x) : x=x+4
ay#=memblock float(3,x) : x=x+4
az#=memblock float(3,x) : x=x+4
make object cube n,s#
position object n,x#,y#,z#
rotate object n,ax#,ay#,az#
endcase
case 3
n=memblock byte(3,x) : inc x
w#=memblock float(3,x) : x=x+4
h#=memblock float(3,x) : x=x+4
d#=memblock float(3,x) : x=x+4
x#=memblock float(3,x) : x=x+4
y#=memblock float(3,x) : x=x+4
z#=memblock float(3,x) : x=x+4
ax#=memblock float(3,x) : x=x+4
ay#=memblock float(3,x) : x=x+4
az#=memblock float(3,x) : x=x+4
make object box n,w#,h#,d#
position object n,x#,y#,z#
rotate object n,ax#,ay#,az#
endcase
case 4
n=memblock byte(3,x) : inc x
s#=memblock float(3,x) : x=x+4
x#=memblock float(3,x) : x=x+4
y#=memblock float(3,x) : x=x+4
z#=memblock float(3,x) : x=x+4
ax#=memblock float(3,x) : x=x+4
ay#=memblock float(3,x) : x=x+4
az#=memblock float(3,x) : x=x+4
make object sphere n,s#
position object n,x#,y#,z#
rotate object n,ax#,ay#,az#
endcase
case 5
n=memblock byte(3,x) : inc x
s#=memblock float(3,x) : x=x+4
x#=memblock float(3,x) : x=x+4
y#=memblock float(3,x) : x=x+4
z#=memblock float(3,x) : x=x+4
ax#=memblock float(3,x) : x=x+4
ay#=memblock float(3,x) : x=x+4
az#=memblock float(3,x) : x=x+4
make object cylinder n,s#
position object n,x#,y#,z#
rotate object n,ax#,ay#,az#
endcase
endselect
if x=tc then done=1
until done=1
return
`LEAVING GAME============================
remstart
mymessage$="sl"+str$(id)
send net message string 0,mymessage$
end
remend
It is severely commented. If you start reading it, and it seems like your not understanding it, don't get frustrated because that's how it is supposed to be. Because you may understand why a certain type of message was sent, until you get to the part where the other players use it. If you read it carefully, and read all the comments, no one should have any problem with it.
I have tested this program connecting with other comps and it works fine. But you may also, for now, test this program, by first running it and hosting, run app again and connect to yourself. If you connect to yourself, I would reccomend not making it dedicated.
Here is the map maker for you to create a simple map to test:
input "size of memblock ",s : s=s+2
make memblock 1,s : write memblock byte 1,0,0
cls
sync on : sync rate 30 : hide mouse : autocam off : backdrop on
o=0
dim ob(s-1)
for x=0 to s-2
ob(x)=0
next x
x=1
do
rotate camera camera angle x(0)+mousemovey(),camera angle y(0)+mousemovex(),0
control camera using arrowkeys 0,2,2
if spacekey()=1 then goto _done
set cursor 0,0
print "(1)make plain"
print "(2)make cube"
print "(3)make box"
print "(4)make cylinder"
print "(5)make sphere"
k$=inkey$()
select k$
case "1"
sync off : sync
input "width ",w#
input "height ",h#
input "x ",x#
input "y ",y#
input "z ",z#
input "ax ",ax#
input "ay ",ay#
input "az ",az#
make object plain o+1,w#,h#
position object o+1,x#,y#,z#
rotate object o+1,ax#,ay#,az#
write memblock byte 1,x,1 : inc x
write memblock byte 1,x,(o+100) : inc x
write memblock float 1,x,w# : x=x+4
write memblock float 1,x,h# : x=x+4
write memblock float 1,x,x# : x=x+4
write memblock float 1,x,y# : x=x+4
write memblock float 1,x,z# : x=x+4
write memblock float 1,x,ax# : x=x+4
write memblock float 1,x,ay# : x=x+4
write memblock float 1,x,az# : x=x+4
inc o
sync on : sync rate 30
endcase
case "2"
sync off : sync
input "size ",s#
input "x ",x#
input "y ",y#
input "z ",z#
input "ax ",ax#
input "ay ",ay#
input "az ",az#
make object cube o+1,s#
position object o+1,x#,y#,z#
rotate object o+1,ax#,ay#,az#
write memblock byte 1,x,2 : inc x
write memblock byte 1,x,(o+100) : inc x
write memblock float 1,x,s# : x=x+4
write memblock float 1,x,x# : x=x+4
write memblock float 1,x,y# : x=x+4
write memblock float 1,x,z# : x=x+4
write memblock float 1,x,ax# : x=x+4
write memblock float 1,x,ay# : x=x+4
write memblock float 1,x,az# : x=x+4
inc o
sync on : sync rate 30
endcase
case "3"
sync off : sync
input "width ",w#
input "height ",h#
input "depth ",d#
input "x ",x#
input "y ",y#
input "z ",z#
input "ax ",ax#
input "ay ",ay#
input "az ",az#
make object box o+1,w#,h#,d#
position object o+1,x#,y#,z#
rotate object o+1,ax#,ay#,az#
write memblock byte 1,x,3 : inc x
write memblock byte 1,x,(o+100) : inc x
write memblock float 1,x,w# : x=x+4
write memblock float 1,x,h# : x=x+4
write memblock float 1,x,d# : x=x+4
write memblock float 1,x,x# : x=x+4
write memblock float 1,x,y# : x=x+4
write memblock float 1,x,z# : x=x+4
write memblock float 1,x,ax# : x=x+4
write memblock float 1,x,ay# : x=x+4
write memblock float 1,x,az# : x=x+4
inc o
sync on : sync rate 30
endcase
case "4"
sync off : sync
input "size ",s#
input "x ",x#
input "y ",y#
input "z ",z#
input "ax ",ax#
input "ay ",ay#
input "az ",az#
make object sphere o+1,s#
position object o+1,x#,y#,z#
rotate object o+1,ax#,ay#,az#
write memblock byte 1,x,4 : inc x
write memblock byte 1,x,(o+100) : inc x
write memblock float 1,x,s# : x=x+4
write memblock float 1,x,x# : x=x+4
write memblock float 1,x,y# : x=x+4
write memblock float 1,x,z# : x=x+4
write memblock float 1,x,ax# : x=x+4
write memblock float 1,x,ay# : x=x+4
write memblock float 1,x,az# : x=x+4
inc o
sync on : sync rate 30
endcase
case "5"
sync off : sync
input "size ",s#
input "x ",x#
input "y ",y#
input "z ",z#
input "ax ",ax#
input "ay ",ay#
input "az ",az#
make object cylinder o+1,s#
position object o+1,x#,y#,z#
rotate object o+1,ax#,ay#,az#
write memblock byte 1,x,5 : inc x
write memblock byte 1,x,(o+100) : inc x
write memblock float 1,x,s# : x=x+4
write memblock float 1,x,x# : x=x+4
write memblock float 1,x,y# : x=x+4
write memblock float 1,x,z# : x=x+4
write memblock float 1,x,ax# : x=x+4
write memblock float 1,x,ay# : x=x+4
write memblock float 1,x,az# : x=x+4
inc o
sync on : sync rate 30
endcase
endselect
sync : loop
_done:
sync off : sync
input "save file as ",file$
open to write 1,file$
make file from memblock 1,1
close file 1
print "done"
This is just a simple program for you to make cheap maps, for testing, it's capabilities. In my map maker, the only objects you can make are plain, cube, box, sphere, cylinder respectively. If you want more objects then that I'm sure you can figure out how to add them, but if you do use custom objects all players must own the objects, not just host.
To get started I would just first run the map maker, when it starts
press "1" then enter then following:
100
100
0
0
0
90
0
0
This will create a plain width=100 height=100 at coordinates (0,0,0)
and rotated 90 degrees on the x axis. then hit the space bar to save the map, as "test" for example.
then run the multiplayer program, host the first time and load the "test" map, then run program again and connect to yourself. You can see that when you join the server, the program never loads a map. It gets the information directly from the host.