/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

// game.h -- game dll information visible to server

#define GAME_API_VERSION 3
#define GAME_API_VERSION_MSUNICAT ((('M' << 0) | ('s' << 8) | ('U' << 16) | ('C' << 24)) ^ (('g' << 0) | ('a' << 8) | ('m' << 16) | ('e' << 24))

// edict->svflags

#define SVF_NOCLIENT 0x00000001    // don't send entity to clients, even if it has effects
#define SVF_DEADMONSTER 0x00000002 // treat as CONTENTS_DEADMONSTER for collision
#define SVF_MONSTER 0x00000004     // treat as CONTENTS_MONSTER for collision

// edict->solid values

typedef enum {
  SOLID_NOT,     // no interaction with other objects
  SOLID_TRIGGER, // only touch when inside, after moving
  SOLID_BBOX,    // touch on edge
  SOLID_BSP      // bsp clip, touch on edge
} solid_t;

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

// link_t is only used for entity area links now
typedef struct link_s {
  struct link_s *prev, *next;
} link_t;

#define MAX_ENT_CLUSTERS 16

typedef struct edict_s edict_t;
typedef struct gclient_s gclient_t;

#ifndef GAME_INCLUDE

struct gclient_s {
  player_state_t ps; // communicated by server to clients
  int ping;
  // the game dll can add anything it wants after
  // this point in the structure
};

struct edict_s {
  entity_state_t s;
  struct gclient_s *client;
  bool inuse;
  int linkcount;

  // FIXME: move these fields to a server private sv_entity_t
  link_t area; // linked to a division node or leaf

  int num_clusters; // if -1, use headnode instead
  int clusternums[MAX_ENT_CLUSTERS];
  int headnode; // unused if num_clusters != -1
  int areanum, areanum2;

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

  int svflags; // SVF_NOCLIENT, SVF_DEADMONSTER, SVF_MONSTER, etc
  vec3_t mins, maxs;
  vec3_t absmin, absmax, size;
  solid_t solid;
  int clipmask;
  edict_t *owner;

  // the game dll can add anything it wants after
  // this point in the structure
};

#endif // GAME_INCLUDE

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

//
// functions provided by the main engine
//
typedef struct {
  // special messages
  void (*bprintf)(int printlevel, char *fmt, ...);
  void (*dprintf)(char *fmt, ...);
  void (*client_printf)(edict_t *ent, int printlevel, char *fmt, ...);
  void (*centerprintf)(edict_t *ent, char *fmt, ...);
  void (*sound)(edict_t *ent, int channel, int soundindex, float volume, float attenuation, float timeofs);
  void (*positioned_sound)(vec3_t origin, edict_t *ent, int channel, int soundinedex, float volume, float attenuation,
                           float timeofs);

  // config strings hold all the index strings, the lightstyles,
  // and misc data like the sky definition and cdtrack.
  // All of the current configstrings are sent to clients when
  // they connect, and changes are sent to all connected clients.
  void (*configstring)(int num, char *string);

  void (*error)(char *fmt, ...);

  // the *index functions create configstrings and some internal server state
  int (*modelindex)(char *name);
  int (*soundindex)(char *name);
  int (*imageindex)(char *name);

  void (*setmodel)(edict_t *ent, char *name);

  // collision detection
  trace_t (*trace)(int cmodel_index, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t *passent,
                   int contentmask);
  int (*pointcontents)(int cmodel_index, vec3_t point);
  bool (*inPVS)(int cmodel_index, vec3_t p1, vec3_t p2);
  bool (*inPHS)(int cmodel_index, vec3_t p1, vec3_t p2);
  void (*SetAreaPortalState)(int cmodel_index, int portalnum, bool open);
  bool (*AreasConnected)(int cmodel_index, int area1, int area2);

  // an entity will never be sent to a client or used for collision
  // if it is not passed to linkentity.  If the size, position, or
  // solidity changes, it must be relinked.
  void (*linkentity)(edict_t *ent);
  void (*unlinkentity)(edict_t *ent); // call before removing an interactive edict
  int (*BoxEdicts)(int cmodel_index, vec3_t mins, vec3_t maxs, edict_t **list, int maxcount, int areatype);
  void (*Pmove)(pmove_t *pmove); // player movement code common with client prediction

  // network messaging
  void (*multicast)(int cmodel_index, vec3_t origin, multicast_t to);
  void (*unicast)(edict_t *ent, bool reliable);
  void (*WriteChar)(int c);
  void (*WriteByte)(int c);
  void (*WriteShort)(int c);
  void (*WriteLong)(int c);
  void (*WriteFloat)(float f);
  void (*WriteString)(char *s);
  void (*WritePosition)(vec3_t pos); // some fractional bits
  void (*WriteDir)(vec3_t pos);      // single byte encoded, very coarse
  void (*WriteAngle)(float f);

  // managed memory allocation
  void *(*TagMalloc)(int size, int tag);
  void (*TagFree)(void *block);
  void (*FreeTags)(int tag);

  // console variable interaction
  cvar_t *(*cvar)(const char *var_name, const char *value, int flags);
  cvar_t *(*cvar_set)(const char *var_name, const char *value);
  cvar_t *(*cvar_forceset)(const char *var_name, const char *value);

  // ClientCommand and ServerCommand parameter access
  int (*argc)(void);
  char *(*argv)(int n);
  char *(*args)(void); // concatenation of all argv >= 1

  // add commands to the server console as if they were typed in
  // for map changing, etc
  void (*AddCommandString)(const char *text);

  void (*DebugGraph)(float value, int color);
} game_import_t;

//
// functions exported by the game subsystem
//
typedef struct {
  int apiversion;

  // the init function will only be called when a game starts,
  // not each time a level is loaded.  Persistant data for clients
  // and the server can be allocated in init
  void (*Init)(void);
  void (*Shutdown)(void);

  // each new level entered will cause a call to SpawnEntities
  void (*SpawnEntities)(int cmodel_index, const char *mapname, const char *entstring, const char *spawnpoint);

  // Read/Write Game is for storing persistant cross level information
  // about the world state and the clients.
  // WriteGame is called every time a level is exited.
  // ReadGame is called on a loadgame.
  void (*WriteGame)(char *filename, bool autosave);
  void (*ReadGame)(char *filename);

  // ReadLevel is called after the default map information has been
  // loaded with SpawnEntities
  void (*WriteLevel)(char *filename);
  void (*ReadLevel)(char *filename);

  bool (*ClientConnect)(edict_t *ent, char *userinfo);
  void (*ClientBegin)(edict_t *ent);
  void (*ClientUserinfoChanged)(edict_t *ent, char *userinfo);
  void (*ClientDisconnect)(edict_t *ent);
  void (*ClientCommand)(edict_t *ent);
  void (*ClientThink)(edict_t *ent, usercmd_t *cmd);

  void (*RunFrame)(void);

  // ServerCommand will be called when an "sv <command>" command is issued on the
  // server console.
  // The game can issue gi.argc() / gi.argv() commands to get the rest
  // of the parameters
  void (*ServerCommand)(void);

  //
  // global variables shared between game and server
  //

  // The edict array is allocated in the game dll so it
  // can vary in size from one game to another.
  //
  // The size will be fixed when ge->Init() is called
  struct edict_s *edicts;
  int edict_size;
  int num_edicts; // current number, <= max_edicts
  int max_edicts;
} game_export_t;

game_export_t *GetGameApi(game_import_t *import);