Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ///////////////// GAME/CLIENT.SGS //////////////////
- include "network.sgs";
- global NC_State =
- {
- connected = false,
- server_addr = null,
- svtime = 0,
- cltime = 0,
- rtt = 0,
- entities = [],
- };
- function C_Send( type, data )
- {
- Socket.sendto( Serialize_Packet( type, data ), NC_State.server_addr );
- }
- function C_Disconnect( last )
- {
- last ||= false;
- if( !NC_State.connected || !NC_State.server_addr )
- return;
- C_Send( MT_Detach, "" );
- if( !last )
- {
- NC_State.connected = false;
- NC_State.server_addr = null;
- }
- }
- function C_Connect( ip, port )
- {
- if( NC_State.connected )
- C_Disconnect();
- NC_State.server_addr = socket_address( AF_INET, ip, port );
- C_Send( MT_Connect, "" );
- }
- function C_SendInput( sample )
- {
- C_Send( MT_Input, Serialize_Input( sample ) );
- }
- function C_SendConfig( key, value )
- {
- C_Send( MT_Config, Serialize_SendConfig( key, value ) );
- }
- function C_ReceivePacket()
- {
- (data,addr) = Socket.recvfrom( MAX_PACKET_SIZE );
- if( !data )
- return false;
- header = fmt_unpack( "lc", data );
- return
- {
- id = header[0],
- type = header[1],
- data = string_part( data, 5 ),
- addr = addr,
- is_server = NC_State.server_addr == addr,
- };
- }
- function C_DefMsgProc( packet )
- {
- if( packet.type == MT_Respond )
- {
- println( "Connected!" );
- NC_State.connected = true;
- }
- if( packet.type == MT_TimeCast )
- {
- time = ftime();
- times = Unserialize_TimeData( packet.data );
- if( times[0] > NC_State.svtime )
- {
- NC_State.svtime = times[0];
- NC_State.cltime = time;
- NC_State.rtt = times[1];
- println(times);
- C_Send( MT_TimeAck, Serialize_TimeData( times[0], time ) );
- }
- }
- }
- ///////////////// GAME/NETWORK.SGS //////////////////
- include "string", "fmt", "sgssockets";
- global
- // Common messages
- MT_Ack = 1, // receival confirmation messages
- MT_Detach = 2, // notify other side before disconnecting
- MT_Config = 3, // send a configuration item
- // Client messages
- MT_Connect = 101, // ask for connection to server
- MT_Input = 102, // send input data
- MT_TimeAck = 103, // reply with both times
- // Server messages
- MT_Respond = 201, // respond to connection request
- MT_State = 202, // send state data
- MT_TimeCast = 203; // send server time to clients
- global
- MA_MoveLf = 1<<0,
- MA_MoveUp = 1<<1,
- MA_MoveRt = 1<<2,
- MA_MoveDn = 1<<3,
- MA_Shoot = 1<<4;
- global MAX_PACKET_SIZE = 512;
- global PACKET_HDR_SIZE = 5;
- global Packet_ID = 0;
- global Socket = socket_udp();
- Socket.blocking = false;
- // SERIALIZE
- function Serialize_String( str )
- {
- str = tostring( str );
- return fmt_pack( "c", str.length ) $ str;
- }
- function Serialize_Packet( type, data )
- {
- var pid = Packet_ID++;
- return fmt_pack( "lc", pid, type ) $ data;
- }
- function Serialize_SendConfig( key, value )
- {
- return Serialize_String( key ) $ Serialize_String( value );
- }
- function Serialize_Input( input )
- {
- return fmt_pack( "l", input );
- }
- function Unserialize_Input( data )
- {
- if( data.length < 4 )
- return 0;
- return fmt_unpack( "l", data )[0];
- }
- function Serialize_StateList( list )
- {
- out = [];
- foreach( item : list )
- out.push( fmt_pack( "lc", item[0], item[1] ) $ serialize( item[2] ) );
- return out;
- }
- function MakeChunks_StateList( time, list )
- {
- ct = fmt_pack( "d", time );
- out = [];
- cur = ct;
- foreach( item : list )
- {
- item = fmt_pack( "c", item.length ) $ item;
- if( cur.length + item.length + PACKET_HDR_SIZE + 8 > MAX_PACKET_SIZE )
- {
- out.push( cur );
- cur = ct;
- }
- cur $= item;
- }
- if( cur != ct )
- out.push( cur );
- return out;
- }
- function Unserialize_StateList( data )
- {
- out = [];
- if( data.length < 8 )
- return out, 0;
- time = fmt_unpack( "d", data )[0];
- i = 8;
- while( i < data.length )
- {
- size = string_charcode( data, i++ );
- hdr = fmt_unpack( "lc", string_part( data, i ) );
- val = unserialize( string_part( data, i + 5, size - 5 ) );
- i += size;
- hdr.push( val );
- out.push( hdr );
- }
- return out, time;
- }
- function Serialize_TimeData( time1, time2 )
- {
- return fmt_pack( "dd", time1, time2 );
- }
- function Unserialize_TimeData( data )
- {
- if( data.length != 16 )
- return [0,0];
- return fmt_unpack( "dd", data );
- }
- ///////////////// GAME/SERVER.SGS //////////////////
- include "network.sgs";
- global NS_State =
- {
- clients = [],
- max_clients = 16,
- svtime = 0,
- entities =
- [
- {
- id = 1,
- time = 0,
- rtt = 0,
- vars =
- [
- 50, 50
- ],
- },
- ],
- };
- function S_SendTo( addr, type, data )
- {
- Socket.sendto( Serialize_Packet( type, data ), addr );
- }
- function S_Send( client, type, data )
- {
- Socket.sendto( Serialize_Packet( type, data ), NS_State.clients[ client ].addr );
- }
- function S_SendToAll( type, data )
- {
- packet = Serialize_Packet( type, data );
- foreach( client : NS_State.clients )
- Socket.sendto( packet, client.addr );
- }
- function S_Detach( client )
- {
- S_Send( client, MT_Detach, "" );
- }
- function S_SendState( client, statechunk )
- {
- S_Send( client, MT_State, statechunk );
- }
- function S_SendConfig( key, value, cid )
- {
- srlzd = Serialize_SendConfig( key, value );
- if( cid !== null )
- S_Send( cid, MT_Config, srlzd );
- else
- S_SendToAll( MT_Config, srlzd );
- }
- function S_Respond( addr, allow )
- {
- S_SendTo( addr, MT_Respond, if(allow,"Y","N") );
- }
- function S_ReceivePacket()
- {
- (data,addr) = Socket.recvfrom( MAX_PACKET_SIZE );
- if( !data )
- return false;
- has_client = false;
- header = fmt_unpack( "lc", data );
- foreach( cid, cdata : NS_State.clients )
- {
- if( cdata.addr == addr )
- {
- has_client = true;
- break;
- }
- }
- if( !has_client )
- {
- cid = null;
- cdata = null;
- }
- return
- {
- id = header[0],
- type = header[1],
- data = string_part( data, 5 ),
- addr = addr,
- client_id = cid,
- client_data = cdata,
- };
- }
- function S_CreateClient( addr )
- {
- return
- {
- addr = addr,
- input = 0,
- time = 0,
- rtt = 0,
- };
- }
- println( "MPTest server @ 8378" );
- Socket.bind( 8378 );
- _T.set( "initialized", true );
- for(;;)
- {
- if( _T.get( "quit" ) )
- break;
- cmd = _T.get( "command" );
- if( cmd )
- {
- if( cmd == "status" )
- printvar( NS_State );
- _T.set( "command", null );
- }
- if( _T.get("sleepmode") )
- sleep( 1 );
- // MAIN LOOP
- curtime = ftime();
- // - work the entities
- global lastupdate;
- if( !isset( _G, "lastupdate" ) )
- lastupdate = 0;
- if( curtime - lastupdate > 1.0/2.0 )
- lastupdate = curtime - 1.0/2.0;
- while( curtime > lastupdate + 1.0/30.0 )
- {
- foreach( entity : NS_State.entities )
- {
- foreach( client : NS_State.clients )
- {
- entity.vars[0] += ( ( client.input & MA_MoveRt != 0 ) - ( client.input & MA_MoveLf != 0 ) ) * 10;
- entity.vars[1] += ( ( client.input & MA_MoveDn != 0 ) - ( client.input & MA_MoveUp != 0 ) ) * 10;
- }
- }
- lastupdate += 1.0/30.0;
- }
- // - entity sync
- global lastentitysync;
- if( !isset( _G, "lastentitysync" ) )
- lastentitysync = 0;
- if( curtime > lastentitysync + 1.0/5.0 )
- {
- statelist = [];
- foreach( entity : NS_State.entities )
- {
- estates = [];
- foreach( evid, ev : entity.vars )
- estates.push([ entity.id, evid, ev ]);
- statelist = get_concat( statelist, Serialize_StateList( estates ) );
- }
- chunks = MakeChunks_StateList( curtime, statelist );
- foreach( chunk : chunks )
- {
- foreach( cid ,: NS_State.clients )
- S_SendState( cid, chunk );
- }
- lastentitysync = curtime;
- }
- // - time sync
- global lasttimesync;
- if( !isset( _G, "lasttimesync" ) )
- lasttimesync = 0;
- if( curtime > lasttimesync + 1.0 )
- {
- NS_State.svtime = curtime;
- foreach( cid, client : NS_State.clients )
- S_Send( cid, MT_TimeCast, Serialize_TimeData( curtime, client.rtt ) );
- lasttimesync = curtime;
- }
- // MAIN LOOP END
- // NETWORKING
- packet = S_ReceivePacket();
- if( !packet )
- {
- if( !NS_State.clients.size )
- sleep( 8 );
- continue;
- }
- wrote = true;
- if( packet.type == MT_Connect )
- {
- println( "Connection request from " $ packet.addr );
- allow = true;
- if( NS_State.clients.size >= NS_State.max_clients )
- {
- println( "-> Too many connections" );
- allow = false;
- }
- else
- {
- println( "-> Accepted" );
- NS_State.clients.push( S_CreateClient( packet.addr ) );
- }
- S_Respond( packet.addr, allow );
- }
- else if( packet.type == MT_Detach )
- {
- if( packet.client_id !== null )
- {
- println( "Disconnected: " $ packet.addr );
- NS_State.clients.erase( packet.client_id );
- }
- else
- wrote = false;
- }
- else if( packet.type == MT_Input )
- {
- if( packet.client_id !== null )
- packet.client_data.input = Unserialize_Input( packet.data );
- wrote = false;
- }
- else if( packet.type == MT_TimeAck )
- {
- if( packet.client_id !== null )
- {
- times = Unserialize_TimeData( packet.data );
- if( times[0] == NS_State.svtime )
- {
- packet.client_data.time = times[1];
- packet.client_data.rtt = ftime() - times[0];
- println([packet.client_data.time,packet.client_data.rtt]);
- }
- }
- wrote = false;
- }
- else
- {
- println( "UNKNOWN PACKET" );
- printvar( packet );
- }
- if( wrote )
- print( "> " );
- }
- ///////////////// MAIN.SGS //////////////////
- include "fmt", "engine/all.sgs", "game/client.sgs";
- function configure()
- {
- global sys_exit;
- for( i = 0; i < sys_args.size; ++i )
- {
- var arg = sys_args[ i ];
- if( arg == "-profile" )
- {
- enable_profiler();
- println( "PROFILER ENABLED" );
- }
- else if( arg == "-profile-ops" )
- {
- enable_profiler2();
- println( "PROFILER [mode 2] ENABLED" );
- }
- }
- }
- // global W, H, W1 = 1024, H1 = 576, F1 = "", W2 = 1600, H2 = 900, F2 = "", which = 2;
- global W, H, W1 = 1024, H1 = 576, F1 = "", W2 = 1024, H2 = 576, F2 = "vsync", which = 2;
- global X = 100, Y = 100;
- function switch()
- {
- global W, H, W1, H1, F1, W2, H2, F2, which;
- which = 3 - which;
- if( which == 1 )
- {
- set_video_mode( W1, H1, 32, F1 );
- W = W1; H = H1;
- }
- else
- {
- set_video_mode( W2, H2, 32, F2 );
- W = W2; H = H2;
- }
- }
- function initialize()
- {
- // global variables
- global lasttime = ftime();
- global mpos = [0,0];
- global keys = [];
- keys.resize( SDLK_LAST );
- // initialize rendering
- set_caption( "MP Test" );
- printvar( list_video_modes("fullscreen") );
- set_gl_attrib( SDL_GL_DEPTH_SIZE, 24 );
- set_gl_attrib( SDL_GL_STENCIL_SIZE, 8 );
- switch();
- global UI = UIFrame.create( 1024, 576 );
- // UI.addChild( UIControl.createButton( "Make it rain!", 10, 10, 120, 40, function(){} ) );
- global image = create_texture( "crosshair.png", "mipmaps" );
- global Font = create_font( "verdana.ttf", 12 );
- // initialize MP
- C_Connect( "127.0.0.1", 8378 );
- }
- function cleanup()
- {
- // won't have a chance to send these later
- C_Disconnect( true );
- C_Disconnect( true );
- C_Disconnect( true );
- }
- global X=0, Y=0, T=0, PX=0, PY=0, PT=-10000, CX=0, CY=0, CT=-10000;
- function update()
- {
- global lasttime, rotation, P, W, H;
- var curtime = ftime();
- var delta = curtime - lasttime;
- lasttime = curtime;
- if( delta > 1.0/15.0 )
- delta = 1.0/15.0;
- global X, Y, T, PX, PY, PT, CX, CY, CT;
- // MULTIPLAYER
- stateupdate = false;
- packet = C_ReceivePacket();
- if( packet )
- {
- if( packet.type == MT_State )
- {
- (pkstate,pktime) = Unserialize_StateList( packet.data );
- if( pktime > PT )
- {
- stateupdate = true;
- PX = CX;
- PY = CY;
- PT = CT;
- foreach( svar : pkstate )
- {
- CT = pktime;
- if( svar[1] == 0 )
- CX = svar[2];
- else if( svar[1] == 1 )
- CY = svar[2];
- }
- }
- }
- C_DefMsgProc( packet );
- }
- input = 0;
- if( keys[ SDLK_W ] ) input |= MA_MoveUp;
- if( keys[ SDLK_A ] ) input |= MA_MoveLf;
- if( keys[ SDLK_S ] ) input |= MA_MoveDn;
- if( keys[ SDLK_D ] ) input |= MA_MoveRt;
- if( keys[ SDLK_SPACE ] ) input |= MA_Shoot;
- if( NC_State.connected )
- {
- global lastinputnotification;
- if( !isset( _G, "lastinputnotification" ) )
- lastinputnotification = 0;
- if( curtime > lastinputnotification + 1.0/30.0 )
- {
- C_SendInput( input );
- lastinputnotification = curtime;
- }
- }
- // TICK
- // - work the entities
- global lastupdate;
- if( !isset( _G, "lastupdate" ) )
- lastupdate = 0;
- if( curtime - lastupdate > 1.0/2.0 )
- lastupdate = curtime - 1.0/2.0;
- while( curtime > lastupdate + 1.0/30.0 )
- {
- X += ( ( input & MA_MoveRt != 0 ) - ( input & MA_MoveLf != 0 ) ) * 10;
- Y += ( ( input & MA_MoveDn != 0 ) - ( input & MA_MoveUp != 0 ) ) * 10;
- lastupdate += 1.0/30.0;
- }
- if( stateupdate )
- {
- X = CX;
- Y = CY;
- if( PT != CT )
- {
- tm = curtime - NC_State.cltime + NC_State.svtime;
- q = ( tm - PT ) / ( CT - PT );
- X = ( CX - PX ) * q + PX;
- Y = ( CY - PY ) * q + PY;
- }
- }
- // RENDERING
- clear([0.1,0.2,0.4]);
- // Game VIEW
- set_camera_2d( 500, 500, 500, W/H, 0 );
- // ...
- // UI VIEW
- set_camera_ui( 0, W, 0, H );
- draw({ preset = "box", texture = image, position = [X,Y], scale = [64,64], color = [0.3,0.5,0.7,1] });
- UI.draw();
- tx = "frame time: " $ ( ftime() - lasttime ) * 1000.0 $ " ms";
- draw_text_line( tx, Font, 101, 1, [0,0,0,1] );
- draw_text_line( tx, Font, 100, 0, [0.9,0.8,0.7,1] );
- present();
- sleeptime = 15 - ( ftime() - lasttime ) * 1000;
- // if( sleeptime > 0 ) sleep( sleeptime );
- sleep( 5 );
- }
- function on_event( e )
- {
- global keys;
- if( e.type == SDL_QUIT )
- global sys_exit = true;
- if( e.type == SDL_MOUSEMOTION )
- {
- global mpos = [e.x,e.y];
- // println( get_relative_mouse_state() );
- }
- if( e.type == SDL_KEYDOWN || e.type == SDL_KEYUP )
- keys[ e.keycode ] = e.type == SDL_KEYDOWN;
- if( e.type == SDL_KEYDOWN && e.keycode == SDLK_F11 )
- switch();
- if( e.type == SDL_VIDEO_DEVICELOST ) println( "Device lost!" );
- if( e.type == SDL_VIDEO_DEVICERESET ) println( "Device reset!" );
- UI.event( e );
- }
- ///////////////// SERVER.SGS //////////////////
- include "sgspproc", "string";
- P = pproc_create();
- job = P.add_job(function()
- {
- include "game/server.sgs";
- });
- job.set( "quit", false );
- job.set( "initialized", false );
- job.set( "command", null );
- job.set( "sleepmode", true );
- job.start();
- while( !job.get( "initialized" ) )
- sleep( 1 );
- for(;;)
- {
- print "> ";
- line = read_stdin();
- if( line == "quit" )
- {
- job.set( "quit", true );
- break;
- }
- else if( string_part( line, 0, 4 ) == "set " )
- {
- kv = string_explode( string_trim( string_part( line, 4 ) ), " " );
- key = kv.shift();
- value = eval( "return " $ string_implode( kv, " " ) $ ";" );
- job.set( key, value );
- println( key $ " = " $ value );
- }
- else
- {
- job.set( "command", line );
- while( job.get( "command" ) )
- sleep( 1 );
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement