⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sv_ccmds.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
      // clear all the client inuse flags before saving so that
      // when the level is re-entered, the clients will spawn
      // at spawn points instead of occupying body shells
      savedInuse := malloc(Round(maxclients.value) * sizeof(qboolean));
      cl := client_p(svs.clients);
      i := 0;
      while (i < maxclients.value) do
      begin
        savedInuse^[i] := cl^.edict^.inuse;
        cl^.edict^.inuse := false;
        Inc(i);
        Inc(cl);
      end;

      SV_WriteLevelFile();

      // we must restore these for clients to transfer over correctly
      cl := client_p(svs.clients);
      i := 0;
      while (i < maxclients.value) do
      begin
        cl^.edict^.inuse := savedInuse^[i];
        inc(i);
        inc(cl);
      end;
      free(savedInuse);
    end;
  end;

  // start up the next map
  SV_Map(false, Cmd_Argv(1), false);

  // archive server state
  strncpy(@svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd) - 1);

  // copy off the level to the autosave slot
  if not (dedicated.value <> 0) then
  begin
    SV_WriteServerFile(true);
    SV_CopySaveGame('current', 'save0');
  end;
end;

(*
==================================================
SV_Map_f

Goes directly to a given map without any savegame archiving.
For development work
==================================================
*)

procedure SV_Map_f(); cdecl;
var
  map: pchar;
  expanded: array[0..MAX_QPATH - 1] of char;
