Advertisement
snake5

mptest - unfinished code

Jul 10th, 2014
408
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ///////////////// GAME/CLIENT.SGS //////////////////
  2.  
  3. include "network.sgs";
  4.  
  5.  
  6. global NC_State =
  7. {
  8.     connected = false,
  9.     server_addr = null,
  10.     svtime = 0,
  11.     cltime = 0,
  12.     rtt = 0,
  13.     entities = [],
  14. };
  15.  
  16.  
  17. function C_Send( type, data )
  18. {
  19.     Socket.sendto( Serialize_Packet( type, data ), NC_State.server_addr );
  20. }
  21.  
  22. function C_Disconnect( last )
  23. {
  24.     last ||= false;
  25.    
  26.     if( !NC_State.connected || !NC_State.server_addr )
  27.         return;
  28.     C_Send( MT_Detach, "" );
  29.     if( !last )
  30.     {
  31.         NC_State.connected = false;
  32.         NC_State.server_addr = null;
  33.     }
  34. }
  35.  
  36. function C_Connect( ip, port )
  37. {
  38.     if( NC_State.connected )
  39.         C_Disconnect();
  40.    
  41.     NC_State.server_addr = socket_address( AF_INET, ip, port );
  42.     C_Send( MT_Connect, "" );
  43. }
  44.  
  45. function C_SendInput( sample )
  46. {
  47.     C_Send( MT_Input, Serialize_Input( sample ) );
  48. }
  49.  
  50. function C_SendConfig( key, value )
  51. {
  52.     C_Send( MT_Config, Serialize_SendConfig( key, value ) );
  53. }
  54.  
  55. function C_ReceivePacket()
  56. {
  57.     (data,addr) = Socket.recvfrom( MAX_PACKET_SIZE );
  58.     if( !data )
  59.         return false;
  60.    
  61.     header = fmt_unpack( "lc", data );
  62.    
  63.     return
  64.     {
  65.         id = header[0],
  66.         type = header[1],
  67.         data = string_part( data, 5 ),
  68.         addr = addr,
  69.         is_server = NC_State.server_addr == addr,
  70.     };
  71. }
  72.  
  73.  
  74. function C_DefMsgProc( packet )
  75. {
  76.     if( packet.type == MT_Respond )
  77.     {
  78.         println( "Connected!" );
  79.         NC_State.connected = true;
  80.     }
  81.     if( packet.type == MT_TimeCast )
  82.     {
  83.         time = ftime();
  84.         times = Unserialize_TimeData( packet.data );
  85.         if( times[0] > NC_State.svtime )
  86.         {
  87.             NC_State.svtime = times[0];
  88.             NC_State.cltime = time;
  89.             NC_State.rtt = times[1];
  90.             println(times);
  91.             C_Send( MT_TimeAck, Serialize_TimeData( times[0], time ) );
  92.         }
  93.     }
  94. }
  95.  
  96. ///////////////// GAME/NETWORK.SGS //////////////////
  97.  
  98. include "string", "fmt", "sgssockets";
  99.  
  100.  
  101. global
  102.     // Common messages
  103.     MT_Ack      = 1,    // receival confirmation messages
  104.     MT_Detach   = 2,    // notify other side before disconnecting
  105.     MT_Config   = 3,    // send a configuration item
  106.     // Client messages
  107.     MT_Connect  = 101,  // ask for connection to server
  108.     MT_Input    = 102,  // send input data
  109.     MT_TimeAck  = 103,  // reply with both times
  110.     // Server messages
  111.     MT_Respond  = 201,  // respond to connection request
  112.     MT_State    = 202,  // send state data
  113.     MT_TimeCast = 203;  // send server time to clients
  114.  
  115. global
  116.     MA_MoveLf = 1<<0,
  117.     MA_MoveUp = 1<<1,
  118.     MA_MoveRt = 1<<2,
  119.     MA_MoveDn = 1<<3,
  120.     MA_Shoot  = 1<<4;
  121.  
  122. global MAX_PACKET_SIZE = 512;
  123. global PACKET_HDR_SIZE = 5;
  124.  
  125. global Packet_ID = 0;
  126. global Socket = socket_udp();
  127. Socket.blocking = false;
  128.  
  129.  
  130. // SERIALIZE
  131. function Serialize_String( str )
  132. {
  133.     str = tostring( str );
  134.     return fmt_pack( "c", str.length ) $ str;
  135. }
  136.  
  137. function Serialize_Packet( type, data )
  138. {
  139.     var pid = Packet_ID++;
  140.     return fmt_pack( "lc", pid, type ) $ data;
  141. }
  142.  
  143. function Serialize_SendConfig( key, value )
  144. {
  145.     return Serialize_String( key ) $ Serialize_String( value );
  146. }
  147.  
  148.  
  149. function Serialize_Input( input )
  150. {
  151.     return fmt_pack( "l", input );
  152. }
  153.  
  154. function Unserialize_Input( data )
  155. {
  156.     if( data.length < 4 )
  157.         return 0;
  158.     return fmt_unpack( "l", data )[0];
  159. }
  160.  
  161.  
  162. function Serialize_StateList( list )
  163. {
  164.     out = [];
  165.     foreach( item : list )
  166.         out.push( fmt_pack( "lc", item[0], item[1] ) $ serialize( item[2] ) );
  167.     return out;
  168. }
  169.  
  170. function MakeChunks_StateList( time, list )
  171. {
  172.     ct = fmt_pack( "d", time );
  173.     out = [];
  174.     cur = ct;
  175.     foreach( item : list )
  176.     {
  177.         item = fmt_pack( "c", item.length ) $ item;
  178.         if( cur.length + item.length + PACKET_HDR_SIZE + 8 > MAX_PACKET_SIZE )
  179.         {
  180.             out.push( cur );
  181.             cur = ct;
  182.         }
  183.         cur $= item;
  184.     }
  185.     if( cur != ct )
  186.         out.push( cur );
  187.     return out;
  188. }
  189.  
  190. function Unserialize_StateList( data )
  191. {
  192.     out = [];
  193.     if( data.length < 8 )
  194.         return out, 0;
  195.     time = fmt_unpack( "d", data )[0];
  196.     i = 8;
  197.     while( i < data.length )
  198.     {
  199.         size = string_charcode( data, i++ );
  200.         hdr = fmt_unpack( "lc", string_part( data, i ) );
  201.         val = unserialize( string_part( data, i + 5, size - 5 ) );
  202.         i += size;
  203.         hdr.push( val );
  204.         out.push( hdr );
  205.     }
  206.     return out, time;
  207. }
  208.  
  209. function Serialize_TimeData( time1, time2 )
  210. {
  211.     return fmt_pack( "dd", time1, time2 );
  212. }
  213. function Unserialize_TimeData( data )
  214. {
  215.     if( data.length != 16 )
  216.         return [0,0];
  217.     return fmt_unpack( "dd", data );
  218. }
  219.  
  220.  
  221.  
  222. ///////////////// GAME/SERVER.SGS //////////////////
  223.  
  224. include "network.sgs";
  225.  
  226.  
  227. global NS_State =
  228. {
  229.     clients = [],
  230.     max_clients = 16,
  231.     svtime = 0,
  232.     entities =
  233.     [
  234.         {
  235.             id = 1,
  236.             time = 0,
  237.             rtt = 0,
  238.             vars =
  239.             [
  240.                 50, 50
  241.             ],
  242.         },
  243.     ],
  244. };
  245.  
  246.  
  247. function S_SendTo( addr, type, data )
  248. {
  249.     Socket.sendto( Serialize_Packet( type, data ), addr );
  250. }
  251.  
  252. function S_Send( client, type, data )
  253. {
  254.     Socket.sendto( Serialize_Packet( type, data ), NS_State.clients[ client ].addr );
  255. }
  256.  
  257. function S_SendToAll( type, data )
  258. {
  259.     packet = Serialize_Packet( type, data );
  260.     foreach( client : NS_State.clients )
  261.         Socket.sendto( packet, client.addr );
  262. }
  263.  
  264. function S_Detach( client )
  265. {
  266.     S_Send( client, MT_Detach, "" );
  267. }
  268.  
  269. function S_SendState( client, statechunk )
  270. {
  271.     S_Send( client, MT_State, statechunk );
  272. }
  273.  
  274. function S_SendConfig( key, value, cid )
  275. {
  276.     srlzd = Serialize_SendConfig( key, value );
  277.     if( cid !== null )
  278.         S_Send( cid, MT_Config, srlzd );
  279.     else
  280.         S_SendToAll( MT_Config, srlzd );
  281. }
  282.  
  283. function S_Respond( addr, allow )
  284. {
  285.     S_SendTo( addr, MT_Respond, if(allow,"Y","N") );
  286. }
  287.  
  288. function S_ReceivePacket()
  289. {
  290.     (data,addr) = Socket.recvfrom( MAX_PACKET_SIZE );
  291.     if( !data )
  292.         return false;
  293.    
  294.     has_client = false;
  295.     header = fmt_unpack( "lc", data );
  296.     foreach( cid, cdata : NS_State.clients )
  297.     {
  298.         if( cdata.addr == addr )
  299.         {
  300.             has_client = true;
  301.             break;
  302.         }
  303.     }
  304.    
  305.     if( !has_client )
  306.     {
  307.         cid = null;
  308.         cdata = null;
  309.     }
  310.    
  311.     return
  312.     {
  313.         id = header[0],
  314.         type = header[1],
  315.         data = string_part( data, 5 ),
  316.         addr = addr,
  317.         client_id = cid,
  318.         client_data = cdata,
  319.     };
  320. }
  321.  
  322. function S_CreateClient( addr )
  323. {
  324.     return
  325.     {
  326.         addr = addr,
  327.         input = 0,
  328.         time = 0,
  329.         rtt = 0,
  330.     };
  331. }
  332.  
  333.  
  334. println( "MPTest server @ 8378" );
  335.  
  336. Socket.bind( 8378 );
  337.  
  338. _T.set( "initialized", true );
  339.  
  340. for(;;)
  341. {
  342.     if( _T.get( "quit" ) )
  343.         break;
  344.    
  345.     cmd = _T.get( "command" );
  346.     if( cmd )
  347.     {
  348.         if( cmd == "status" )
  349.             printvar( NS_State );
  350.         _T.set( "command", null );
  351.     }
  352.    
  353.     if( _T.get("sleepmode") )
  354.         sleep( 1 );
  355.    
  356.     // MAIN LOOP
  357.     curtime = ftime();
  358.    
  359.     // - work the entities
  360.     global lastupdate;
  361.     if( !isset( _G, "lastupdate" ) )
  362.         lastupdate = 0;
  363.     if( curtime - lastupdate > 1.0/2.0 )
  364.         lastupdate = curtime - 1.0/2.0;
  365.     while( curtime > lastupdate + 1.0/30.0 )
  366.     {
  367.         foreach( entity : NS_State.entities )
  368.         {
  369.             foreach( client : NS_State.clients )
  370.             {
  371.                 entity.vars[0] += ( ( client.input & MA_MoveRt != 0 ) - ( client.input & MA_MoveLf != 0 ) ) * 10;
  372.                 entity.vars[1] += ( ( client.input & MA_MoveDn != 0 ) - ( client.input & MA_MoveUp != 0 ) ) * 10;
  373.             }
  374.         }
  375.         lastupdate += 1.0/30.0;
  376.     }
  377.    
  378.     // - entity sync
  379.     global lastentitysync;
  380.     if( !isset( _G, "lastentitysync" ) )
  381.         lastentitysync = 0;
  382.     if( curtime > lastentitysync + 1.0/5.0 )
  383.     {
  384.         statelist = [];
  385.         foreach( entity : NS_State.entities )
  386.         {
  387.             estates = [];
  388.             foreach( evid, ev : entity.vars )
  389.                 estates.push([ entity.id, evid, ev ]);
  390.             statelist = get_concat( statelist, Serialize_StateList( estates ) );
  391.         }
  392.         chunks = MakeChunks_StateList( curtime, statelist );
  393.         foreach( chunk : chunks )
  394.         {
  395.             foreach( cid ,: NS_State.clients )
  396.                 S_SendState( cid, chunk );
  397.         }
  398.         lastentitysync = curtime;
  399.     }
  400.    
  401.     // - time sync
  402.     global lasttimesync;
  403.     if( !isset( _G, "lasttimesync" ) )
  404.         lasttimesync = 0;
  405.     if( curtime > lasttimesync + 1.0 )
  406.     {
  407.         NS_State.svtime = curtime;
  408.         foreach( cid, client : NS_State.clients )
  409.             S_Send( cid, MT_TimeCast, Serialize_TimeData( curtime, client.rtt ) );
  410.         lasttimesync = curtime;
  411.     }
  412.    
  413.     // MAIN LOOP END
  414.    
  415.     // NETWORKING
  416.     packet = S_ReceivePacket();
  417.     if( !packet )
  418.     {
  419.         if( !NS_State.clients.size )
  420.             sleep( 8 );
  421.         continue;
  422.     }
  423.    
  424.     wrote = true;
  425.     if( packet.type == MT_Connect )
  426.     {
  427.         println( "Connection request from " $ packet.addr );
  428.         allow = true;
  429.         if( NS_State.clients.size >= NS_State.max_clients )
  430.         {
  431.             println( "-> Too many connections" );
  432.             allow = false;
  433.         }
  434.         else
  435.         {
  436.             println( "-> Accepted" );
  437.             NS_State.clients.push( S_CreateClient( packet.addr ) );
  438.         }
  439.         S_Respond( packet.addr, allow );
  440.     }
  441.     else if( packet.type == MT_Detach )
  442.     {
  443.         if( packet.client_id !== null )
  444.         {
  445.             println( "Disconnected: " $ packet.addr );
  446.             NS_State.clients.erase( packet.client_id );
  447.         }
  448.         else
  449.             wrote = false;
  450.     }
  451.     else if( packet.type == MT_Input )
  452.     {
  453.         if( packet.client_id !== null )
  454.             packet.client_data.input = Unserialize_Input( packet.data );
  455.         wrote = false;
  456.     }
  457.     else if( packet.type == MT_TimeAck )
  458.     {
  459.         if( packet.client_id !== null )
  460.         {
  461.             times = Unserialize_TimeData( packet.data );
  462.             if( times[0] == NS_State.svtime )
  463.             {
  464.                 packet.client_data.time = times[1];
  465.                 packet.client_data.rtt = ftime() - times[0];
  466.                 println([packet.client_data.time,packet.client_data.rtt]);
  467.             }
  468.         }
  469.         wrote = false;
  470.     }
  471.     else
  472.     {
  473.         println( "UNKNOWN PACKET" );
  474.         printvar( packet );
  475.     }
  476.    
  477.     if( wrote )
  478.         print( "> " );
  479. }
  480.  
  481. ///////////////// MAIN.SGS //////////////////
  482.  
  483. include "fmt", "engine/all.sgs", "game/client.sgs";
  484.  
  485.  
  486. function configure()
  487. {
  488.     global sys_exit;
  489.    
  490.     for( i = 0; i < sys_args.size; ++i )
  491.     {
  492.         var arg = sys_args[ i ];
  493.         if( arg == "-profile" )
  494.         {
  495.             enable_profiler();
  496.             println( "PROFILER ENABLED" );
  497.         }
  498.         else if( arg == "-profile-ops" )
  499.         {
  500.             enable_profiler2();
  501.             println( "PROFILER [mode 2] ENABLED" );
  502.         }
  503.     }
  504. }
  505.  
  506. // global W, H, W1 = 1024, H1 = 576, F1 = "", W2 = 1600, H2 = 900, F2 = "", which = 2;
  507. global W, H, W1 = 1024, H1 = 576, F1 = "", W2 = 1024, H2 = 576, F2 = "vsync", which = 2;
  508.  
  509. global X = 100, Y = 100;
  510.  
  511. function switch()
  512. {
  513.     global W, H, W1, H1, F1, W2, H2, F2, which;
  514.    
  515.     which = 3 - which;
  516.     if( which == 1 )
  517.     {
  518.         set_video_mode( W1, H1, 32, F1 );
  519.         W = W1; H = H1;
  520.     }
  521.     else
  522.     {
  523.         set_video_mode( W2, H2, 32, F2 );
  524.         W = W2; H = H2;
  525.     }
  526. }
  527.  
  528. function initialize()
  529. {
  530.     // global variables
  531.     global lasttime = ftime();
  532.     global mpos = [0,0];
  533.     global keys = [];
  534.     keys.resize( SDLK_LAST );
  535.    
  536.     // initialize rendering
  537.     set_caption( "MP Test" );
  538.     printvar( list_video_modes("fullscreen") );
  539.     set_gl_attrib( SDL_GL_DEPTH_SIZE, 24 );
  540.     set_gl_attrib( SDL_GL_STENCIL_SIZE, 8 );
  541.     switch();
  542.    
  543.     global UI = UIFrame.create( 1024, 576 );
  544. //  UI.addChild( UIControl.createButton( "Make it rain!", 10, 10, 120, 40, function(){} ) );
  545.    
  546.     global image = create_texture( "crosshair.png", "mipmaps" );
  547.     global Font = create_font( "verdana.ttf", 12 );
  548.    
  549.     // initialize MP
  550.     C_Connect( "127.0.0.1", 8378 );
  551. }
  552.  
  553.  
  554. function cleanup()
  555. {
  556.     // won't have a chance to send these later
  557.     C_Disconnect( true );
  558.     C_Disconnect( true );
  559.     C_Disconnect( true );
  560. }
  561.  
  562.  
  563. global X=0, Y=0, T=0, PX=0, PY=0, PT=-10000, CX=0, CY=0, CT=-10000;
  564.  
  565. function update()
  566. {
  567.     global lasttime, rotation, P, W, H;
  568.     var curtime = ftime();
  569.     var delta = curtime - lasttime;
  570.     lasttime = curtime;
  571.     if( delta > 1.0/15.0 )
  572.         delta = 1.0/15.0;
  573.    
  574.     global X, Y, T, PX, PY, PT, CX, CY, CT;
  575.    
  576.     // MULTIPLAYER
  577.     stateupdate = false;
  578.     packet = C_ReceivePacket();
  579.     if( packet )
  580.     {
  581.         if( packet.type == MT_State )
  582.         {
  583.             (pkstate,pktime) = Unserialize_StateList( packet.data );
  584.             if( pktime > PT )
  585.             {
  586.                 stateupdate = true;
  587.                
  588.                 PX = CX;
  589.                 PY = CY;
  590.                 PT = CT;
  591.                
  592.                 foreach( svar : pkstate )
  593.                 {
  594.                     CT = pktime;
  595.                     if( svar[1] == 0 )
  596.                         CX = svar[2];
  597.                     else if( svar[1] == 1 )
  598.                         CY = svar[2];
  599.                 }
  600.             }
  601.         }
  602.         C_DefMsgProc( packet );
  603.     }
  604.    
  605.     input = 0;
  606.     if( keys[ SDLK_W ] ) input |= MA_MoveUp;
  607.     if( keys[ SDLK_A ] ) input |= MA_MoveLf;
  608.     if( keys[ SDLK_S ] ) input |= MA_MoveDn;
  609.     if( keys[ SDLK_D ] ) input |= MA_MoveRt;
  610.     if( keys[ SDLK_SPACE ] ) input |= MA_Shoot;
  611.    
  612.     if( NC_State.connected )
  613.     {
  614.         global lastinputnotification;
  615.         if( !isset( _G, "lastinputnotification" ) )
  616.             lastinputnotification = 0;
  617.         if( curtime > lastinputnotification + 1.0/30.0 )
  618.         {
  619.             C_SendInput( input );
  620.            
  621.             lastinputnotification = curtime;
  622.         }
  623.     }
  624.    
  625.     // TICK
  626.    
  627.     // - work the entities
  628.     global lastupdate;
  629.     if( !isset( _G, "lastupdate" ) )
  630.         lastupdate = 0;
  631.     if( curtime - lastupdate > 1.0/2.0 )
  632.         lastupdate = curtime - 1.0/2.0;
  633.     while( curtime > lastupdate + 1.0/30.0 )
  634.     {
  635.         X += ( ( input & MA_MoveRt != 0 ) - ( input & MA_MoveLf != 0 ) ) * 10;
  636.         Y += ( ( input & MA_MoveDn != 0 ) - ( input & MA_MoveUp != 0 ) ) * 10;
  637.        
  638.         lastupdate += 1.0/30.0;
  639.     }
  640.     if( stateupdate )
  641.     {
  642.         X = CX;
  643.         Y = CY;
  644.         if( PT != CT )
  645.         {
  646.             tm = curtime - NC_State.cltime + NC_State.svtime;
  647.             q = ( tm - PT ) / ( CT - PT );
  648.             X = ( CX - PX ) * q + PX;
  649.             Y = ( CY - PY ) * q + PY;
  650.         }
  651.     }
  652.     // RENDERING
  653.    
  654.     clear([0.1,0.2,0.4]);
  655.    
  656.     // Game VIEW
  657.     set_camera_2d( 500, 500, 500, W/H, 0 );
  658.    
  659.     // ...
  660.    
  661.     // UI VIEW
  662.     set_camera_ui( 0, W, 0, H );
  663.    
  664.     draw({ preset = "box", texture = image, position = [X,Y], scale = [64,64], color = [0.3,0.5,0.7,1] });
  665.    
  666.     UI.draw();
  667.    
  668.     tx = "frame time: " $ ( ftime() - lasttime ) * 1000.0 $ " ms";
  669.     draw_text_line( tx, Font, 101, 1, [0,0,0,1] );
  670.     draw_text_line( tx, Font, 100, 0, [0.9,0.8,0.7,1] );
  671.    
  672.     present();
  673.  
  674.     sleeptime = 15 - ( ftime() - lasttime ) * 1000;
  675. //  if( sleeptime > 0 ) sleep( sleeptime );
  676.    
  677.     sleep( 5 );
  678. }
  679.  
  680. function on_event( e )
  681. {
  682.     global keys;
  683.     if( e.type == SDL_QUIT )
  684.         global sys_exit = true;
  685.     if( e.type == SDL_MOUSEMOTION )
  686.     {
  687.         global mpos = [e.x,e.y];
  688. //      println( get_relative_mouse_state() );
  689.     }
  690.     if( e.type == SDL_KEYDOWN || e.type == SDL_KEYUP )
  691.         keys[ e.keycode ] = e.type == SDL_KEYDOWN;
  692.     if( e.type == SDL_KEYDOWN && e.keycode == SDLK_F11 )
  693.         switch();
  694.     if( e.type == SDL_VIDEO_DEVICELOST ) println( "Device lost!" );
  695.     if( e.type == SDL_VIDEO_DEVICERESET ) println( "Device reset!" );
  696.  
  697.     UI.event( e );
  698. }
  699.  
  700.  
  701. ///////////////// SERVER.SGS //////////////////
  702.  
  703. include "sgspproc", "string";
  704.  
  705. P = pproc_create();
  706.  
  707.  
  708. job = P.add_job(function()
  709. {
  710.     include "game/server.sgs";
  711. });
  712.  
  713. job.set( "quit", false );
  714. job.set( "initialized", false );
  715. job.set( "command", null );
  716. job.set( "sleepmode", true );
  717. job.start();
  718.  
  719. while( !job.get( "initialized" ) )
  720.     sleep( 1 );
  721.  
  722. for(;;)
  723. {
  724.     print "> ";
  725.     line = read_stdin();
  726.    
  727.     if( line == "quit" )
  728.     {
  729.         job.set( "quit", true );
  730.         break;
  731.     }
  732.     else if( string_part( line, 0, 4 ) == "set " )
  733.     {
  734.         kv = string_explode( string_trim( string_part( line, 4 ) ), " " );
  735.         key = kv.shift();
  736.         value = eval( "return " $ string_implode( kv, " " ) $ ";" );
  737.         job.set( key, value );
  738.         println( key $ " = " $ value );
  739.     }
  740.     else
  741.     {
  742.         job.set( "command", line );
  743.         while( job.get( "command" ) )
  744.             sleep( 1 );
  745.     }
  746. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement