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

📄 g_save.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 3 页
字号:
    WriteField2(f, field, PByte(client));
    inc(field);
  end;
end;

(*
==============
ReadClient

All pointer variables (except function pointers) must be handled specially.
==============
*)
procedure ReadClient(Var f: File; client: gclient_p);
Var field: field_p;
begin
  BlockRead(f, client^, sizeof(client^));
  field := @clientfields[0];
  while field.name<>Nil do begin
    ReadField(f, field, PByte(client));
    inc(field);
  end;
end;

(*
============
WriteGame

This will be called whenever the game goes to a new level,
and when the user explicitly saves the game.

Game information include cross level data, like multi level
triggers, help computer info, and all client states.

A single player death will automatically restore from the
last save position.
============
*)
procedure WriteGame(filename: PChar; autosave: qboolean); cdecl;
Var f: File; i: Integer; str: Array[0..15] of Char;
begin
  if not autosave then
    SaveClientData;

    try
      AssignFile(f, filename);
      Rewrite(f, 1);
    except
      gi_error('Couldn''t open %s', [filename]);
    end;

    FillChar(str[0],sizeof(str),0);
    strcopy(str, __DATE__);
    BlockWrite(f, str[0], sizeof(str));

    game.autosaved := autosave;
    BlockWrite(f, game, sizeof(game));
    game.autosaved := false;

    for i:=0 to game.maxclients-1 do begin
      WriteClient(f, @gclient_a(game.clients)[i]);
    end;

    CloseFile(f);
end;

procedure ReadGame(filename: PChar); cdecl;
Var f: File; i: Integer; str: Array[0..15] of Char;
begin
  gi.FreeTags(TAG_GAME);

  try
    AssignFile(f, filename);
    Reset(f,1);
  except
    gi_error('Couldn''t open %s', [filename]);
  end;

  BlockRead(f, str[0], sizeof(str));
  if strcomp(str, __DATE__) <> 0 then begin
    CloseFile(f);
    gi.error('Savegame from an older version.'#10);
  end;

  g_edicts := gi.TagMalloc(game.maxentities * sizeof(g_edicts[0]), TAG_GAME);
  globals.edicts := @g_edicts[0];

  BlockRead(f, game, sizeof(game));
  game.clients := gi.TagMalloc(game.maxclients * sizeof(gclient_t), TAG_GAME);
  for i:=0 to game.maxclients-1 do
    ReadClient(f, @gclient_a(game.clients)[i]);

  CloseFile(f);
end;

//==========================================================

(*
==============
WriteEdict

All pointer variables (except function pointers) must be handled specially.
==============
*)
procedure WriteEdict(Var f: File; ent: edict_p);
Var field: field_p; temp: edict_t;
begin
  // all of the ints, floats, and vectors stay as they are
  temp := ent^;

  // change the pointers to lengths or indexes
  field := @fields[0];
  while (field.name <> Nil) do begin
    WriteField1(f, field, PByte(@temp));
    inc(field);
  end;

  // write the block
  BlockWrite(f, temp, sizeof(temp));

  // now write any allocated data following the edict
  field := @fields[0];
  while field.name <> Nil do begin
    WriteField2(f, field, PByte(ent));
    inc(field);
  end;
end;

(*
==============
WriteLevelLocals

All pointer variables (except function pointers) must be handled specially.
==============
*)
procedure WriteLevelLocals(Var f: File);
Var field: field_p; temp: level_locals_t;
begin
  // all of the ints, floats, and vectors stay as they are
  temp := level;

  // change the pointers to lengths or indexes
  field := @levelfields[0];
  While field.name <> Nil do begin
    WriteField1(f, field, PByte(@temp));
    inc(field);
  end;

  // write the block
  BlockWrite(f, temp, sizeof(temp));

  // now write any allocated data following the edict
  field := @levelfields[0];
  While field.name <> Nil do begin
    WriteField2(f, field, PByte(@level));
    inc(field);
  end;
end;


(*
==============
ReadEdict

All pointer variables (except function pointers) must be handled specially.
==============
*)
procedure ReadEdict(Var f: File; ent: edict_p);
Var field: field_p;
begin
  BlockRead(f, ent^, sizeof(ent^));

  field := @fields[0];
  While field.name <> Nil do begin
    ReadField(f, field, PByte(ent));
    inc(field);
  end;
end;

(*
==============
ReadLevelLocals

All pointer variables (except function pointers) must be handled specially.
==============
*)
procedure ReadLevelLocals(Var f: File);
Var field: field_p;
begin
  BlockRead(f, level, sizeof(level));

  field := @levelfields[0];
  While field.name <> Nil do begin
    ReadField(f, field, PByte(@level));
    inc(field);
  end;
end;

(*
=================
WriteLevel

=================
*)
procedure WriteLevel(filename: PChar); cdecl;
Var i: Integer; ent: edict_p; f: File; base: Pointer;
begin
  Try
    AssignFile(f, filename);
    Rewrite(f, 1);
  Except
    gi_error('Couldn''t open %s', [filename]);
  end;


  // write out edict size for checking
  i := sizeof(edict_t);
  BlockWrite(f, i, sizeof(i));

  // write out a function pointer for checking
  base := @InitGame;
  BlockWrite(f, base, sizeof(base));

  // write out level_locals_t
  WriteLevelLocals(f);

  // write out all the entities
  for i:=0 to globals.num_edicts - 1 do begin
    ent := @g_edicts[i];
    if not ent.inuse then
      continue;
    BlockWrite(f, i, sizeof(i));
    WriteEdict(f, ent);
  end;
  i := -1;
  BlockWrite(f, i, sizeof(i));

  CloseFile(f);
end;


(*
=================
ReadLevel

SpawnEntities will allready have been called on the
level the same way it was when the level was saved.

That is necessary to get the baselines
set up identically.

The server will have cleared all of the world links before
calling ReadLevel.

No clients are connected yet.
=================
*)
procedure ReadLevel(filename: PChar); cdecl;
Var entnum: Integer; f: File; i: Integer; base: Pointer; ent: edict_p;
BytesRead: Integer;
begin
  Try
    AssignFile(f, filename);
    Reset(f, 1);
  Except
    gi_error('Couldn''t open %s', [filename]);
  end;

  // free any dynamic memory allocated by loading the level
  // base state
  gi.FreeTags(TAG_LEVEL);

  // wipe all the entities
  FillChar(g_edicts, game.maxentities*sizeof(g_edicts[0]), 0);
  globals.num_edicts := Trunc(maxclients.value)+1;

  // check edict size
  BlockRead(f, i, sizeof(i));
  if i <> sizeof(edict_t) then begin
    CloseFile(f);
    gi.error('ReadLevel: mismatched edict size');
  end;

  // check function pointer base address
  BlockRead(f, base, sizeof(base));
{$ifdef WIN32}
  if base <> @InitGame then begin
    CloseFile(f);
    gi.error('ReadLevel: function pointers have moved');
  end;
{$else}
  gi_dprintf('Function offsets %d\n', [LongInt(base) - LongInt(@InitGame)]);
{$endif}

  // load the level locals
  ReadLevelLocals(f);

  // load all the entities
  while true do begin
    BlockRead(f, entnum, sizeof(entnum), BytesRead);
    if BytesRead <> sizeof(entnum) then begin
      CloseFile(f);
      gi.error('ReadLevel: failed to read entnum');
    end;
    if entnum = -1 then
      break;
    if entnum >= globals.num_edicts then
      globals.num_edicts := entnum+1;

    ent := @g_edicts[entnum];
    ReadEdict(f, ent);

    // let the server rebuild world links for this ent
    FillChar(ent.area, sizeof(ent.area), 0);
    gi.linkentity(ent);
  end;

  CloseFile(f);

  // mark all clients as unconnected
  for i:=0 to Trunc(maxclients.value) - 1 do begin
    ent := @g_edicts[i+1];
    ent.client := @gclient_a(game.clients)[i];
    ent.client.pers.connected := false;
  end;

  // do any load time things at this point
  for i:=0 to globals.num_edicts-1 do begin
    ent := @g_edicts[i];

    if not ent.inuse then
      continue;

    // fire any cross-level triggers
    if ent.classname <> Nil then
      if (strcomp(ent.classname, 'target_crosslevel_target') = 0) then
        ent.nextthink := level.time + ent.delay;
  end;
end;

Initialization
  SetFields;
  SetLevelFields;
  SetClientFields;
end.


⌨️ 快捷键说明

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