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

📄 g_save.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 3 页
字号:

All pointer variables (except function pointers) must be handled specially.
==============
*)
procedure ReadClient(f: integer; client: gclient_p);
var
  field: field_p;
begin
  FileRead(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: integer;
  i: Integer;
  str: array[0..15] of Char;
begin
  if not autosave then
    SaveClientData;

  f := FileCreate(FileName);
  if f = 0 then
    gi.error('Couldn''t open %s', filename);

  FillChar(str[0], SizeOf(str), 0);
  strcopy(str, __DATE__);
  FileWrite(f, str, SizeOf(str));

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

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

  FileClose(f);
end;

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

  f := FileOpen(FileName, fmOpenRead);
  if f = 0 then
    gi.error('Couldn''t open %s', filename);

  FileRead(f, str[0], SizeOf(str));
  if strcomp(str, __DATE__) <> 0 then
  begin
    FileClose(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];

  FileRead(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]);

  FileClose(f);
end;

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

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

All pointer variables (except function pointers) must be handled specially.
==============
*)
procedure WriteEdict(f: integer; 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
  FileWrite(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(f: integer);
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
  FileWrite(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(f: integer; ent: edict_p);
var
  field: field_p;
begin
  FileRead(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(f: integer);
var
  field: field_p;
begin
  FileRead(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: integer;
  base: Pointer;
begin
  f := FileCreate(filename);
  if f = 0 then
    gi.error('Couldn''t open %s', filename);

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

  // write out a function pointer for checking
  base := @InitGame;
  FileWrite(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;
    FileWrite(f, i, SizeOf(i));
    WriteEdict(f, ent);
  end;
  i := -1;
  FileWrite(f, i, SizeOf(i));

  FileClose(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: integer;
  i: Integer;
  base: Pointer;
  ent: edict_p;
  BytesRead: Integer;
begin
   f := FileOpen(FileName, fmOpenRead);
   if f = 0 then
     gi.error('Couldn''t open %s', filename);

  // 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
  FileRead(f, i, SizeOf(i));
  if i <> SizeOf(edict_t) then
  begin
    FileClose(f);
    gi.error('ReadLevel: mismatched edict size');
  end;

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

  // load the level locals
  ReadLevelLocals(f);

  // load all the entities
  while true do
  begin
    BytesRead := FileRead(f, entnum, SizeOf(entnum));
    if BytesRead <> sizeof(entnum) then
    begin
      FileClose(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;

  FileClose(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
begin
  SetFields;
  SetLevelFields;
  SetClientFields;
end;

end.

⌨️ 快捷键说明

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