begin
  // if not a pcx, demo, or cinematic, check to make sure the level exists
  map := Cmd_Argv(1);
  if (not (strstr(map, '.') <> nil)) then
  begin
    Com_sprintf(expanded, sizeof(expanded), 'maps/%s.bsp', [map]);
    if FS_LoadFile(expanded, nil) = -1 then
    begin
      Com_Printf('Can''t find %s'#10, [expanded]);
      exit;
    end;
  end;

  sv.state := ss_dead;                  // don't save current level when changing
  SV_WipeSavegame('current');
  SV_GameMap_f();
end;

(*
==================================================

  SAVEGAMES

==================================================
*)

(*
==================================================
SV_Loadgame_f

==================================================
*)

procedure SV_Loadgame_f(); cdecl;
var
  name: array[0..MAX_OSPATH - 1] of Char;
  f: Integer;
  dir: PChar;
begin
  if (Cmd_Argc() <> 2) then
  begin
    Com_Printf('USAGE: loadgame <directory>'#10, []);
    exit;
  end;

  Com_Printf('Loading game...'#10, []);

  dir := Cmd_Argv(1);
  if (strstr(dir, '..') <> nil) or (strstr(dir, '/') <> nil) or (strstr(dir, '\') <> nil) then
  begin
    Com_Printf('Bad savedir.'#10, []);
  end;

  // make sure the server.ssv file exists
  Com_sprintf(name, sizeof(name), '%s/save/%s/server.ssv', [FS_Gamedir(), Cmd_Argv(1)]);
  f := FileOpen(name, fmOpenRead);
  if (f = -1) then
  begin
    Com_Printf('No such savegame: %s'#10, [name]);
    exit;
  end;
  FileClose(f);

  SV_CopySaveGame(Cmd_Argv(1), 'current');

  SV_ReadServerFile();

  // go to the map
  sv.state := ss_dead;                  // don't save current level when changing
  SV_Map(false, @svs.mapcmd, true);
end;

(*
==================================================
SV_Savegame_f

==================================================
*)

procedure SV_Savegame_f(); cdecl;
var
  dir: pchar;
begin
  if (sv.state <> ss_game) then
  begin
    Com_Printf('You must be in a game to save.'#10, []);
    exit;
  end;

  if (Cmd_Argc() <> 2) then
  begin
    Com_Printf('USAGE: savegame <directory>'#10, []);
    exit;
  end;

  if (Cvar_VariableValue('deathmatch') <> 0) then
  begin
    Com_Printf('Can''t savegame in a deathmatch'#10, []);
    exit;
  end;

  if not (strcmp(Cmd_Argv(1), 'current') <> 0) then
  begin
    Com_Printf('Can''t save to ''current'''#10, []);
    exit;
  end;

  if (maxclients.value = 1) and (svs.clients^[0].edict^.client^.ps.stats[STAT_HEALTH] <= 0) then
  begin
    Com_Printf(#10'Can''t savegame while dead!'#10, []);
    exit;
  end;

  dir := Cmd_Argv(1);
  if (strstr(dir, '..') <> nil) or (strstr(dir, '/') <> nil) or (strstr(dir, '\') <> nil) then
  begin
    Com_Printf('Bad savedir.'#10, []);
  end;

  Com_Printf('Saving game...'#10, []);

  // archive current level, including all client edicts.
  // when the level is reloaded, they will be shells awaiting
  // a connecting client
  SV_WriteLevelFile();

  // save server state
  SV_WriteServerFile(false);

  // copy it off
  SV_CopySaveGame('current', dir);

  Com_Printf('Done.'#10, []);
end;

(*
==================================================
SV_Kick_f

Kick a user off of the server
==================================================
*)

procedure SV_Kick_f(); cdecl;
begin
  if (not svs.initialized) then
  begin
    Com_Printf('No server running.'#10, []);
    exit;
  end;

  if (Cmd_Argc() <> 2) then
  begin
    Com_Printf('Usage: kick <userid>'#10, []);
    exit;
  end;

  if (not SV_SetPlayer()) then
    exit;

  SV_BroadcastPrintf(PRINT_HIGH, '%s was kicked'#10, [sv_client^.name]);
  // print directly, because the dropped client won't get the
  // SV_BroadcastPrintf message
  SV_ClientPrintf(sv_client, PRINT_HIGH, 'You were kicked from the game'#10, []);
  SV_DropClient(sv_client);
  sv_client^.lastmessage := svs.realtime; // min case there is a funny zombie
end;

(*
==================================================
SV_Status_f
==================================================
*)

procedure SV_Status_f; cdecl;
var
  i, j, l: integer;
  cl: client_p;
  s: pchar;
  ping: integer;
label
  continue_;
begin
  if (svs.clients = nil) then
  begin
    Com_Printf('No server running.'#10, []);
    exit;
  end;
  Com_Printf('map              : %s'#10, [sv.name]);

  Com_Printf('num score ping name            lastmsg address               qport '#10, []);
  Com_Printf('--- ----- ---- --------------- ------- --------------------- ------'#10, []);
  i := 0;
  cl := client_p(svs.clients);
  while (i < maxclients.value) do
  begin
    if (Integer(cl.state) = 0) then
      goto continue_;
    Com_Printf('%3i ', [i]);
    Com_Printf('%5i ', [cl^.edict^.client^.ps.stats[STAT_FRAGS]]);

    if (cl^.state = cs_connected) then
      Com_Printf('CNCT ', [])
    else if (cl^.state = cs_zombie) then
      Com_Printf('ZMBI ', [])
    else
    begin
      if cl^.ping < 9999 then
        ping := cl^.ping
      else
        ping := 9999;
      Com_Printf('%4i ', [ping]);
    end;

    Com_Printf('%s', [cl^.name]);
    l := 16 - strlen(cl.name);
    for j := 0 to l - 1 do
      Com_Printf(' ');

    Com_Printf('%7i ', [svs.realtime - cl.lastmessage]);

    s := NET_AdrToString(cl.netchan.remote_address);
    Com_Printf('%s', [s]);
    l := 22 - strlen(s);
    for j := 0 to l - 1 do
      Com_Printf(' ');

    Com_Printf('%5i', [cl.netchan.qport]);

    Com_Printf(#10);
    continue_:
    Inc(i);
    Inc(cl);
  end;
  Com_Printf(#10);
end;

(*
==================================================
SV_ConSay_f
==================================================
*)

procedure SV_ConSay_f; cdecl;
var
  client: client_p;
  j: integer;
  p: pchar;
  text: array[0..1024 - 1] of char;
label
  continue_;
begin
  if (Cmd_Argc() < 2) then
    exit;

  strcpy(text, 'console: ');
  p := Cmd_Args();

  if (p^ = '"') then
  begin
    Inc(p);
    p[strlen(p) - 1] := #0;
  end;

  strcat(text, p);

  j := 0;
  client := client_p(svs.clients);
  while (j < maxclients.value) do
  begin
    if (client^.state <> cs_spawned) then
      goto continue_;
    SV_ClientPrintf(client, PRINT_CHAT, '%s'#10, [text]);
    continue_:
    Inc(j);
    Inc(client);
  end;
end;

(*
==================================================
SV_Heartbeat_f
==================================================
*)

procedure SV_Heartbeat_f; cdecl;
begin
  svs.last_heartbeat := -9999999;
end;

(*
==================================================
SV_Serverinfo_f

  Examine or change the serverinfo string
==================================================
*)

procedure SV_Serverinfo_f; cdecl;
begin
  Com_Printf('Server info settings:'#10);
  Info_Print(Cvar_Serverinfo_());
end;

(*
==================================================
SV_DumpUser_f

Examine all a users info strings
==================================================
*)

procedure SV_DumpUser_f; cdecl;
begin
  if (Cmd_Argc() <> 2) then
  begin
    Com_Printf('Usage: info <userid>'#10);
    exit;
  end;

  if (not SV_SetPlayer()) then
    exit;

  Com_Printf('userinfo'#10);
  Com_Printf('--------'#10);
  Info_Print(sv_client.userinfo);

end;

(*
==================================================
SV_ServerRecord_f

Begins server demo recording.  Every entity and every message will be
recorded, but no playerinfo will be stored.  Primarily for demo merging.
==================================================
*)

procedure SV_ServerRecord_f; cdecl;
var
  name: array[0..MAX_OSPATH - 1] of char;
  buf_data: array[0..32768 - 1] of char;
  buf: sizebuf_t;
  len: integer;
  i: integer;
begin
  if (Cmd_Argc() <> 2) then
  begin
    Com_Printf('serverrecord <demoname>'#10);
    exit;
  end;

  if (svs.demofile > 0) then
  begin
    Com_Printf('Already recording.'#10);
    exit;
  end;

  if (sv.state <> ss_game) then
  begin
    Com_Printf('You must be in a level to record.'#10);
    exit;
  end;

  //
  // open the demo file
  //
  Com_sprintf(name, sizeof(name), '%s/demos/%s.dm2', [FS_Gamedir(), Cmd_Argv(1)]);

  Com_Printf('recording to %s.'#10, [name]);
  FS_CreatePath(name);
  svs.demofile := FileOpen(name, fmOpenReadWrite);
  if (svs.demofile = -1) then
  begin
    Com_Printf('ERROR: couldn''t open.'#10);
    exit;
  end;

  // setup a buffer to catch all multicasts
  SZ_Init(svs.demo_multicast, @svs.demo_multicast_buf, sizeof(svs.demo_multicast_buf));

  //
  // write a single giant fake message with all the startup info
  //
  SZ_Init(buf, @buf_data, sizeof(buf_data));

  //
  // serverdata needs to go over for all types of servers
  // to make sure the protocol is right, and to set the gamedir
  //
  // send the serverdata
  MSG_WriteByte(buf, Integer(svc_serverdata));
  MSG_WriteLong(buf, PROTOCOL_VERSION);
  MSG_WriteLong(buf, svs.spawncount);
  // 2 means server demo
  MSG_WriteByte(buf, 2);                // demos are always attract loops
  MSG_WriteString(buf, Cvar_VariableString('gamedir'));
  MSG_WriteShort(buf, -1);
  // send full levelname
  MSG_WriteString(buf, sv.configstrings[CS_NAME]);

  for i := 0 to MAX_CONFIGSTRINGS - 1 do
  begin
    if (sv.configstrings[i, 0] <> #0) then
    begin
      MSG_WriteByte(buf, Integer(svc_configstring));
      MSG_WriteShort(buf, i);
      MSG_WriteString(buf, sv.configstrings[i]);
    end;
  end;
  // write it to the demo file
  Com_DPrintf('signon message length: %i'#10, [buf.cursize]);
  len := LittleLong(buf.cursize);
  FileWrite(svs.demofile, len, 4);
  FileWrite(svs.demofile, buf.data^, buf.cursize);

  // the rest of the demo file will be individual frames
end;

(*
==================================================
SV_ServerStop_f

Ends server demo recording
==================================================
*)

procedure SV_ServerStop_f; cdecl;
begin
  if (svs.demofile <= 0) then
  begin
    Com_Printf('Not doing a serverrecord.'#10);
    exit;
  end;
  FileClose(svs.demofile);
  svs.demofile := 0;
  Com_Printf('Recording completed.'#10);
end;

(*
==================================================
SV_KillServer_f

Kick everyone off, possibly in preparation for a new game

==================================================*)

procedure SV_KillServer_f; cdecl;
begin
  if (not svs.initialized) then
    exit;
  SV_Shutdown('Server was killed.'#10, false);
  NET_Config(false);                    // close network sockets
end;

(*
==================================================
SV_ServerCommand_f

Let the game dll handle a command
==================================================
*)

procedure SV_ServerCommand_f(); cdecl;
begin
  if (ge = nil) then
  begin
    Com_Printf('No game loaded.'#10);
    exit;
  end;
  ge.ServerCommand();
end;

(*
==================================================
SV_InitOperatorCommands
==================================================
*)

procedure SV_InitOperatorCommands();
begin
  Cmd_AddCommand('heartbeat', SV_Heartbeat_f);
  Cmd_AddCommand('kick', SV_Kick_f);
  Cmd_AddCommand('status', SV_Status_f);
  Cmd_AddCommand('serverinfo', SV_Serverinfo_f);
  Cmd_AddCommand('dumpuser', SV_DumpUser_f);

  Cmd_AddCommand('map', SV_Map_f);
  Cmd_AddCommand('demomap', SV_DemoMap_f);
  Cmd_AddCommand('gamemap', SV_GameMap_f);
  Cmd_AddCommand('setmaster', SV_SetMaster_f);

  if (dedicated.value <> 0) then
    Cmd_AddCommand('say', SV_ConSay_f);

  Cmd_AddCommand('serverrecord', SV_ServerRecord_f);
  Cmd_AddCommand('serverstop', SV_ServerStop_f);

  Cmd_AddCommand('save', SV_Savegame_f);
  Cmd_AddCommand('load', SV_Loadgame_f);

  Cmd_AddCommand('killserver', SV_KillServer_f);

  Cmd_AddCommand('sv', SV_ServerCommand_f);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -