drop game/client.cc, remove some stubs, consolidate under game.cc

master
Daniel Kolesa 2020-04-26 19:02:26 +02:00
parent 4c0496c07a
commit c338156fa2
8 changed files with 144 additions and 618 deletions

View File

@ -1,101 +0,0 @@
* Installing and Running Tesseract
*nix versions of Tesseract clients and standalone servers.
The clients function identical to the win32 client, see config.html for more
information about command-line options if necessary.
Please run "tesseract_unix" from the root Tesseract dir (NOT from inside the "bin_unix"
directory) to launch these, or set the TESS_DATA variable at the top of the "tesseract_unix"
script to an absolute path to allow it to be run from any location. Note that the "tesseract_unix"
script is set up to write any files (saved maps, configs, etc.) into the user's home
directory at "~/.tesseract".
Clients will need the following dynamic link libraries present:
* libGL (OpenGL)
* SDL2 (>= 2.0.0)
* SDL2_image
* SDL2_mixer
* libpng
* libjpeg
* zlib
If native binaries for your platform are not included, then try the following:
1) Ensure you have the DEVELOPMENT VERSIONS of the above libraries installed.
2) Type "make -C src install".
3) Re-run the "tesseract_unix" script if it succeeded.
The servers (bin_unix/linux_server or bin_unix/native_server) should need no libs
other than libstdc++ and zlib. Note that for the server to see the "config/server-init.cfg",
it must be run from the root Tesseract directory. If you run a server with the
"tesseract_unix -d" command, this happens automatically. However, if you wish to
run the standalone servers instead, then you may need to write an appropriate wrapper
script to change to the appropriate data directory before running the standalone
server binary, as described below in the packaging guide.
* Packaging Guide for Unix-like Operating System Developers/Maintainers
If you are packaging Tesseract up for redistribution in a Linux distribution or other
similar OS, please avoid using the "tesseract_unix" script in its default/unmodified form.
You should at least set the TESS_DATA variable to appropriately find the common Tesseract
data files, or better yet replace it with a more appropriate way of starting Tesseract using
the script as a basis. If the distribution happens to place program binaries in a specific
directory separate from data files, such as "/usr/bin", then much of the lines within the script
that deal with finding an appropriate binary can be removed, as they only exist to help people
running from the original Tesseract tarball. An example run script is shown further
below.
Also, please note, that if your distribution chooses to package the binaries and game data
as separate packages due to whatever licensing rules or cross-architecture package sharing,
that client binaries from newer Tesseract editions are NOT compatible with older versions of
game data, on whole, nor obviously compatible with newer versions of game data. Game data, as a
whole, and client binaries are only roughly compatible within individual Tesseract editions,
though patches to individual Tesseract editions generally always retain compatibility with
the game data.
For those writing custom Tesseract run scripts for packaging, they should adhere to the following
guidelines:
Tesseract finds all game files relative to the current directory from which Tesseract is run,
so any script running Tesseract should set its current directory to where the Tesseract data
files are located before it runs the Tesseract client binaries. No silly symlinking tricks should
be at all necessary.
When running the Tesseract client, one command-line switch should ALWAYS be supplied to
the client binary. This is "-u${HOME}/.tesseract", which will instruct Tesseract to
write any user private files such as saved maps and configurations to a private ".tesseract"
directory within each user's home directory. Tesseract will automatically create this
directory and any subdirectories for each user running it, so do not pre-create this directory
or install any symlinks within it - as some Linux distribution packages have erroneously done.
All command-line switches supplied to the Tesseract run script should be passed to the
Tesseract client after the "-u${HOME}/.tesseract" switch.
A simple script such as the following (with directory/file names set as appropriate) would
ultimately suffice for the client:
#!/bin/sh
TESS_DATA=/usr/share/games/tesseract
TESS_BIN=/usr/bin/tesseract_client
TESS_OPTIONS="-u${HOME}/.tesseract"
cd ${TESS_DATA}
exec ${TESS_BIN} ${TESS_OPTIONS} "$@"
A simple script for the server, which assumes a global default "config/server-init.cfg" in TESS_DATA,
but allows per-user overriding via the home directory, might be:
#!/bin/sh
TESS_DATA=/usr/share/games/tesseract
TESS_SERV_BIN=/usr/bin/tesseract_server
TESS_SERV_OPTIONS="-u${HOME}/.tesseract"
cd ${TESS_DATA}
exec ${TESS_SERV_BIN} ${TESS_SERV_OPTIONS} "$@"
With respect to libraries, make sure that you do not link Tesseract against any other ENet package
than the one that comes included with the Tesseract, as it may be different from the official ENet
releases and might fail to compile or communicate properly.

View File

@ -36,10 +36,8 @@ client_src = [
'../engine/water.cc',
'../engine/world.cc',
'../engine/worldio.cc',
'../game/client.cc',
'../game/entities.cc',
'../game/game.cc',
'../game/render.cc',
]
threads_dep = dependency('threads')

View File

@ -1291,78 +1291,6 @@ void entattr(int *attr, int *val, int *numargs)
COMMAND(enttype, "sN");
COMMAND(entattr, "iiN");
int findentity(int type, int index, int attr1, int attr2)
{
const vector<extentity *> &ents = entities::getents();
if(index > ents.length()) index = ents.length();
else for(int i = index; i<ents.length(); i++)
{
extentity &e = *ents[i];
if(e.type==type && (attr1<0 || e.attr1==attr1) && (attr2<0 || e.attr2==attr2))
return i;
}
loopj(index)
{
extentity &e = *ents[j];
if(e.type==type && (attr1<0 || e.attr1==attr1) && (attr2<0 || e.attr2==attr2))
return j;
}
return -1;
}
int spawncycle = -1;
void findplayerspawn(dynent *d, int forceent, int tag) // place at random spawn
{
int pick = forceent;
if(pick<0)
{
int r = rnd(10)+1;
pick = spawncycle;
loopi(r)
{
pick = findentity(ET_PLAYERSTART, pick+1, -1, tag);
if(pick < 0) break;
}
if(pick < 0 && tag)
{
pick = spawncycle;
loopi(r)
{
pick = findentity(ET_PLAYERSTART, pick+1, -1, 0);
if(pick < 0) break;
}
}
if(pick >= 0) spawncycle = pick;
}
if(pick>=0)
{
const vector<extentity *> &ents = entities::getents();
d->pitch = 0;
d->roll = 0;
for(int attempt = pick;;)
{
d->o = ents[attempt]->o;
d->yaw = ents[attempt]->attr1;
if(entinmap(d, true)) break;
attempt = findentity(ET_PLAYERSTART, attempt+1, -1, tag);
if(attempt<0 || attempt==pick)
{
d->o = ents[pick]->o;
d->yaw = ents[pick]->attr1;
entinmap(d);
break;
}
}
}
else
{
d->o.x = d->o.y = d->o.z = 0.5f*worldsize;
d->o.z += 1;
entinmap(d);
}
}
void splitocta(cube *c, int size)
{
if(size <= 0x1000) return;
@ -1512,13 +1440,6 @@ COMMAND(newmap, "i");
COMMAND(mapenlarge, "");
COMMAND(shrinkmap, "");
void mapname()
{
result(game::getclientmap());
}
COMMAND(mapname, "");
void mpeditent(int i, const vec &o, int type, int attr1, int attr2, int attr3, int attr4, int attr5, bool local)
{
if(i < 0 || i >= MAXENTS) return;

View File

@ -1,143 +0,0 @@
#include "game.hh"
extern void clearmainmenu();
namespace game
{
VARP(minradarscale, 0, 384, 10000);
VARP(maxradarscale, 1, 1024, 10000);
VARP(radarteammates, 0, 1, 1);
FVARP(minimapalpha, 0, 1, 1);
float calcradarscale()
{
return clamp(max(minimapradius.x, minimapradius.y)/3, float(minradarscale), float(maxradarscale));
}
void drawminimap(gameent *d, float x, float y, float s)
{
vec pos = vec(d->o).sub(minimapcenter).mul(minimapscale).add(0.5f), dir;
vecfromyawpitch(camera1->yaw, 0, 1, 0, dir);
float scale = calcradarscale();
gle::defvertex(2);
gle::deftexcoord0();
gle::begin(GL_TRIANGLE_FAN);
loopi(16)
{
vec v = vec(0, -1, 0).rotate_around_z(i/16.0f*2*M_PI);
gle::attribf(x + 0.5f*s*(1.0f + v.x), y + 0.5f*s*(1.0f + v.y));
vec tc = vec(dir).rotate_around_z(i/16.0f*2*M_PI);
gle::attribf(1.0f - (pos.x + tc.x*scale*minimapscale.x), pos.y + tc.y*scale*minimapscale.y);
}
gle::end();
}
void setradartex()
{
settexture("media/interface/radar/radar.png", 3);
}
bool connected = false;
int sessionid = 0;
string servdesc = "", servauth = "";
VARP(deadpush, 1, 2, 20);
void sendmapinfo()
{
}
void writeclientinfo(stream *f)
{
}
bool allowedittoggle()
{
return true;
}
void edittoggled(bool on)
{
disablezoom();
player1->respawned = -2;
}
string clientmap = "";
void changemapserv(const char *name, int mode) // forced map change from the server
{
if(editmode) toggleedit();
if(!name[0] || !load_world(name))
{
emptymap(0, true, name);
}
startgame();
}
void changemap(const char *name, int mode) // request map change, server may ignore
{
changemapserv(name, 0);
connected = true;
clearmainmenu(); /* XXX hack */
}
void changemap(const char *name)
{
changemap(name, 0);
}
ICOMMAND(map, "s", (char *name), changemap(name));
void forceedit(const char *name)
{
changemap(name, 0);
}
void newmap(int size)
{
if(size>=0) emptymap(size, true, NULL);
else enlargemap(true);
connected = true;
}
void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs)
{
}
void vartrigger(ident *id)
{
}
bool ispaused() { return false; }
bool allowmouselook() { return true; }
int scaletime(int t) { return t*100; }
void connectfail()
{
}
void gameconnect()
{
}
void gamedisconnect(bool cleanup)
{
if (!connected) {
return;
}
connected = false;
player1->clientnum = -1;
if(editmode) toggleedit();
sessionid = 0;
player1->respawn();
player1->state = CS_ALIVE;
if(cleanup)
{
clientmap[0] = '\0';
}
}
void toserver(char *text) { conoutf(CON_CHAT, "%s", text); }
}
bool haslocalclients() { return game::connected; }

View File

@ -34,8 +34,8 @@ namespace entities
{
}
extentity *newentity() { return new gameentity(); }
void deleteentity(extentity *e) { delete (gameentity *)e; }
extentity *newentity() { return new extentity(); }
void deleteentity(extentity *e) { delete e; }
void clearents()
{

View File

@ -1,42 +1,58 @@
#include "game.hh"
extern void clearmainmenu();
namespace game
{
static int maptime = 0, maprealtime = 0;
gameent *player1 = NULL; // our client
dynent *player1 = NULL; // our client
const char *getclientmap() { return clientmap; }
const char *gameident() { return "OctaForge"; }
void saveragdoll(dynent *d)
{
}
void clearragdolls()
{
}
void moveragdolls()
{
}
void rendergame()
{
}
void renderavatar()
{
}
void preloadweapons()
{
}
void preloadsounds()
{
}
void preload()
{
entities::preloadentities();
}
void resetgamestate()
{
}
gameent *spawnstate(gameent *d) // reset player state not persistent accross spawns
dynent *spawnstate(dynent *d) // reset player state not persistent accross spawns
{
d->respawn();
d->spawnstate(0);
d->reset();
return d;
}
void respawnself()
{
if(ispaused()) return;
spawnplayer(player1);
}
gameent *pointatplayer()
{
return NULL;
}
gameent *hudplayer()
{
return player1;
}
void setupcamera()
{
}
@ -58,7 +74,6 @@ namespace game
void updateworld() // main game update loop
{
if(!maptime) { maptime = lastmillis; maprealtime = totalmillis; return; }
if(!curtime) { return; }
physicsframe();
@ -70,9 +85,11 @@ namespace game
}
}
void spawnplayer(gameent *d) // place at random spawn
void spawnplayer(dynent *d) // place at random spawn
{
findplayerspawn(d, -1, 0);
d->o.x = d->o.y = d->o.z = 0.5f*getworldsize();
d->o.z += 1;
entinmap(d);
spawnstate(d);
if(d==player1)
{
@ -82,62 +99,33 @@ namespace game
else d->state = CS_ALIVE;
}
VARP(spawnwait, 0, 0, 1000);
void respawn()
{
if(player1->state==CS_DEAD)
{
respawnself();
}
}
COMMAND(respawn, "");
// inputs
VARP(jumpspawn, 0, 1, 1);
bool canjump()
{
if(!connected) return false;
if(jumpspawn) respawn();
return player1->state!=CS_DEAD;
return connected;
}
bool cancrouch()
{
if(!connected) return false;
return player1->state!=CS_DEAD;
return connected;
}
bool allowmove(physent *d)
{
return true;
}
gameent *getclient(int cn) // ensure valid entity
{
if(cn == player1->clientnum) return player1;
return NULL;
return connected;
}
void initclient()
{
player1 = spawnstate(new gameent);
filtertext(player1->name, "unnamed", false, false, MAXNAMELEN);
player1 = spawnstate(new dynent);
player1->reset();
}
VARP(showmodeinfo, 0, 1, 1);
void startgame()
{
// reset perma-state
player1->startgame();
maptime = maprealtime = 0;
syncplayer();
disablezoom();
execident("mapstart");
@ -147,8 +135,6 @@ namespace game
{
spawnplayer(player1);
copystring(clientmap, name ? name : "");
sendmapinfo();
}
const char *getmapinfo()
@ -169,11 +155,6 @@ namespace game
{
}
void msgsound(int n, physent *d)
{
playsound(n);
}
int numdynents() { return 1; }
dynent *iterdynents(int i)
@ -193,7 +174,7 @@ namespace game
return 1;
}
void drawhudicons(gameent *d)
void drawhudicons(dynent *d)
{
}
@ -201,12 +182,6 @@ namespace game
{
pushhudscale(h/1800.0f);
gameent *d = hudplayer();
if(d->state!=CS_EDITING)
{
if(d->state!=CS_SPECTATOR) drawhudicons(d);
}
pophudmatrix();
}
@ -240,5 +215,95 @@ namespace game
{
execfile("config/auth.cfg", false);
}
void drawminimap(dynent *d, float x, float y, float s)
{
}
void setradartex()
{
}
bool connected = false;
void writeclientinfo(stream *f)
{
}
bool allowedittoggle()
{
return true;
}
void edittoggled(bool on)
{
disablezoom();
}
string clientmap = "";
void changemap(const char *name)
{
if(editmode) toggleedit();
if(!name[0] || !load_world(name))
{
emptymap(0, true, name);
}
startgame();
connected = true;
clearmainmenu(); /* XXX hack */
}
ICOMMAND(map, "s", (char *name), changemap(name));
void forceedit(const char *name)
{
changemap(name);
}
void newmap(int size)
{
if(size>=0) emptymap(size, true, NULL);
else enlargemap(true);
connected = true;
}
void edittrigger(const selinfo &sel, int op, int arg1, int arg2, int arg3, const VSlot *vs)
{
}
void vartrigger(ident *id)
{
}
bool ispaused() { return false; }
bool allowmouselook() { return true; }
int scaletime(int t) { return t*100; }
void connectfail()
{
}
void gameconnect()
{
}
void gamedisconnect(bool cleanup)
{
if (!connected) {
return;
}
connected = false;
if(editmode) toggleedit();
player1->reset();
player1->state = CS_ALIVE;
if(cleanup)
{
clientmap[0] = '\0';
}
}
void toserver(char *text) { conoutf(CON_CHAT, "%s", text); }
}
bool haslocalclients() { return game::connected; }

View File

@ -3,59 +3,13 @@
#include "cube.hh"
// animations
enum
{
ANIM_DEAD = ANIM_GAMESPECIFIC, ANIM_DYING,
ANIM_IDLE, ANIM_RUN_N, ANIM_RUN_NE, ANIM_RUN_E, ANIM_RUN_SE, ANIM_RUN_S, ANIM_RUN_SW, ANIM_RUN_W, ANIM_RUN_NW,
ANIM_JUMP, ANIM_JUMP_N, ANIM_JUMP_NE, ANIM_JUMP_E, ANIM_JUMP_SE, ANIM_JUMP_S, ANIM_JUMP_SW, ANIM_JUMP_W, ANIM_JUMP_NW,
ANIM_SINK, ANIM_SWIM,
ANIM_CROUCH, ANIM_CROUCH_N, ANIM_CROUCH_NE, ANIM_CROUCH_E, ANIM_CROUCH_SE, ANIM_CROUCH_S, ANIM_CROUCH_SW, ANIM_CROUCH_W, ANIM_CROUCH_NW,
ANIM_CROUCH_JUMP, ANIM_CROUCH_JUMP_N, ANIM_CROUCH_JUMP_NE, ANIM_CROUCH_JUMP_E, ANIM_CROUCH_JUMP_SE, ANIM_CROUCH_JUMP_S, ANIM_CROUCH_JUMP_SW, ANIM_CROUCH_JUMP_W, ANIM_CROUCH_JUMP_NW,
ANIM_CROUCH_SINK, ANIM_CROUCH_SWIM,
ANIM_SHOOT, ANIM_MELEE,
ANIM_PAIN,
ANIM_EDIT, ANIM_LAG, ANIM_TAUNT, ANIM_WIN, ANIM_LOSE,
ANIM_GUN_IDLE, ANIM_GUN_SHOOT, ANIM_GUN_MELEE,
ANIM_VWEP_IDLE, ANIM_VWEP_SHOOT, ANIM_VWEP_MELEE,
NUMANIMS
};
static const char * const animnames[] =
{
"mapmodel",
"dead", "dying",
"idle", "run N", "run NE", "run E", "run SE", "run S", "run SW", "run W", "run NW",
"jump", "jump N", "jump NE", "jump E", "jump SE", "jump S", "jump SW", "jump W", "jump NW",
"sink", "swim",
"crouch", "crouch N", "crouch NE", "crouch E", "crouch SE", "crouch S", "crouch SW", "crouch W", "crouch NW",
"crouch jump", "crouch jump N", "crouch jump NE", "crouch jump E", "crouch jump SE", "crouch jump S", "crouch jump SW", "crouch jump W", "crouch jump NW",
"crouch sink", "crouch swim",
"shoot", "melee",
"pain",
"edit", "lag", "taunt", "win", "lose",
"gun idle", "gun shoot", "gun melee",
"vwep idle", "vwep shoot", "vwep melee"
};
// console message types
enum
{
CON_CHAT = 1<<8,
CON_TEAMCHAT = 1<<9,
CON_GAMEINFO = 1<<10,
CON_FRAG_SELF = 1<<11,
CON_FRAG_OTHER = 1<<12,
CON_TEAMKILL = 1<<13
CON_CHAT = 1<<8
};
// network quantization scale
#define DMF 16.0f // for world locations
#define DNF 100.0f // for normalized vectors
#define DVELF 1.0f // for playerspeed based velocity vectors
enum // static entity types
{
NOTUSED = ET_EMPTY, // entity slot not in use in map
@ -73,95 +27,8 @@ enum // static entity types
I_LAST = -1
};
struct gameentity : extentity
{
};
#define TESSERACT_SERVER_PORT 42000
#define TESSERACT_LANINFO_PORT 41998
#define MAXNAMELEN 15
#define validitem(n) false
// inherited by gameent and server clients
struct gamestate
{
gamestate() {}
bool canpickup(int type)
{
return validitem(type);
}
void pickup(int type)
{
}
void respawn()
{
}
void spawnstate(int gamemode)
{
}
};
struct gameent : dynent, gamestate
{
int weight; // affects the effectiveness of hitpush
int clientnum, lastupdate, plag, ping;
int respawned;
int lastaction;
editinfo *edit;
float deltayaw, deltapitch, deltaroll, newyaw, newpitch, newroll;
int smoothmillis;
string name, info;
int team, playermodel, playercolor;
int ownernum, lastnode;
vec muzzle;
gameent() : weight(100), clientnum(-1), lastupdate(0), plag(0), ping(0), respawned(-1), edit(NULL), smoothmillis(-1), team(0), playermodel(-1), playercolor(0), ownernum(-1), muzzle(-1, -1, -1)
{
name[0] = info[0] = 0;
respawn();
}
~gameent()
{
freeeditinfo(edit);
}
void respawn()
{
dynent::reset();
gamestate::respawn();
respawned = -1;
lastaction = 0;
lastnode = -1;
}
int respawnwait(int secs, int delay = 0)
{
return 0;
}
void startgame()
{
respawned = -2;
}
};
struct teaminfo
{
int frags;
teaminfo() { reset(); }
void reset() { frags = 0; }
};
namespace entities
{
extern vector<extentity *> ents;
@ -173,42 +40,16 @@ namespace game
// game
extern string clientmap;
extern gameent *player1;
extern gameent *getclient(int cn);
extern gameent *newclient(int cn);
extern gameent *pointatplayer();
extern gameent *hudplayer();
extern void startgame();
extern void spawnplayer(gameent *);
extern void msgsound(int n, physent *d = NULL);
extern dynent *player1;
// client
extern bool connected, remote, demoplayback;
extern string servdesc;
extern int parseplayer(const char *arg);
extern void sendmapinfo();
extern void changemap(const char *name, int mode);
extern bool connected;
// render
extern void saveragdoll(gameent *d);
extern void saveragdoll(dynent *d);
extern void clearragdolls();
extern void moveragdolls();
extern int getplayercolor(gameent *d, int team);
extern int chooserandomplayermodel(int seed);
extern void syncplayer();
}
namespace server
{
extern void forcemap(const char *map, int mode);
extern void forcepaused(bool paused);
extern void forcegamespeed(int speed);
extern int msgsizelookup(int msg);
extern bool delayspawn(int type);
}
#endif

View File

@ -1,55 +0,0 @@
#include "game.hh"
namespace game
{
void saveragdoll(gameent *d)
{
}
void clearragdolls()
{
}
void moveragdolls()
{
}
void changedplayermodel()
{
}
void syncplayer()
{
}
void preloadplayermodel()
{
}
void rendergame()
{
}
void renderavatar()
{
}
void renderplayerpreview(int model, int color, int weap)
{
}
void preloadweapons()
{
}
void preloadsounds()
{
}
void preload()
{
entities::preloadentities();
}
}