Skip to content
Permalink
Browse files

multiple map buffers for map editing: "xmaps"

An xmap holds everything related to map editing at a certain moment: it is
a map editing snapshot. It contains the name, the header, the geometry,
the entities, the extra headers, the undo/redo data and the cameraposition
from the moment, the snapshot was taken.

Xmaps are held in memory and, if persistentxmaps is set to "1", are saved
at game end and restored at game start.

xmap_list
  lists all xmaps currently in memory

xmap_store <nickname>
  create a snapshot and store it under the given nickname
  (nicknames have to qualify as valid filenames)

xmap_restore <nickname>
  restores the named snapshot. Also creates a backup snapshot of the
  current editing data.

xmap_restore
  restores the last automatic backup snapshot. Automatic snapshots are
  taken, a) before a snapshot is restored, b) before a new map is loaded
  (if there were unsaved edits on the map) and c) when the game ends (if
  there were unsaved edits).

xmap_delete <nickname>
  deletes the named snapshot.

Unsaved edits are flagged in the HUD with an "U" in the lower right
corner of the screen.

The files with the persistent xmaps are stored in mapediting/xmaps. After
they were restored at game start, the files are moved to
mapediting/xmaps/backups. Xmap files are cubescript files.
  • Loading branch information...
ac-stef committed May 10, 2014
1 parent d3bda71 commit b0649b5ea5a812df152fb25e5ee91c0528c00a6e
@@ -1117,15 +1117,16 @@ COMMAND(showmapstats, "");
VARP(showmodedescriptions, 0, 1, 1);
extern bool canceldownloads;

void startmap(const char *name, bool reset) // called just after a map load
void startmap(const char *name, bool reset, bool norespawn) // called just after a map load
{
canceldownloads = false;
copystring(clientmap, name);

if(norespawn) return;

sendmapidenttoserver = true;
// Added by Rick
if(m_botmode) BotManager.BeginMap(name);
else kickallbots();
// End add by Rick
clearbounceents();
preparectf(!m_flags);
suicided = -1;
@@ -347,6 +347,7 @@ void mapmsg(char *s)
filterrichtext(text, s);
filterservdesc(text, text);
copystring(hdr.maptitle, text, 128);
unsavededits = 1;
}

void getmapmsg(void)
@@ -39,6 +39,7 @@ extern playerent *player1; // special client ent that receives inpu
extern vector<playerent *> players; // all the other clients (in multiplayer)
extern vector<bounceent *> bounceents;
extern bool editmode;
extern int unsavededits;
extern vector<entity> ents; // map entities
extern vector<int> eh_ents; // edithide entities
extern vec worldpos, camup, camright, camdir; // current target of the crosshair in the world
@@ -24,6 +24,7 @@ int lasttype = 0, lasttex = 0;
sqr rtex;

VAR(editing, 1, 0, 0);
VAR(unsavededits, 1, 0, 0);

bool editmetakeydown = false;
COMMANDF(editmeta, "d", (bool on) { editmetakeydown = on; } );
@@ -302,12 +303,12 @@ void pruneundos(int maxremain) // bound memory
loopvrev(undos)
{
u += undos[i]->xs * undos[i]->ys;
if(u > maxremain) delete[] (uchar *)undos.remove(i);
if(u > maxremain) freeblockp(undos.remove(i));
}
loopvrev(redos)
{
r += redos[i]->xs * redos[i]->ys;
if(r > maxremain) delete[] (uchar *)redos.remove(i);
if(r > maxremain) freeblockp(redos.remove(i));
}
}

@@ -323,6 +324,7 @@ void makeundo(block &sel)
storeposition(sel.p);
undos.add(blockcopy(sel));
pruneundos(undomegs<<20);
unsavededits = 1;
}

void restoreposition(short p[])
@@ -350,6 +352,7 @@ void editundo()
if(editmetakeydown) restoreposition(*p);
blockpaste(*p);
freeblock(p);
unsavededits = 1;
}

void editredo()
@@ -361,6 +364,7 @@ void editredo()
if(editmetakeydown) restoreposition(*p);
blockpaste(*p);
freeblock(p);
unsavededits = 1;
}

extern int worldiodebug;
@@ -418,15 +422,17 @@ int rlencodeundo(int type, vector<uchar> &t, block *s)
return t.length();
}

void backupeditundo(vector<uchar> &buf, int undolimit, int redolimit)
int backupeditundo(vector<uchar> &buf, int undolimit, int redolimit)
{
int numundo = 0;
vector<uchar> tmp;
loopvrev(undos)
{
tmp.setsize(0);
undolimit -= rlencodeundo(10, tmp, undos[i]);
if(undolimit < 0) break;
buf.put(tmp.getbuf(), tmp.length());
numundo++;
#ifdef _DEBUG
if(worldiodebug) clientlogf(" written undo x %d, y %d, xs %d, ys %d, compressed length %d", undos[i]->x, undos[i]->y, undos[i]->xs, undos[i]->ys, tmp.length());
#endif
@@ -442,6 +448,7 @@ void backupeditundo(vector<uchar> &buf, int undolimit, int redolimit)
#endif
}
putuint(buf, 0);
return numundo;
}

vector<block *> copybuffers;
@@ -604,6 +611,7 @@ void edittex(int type, int dir)
edittexxy(type, t, sels[i]);
addmsg(SV_EDITT, "ri6", sels[i].x, sels[i].y, sels[i].xs, sels[i].ys, type, t);
}
unsavededits = 1;
}

void settex(int texture, int type)
@@ -627,6 +635,7 @@ void settex(int texture, int type)
edittexxy(type, t, sels[i]);
addmsg(SV_EDITT, "ri6", sels[i].x, sels[i].y, sels[i].xs, sels[i].ys, type, t);
}
unsavededits = 1;
}

void replace()
@@ -645,6 +654,7 @@ void replace()
}
block b = { 0, 0, ssize, ssize };
remip(b);
unsavededits = 1;
}

void edittypexy(int type, block &sel)
@@ -846,6 +856,7 @@ void movemap(int xo, int yo, int zo) // move whole map
entinmap(player1);
calclight();
resetmap(false);
unsavededits = 1;
}

void selfliprotate(block &sel, int dir)
@@ -961,6 +972,7 @@ void transformclipentities() // transforms all clip entities to tag clips, if t
while(thisrun);
loopi(ssize) loopj(ssize) { sqr *s = S(i,j); if(s->tag & TAGCLIP) s->tag &= ~TAGPLCLIP; }
conoutf("changed %d clip entities to tagged clip areas", total);
unsavededits = 1;
}

COMMAND(transformclipentities, "");
@@ -38,6 +38,7 @@ void quit() // normal exit
if(resetcfg) deletecfg();
else writecfg();
savehistory();
writeallxmaps();
cleanup(NULL);
popscontext();
exit(EXIT_SUCCESS);
@@ -1176,6 +1177,8 @@ int main(int argc, char **argv)
exec("config/admin.cfg");
execfile("config/servers.cfg");
loadhistory();
int xmn = loadallxmaps();
if(xmn) conoutf("loaded %d xmaps", xmn);
per_idents = true;

static char resdata[] = { 112, 97, 99, 107, 97, 103, 101, 115, 47, 116, 101, 120, 116, 117, 114, 101, 115, 47, 107, 117, 114, 116, 47, 107, 108, 105, 116, 101, 50, 46, 106, 112, 103, 0 };
@@ -403,7 +403,7 @@ struct serverstate { int autoteam; int mastermode; int matchteamsize; void reset
extern struct serverstate servstate;
extern void updateworld(int curtime, int lastmillis);
extern void resetmap(bool mrproper = true);
extern void startmap(const char *name, bool reset = true);
extern void startmap(const char *name, bool reset = true, bool norespawn = false);
extern void changemap(const char *name);
extern void initclient();
extern void deathstate(playerent *pl);
@@ -500,7 +500,9 @@ extern void removedynlights(physent *owner);
extern block *blockcopy(const block &b);
extern void blockpaste(const block &b, int bx, int by, bool light);
extern void blockpaste(const block &b);
extern void freeblockp(block *b);
extern void freeblock(block *&b);
extern block *duplicateblock(const block *s);

// worldrender
extern void render_world(float vx, float vy, float vh, float changelod, int yaw, int pitch, float fov, float fovy, int w, int h);
@@ -591,8 +593,10 @@ extern void editheightxy(bool isfloor, int amount, block &sel);
//extern bool noteditmode();
extern bool noteditmode(const char* func = NULL);
extern void pruneundos(int maxremain = 0);
extern void storeposition(short p[]);
extern void restoreposition(short p[]);
extern void restoreeditundo(ucharbuf &q);
extern void backupeditundo(vector<uchar> &buf, int undolimit, int redolimit);
extern int backupeditundo(vector<uchar> &buf, int undolimit, int redolimit);

// renderhud
enum
@@ -680,6 +684,9 @@ extern uchar *readmcfggz(char *name, int *size, int *sizegz);
extern void rlencodecubes(vector<uchar> &f, sqr *s, int len, bool preservesolids);
extern void rldecodecubes(ucharbuf &f, sqr *s, int len, int version, bool silent);
extern void clearheaderextras();
extern void xmapbackup(const char *nickprefix, const char *nick);
extern void writeallxmaps();
extern int loadallxmaps();

// physics
extern float raycube(const vec &o, const vec &ray, vec &surface);
@@ -946,6 +946,8 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
formatstring(c_val)("%d", xtraverts);
c_num = xtraverts>3999?(xtraverts>5999?(xtraverts>7999?3:2):1):0; TXTCOLRGB
draw_text(c_val, ttll - text_width(c_val), top+320, c_r, c_g, c_b);

if(unsavededits) draw_text("U", ttll - text_width("U"), top - 90);
}
else
{
@@ -966,6 +968,7 @@ void gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwat
}
defformatstring(c_val)("fps %d", curfps);
draw_text(c_val, VIRTW*2 - ( text_width(c_val) + FONTH ), VIRTH*2 - 3*FONTH/2);
if(unsavededits) draw_text("U", VIRTW*2 - text_width("U") - FONTH, VIRTH*2 - 5*FONTH/2);
}
}
if(!intermission && clockdisplay!=0 && lastgametimeupdate!=0)
@@ -162,7 +162,7 @@ inline bool issimilar (char s, char d)
}

#define MAXMAPNAMELEN 64
inline bool validmapname(char *s)
inline bool validmapname(const char *s)
{
int len = strlen(s);
if(len > MAXMAPNAMELEN) return false;
@@ -4,7 +4,7 @@ int wx1, wy1, wx2, wy2;
float wsx1, wsy1, wsx2, wsy2;

VARP(watersubdiv, 1, 4, 64);
VARF(waterlevel, -128, -128, 127, if(!noteditmode("waterlevel")) hdr.waterlevel = waterlevel);
VARF(waterlevel, -128, -128, 127, if(!noteditmode("waterlevel")) { hdr.waterlevel = waterlevel; unsavededits = 1; });

void setwatercolor(const char *r, const char *g, const char *b, const char *a)
{
@@ -22,6 +22,7 @@ void setwatercolor(const char *r, const char *g, const char *b, const char *a)
hdr.watercolor[2] = 20;
hdr.watercolor[3] = 178;
}
unsavededits = 1;
}

COMMANDN(watercolour, setwatercolor, "ssss");
@@ -191,6 +191,7 @@ void entproperty(int prop, int amount)
loc->drop();
}
if(changedents.find(n) == -1) changedents.add(n); // apply ent changes later (reduces network traffic)
unsavededits = 1;
}

hashtable<char *, enet_uint32> mapinfo, &resdata = mapinfo;
@@ -246,6 +247,7 @@ void delent()
{
case LIGHT: calclight(); break;
}
unsavededits = 1;
}

int findtype(char *what)
@@ -310,6 +312,7 @@ entity *newentity(int index, int x, int y, int z, char *what, int v1, int v2, in
case LIGHT: calclight(); break;
case SOUND: audiomgr.preloadmapsound(e); break;
}
unsavededits = 1;
return index<0 ? &ents.last() : &ents[index];
}

@@ -333,6 +336,7 @@ void clearents(char *name)
{
entity &e = ents[i];
if(e.type==type) e.type = NOTUSED;
unsavededits = 1;
}
switch(type)
{
@@ -365,6 +369,7 @@ void scalelights(int f, int intens)
scalecomp(e.attr3, intens);
scalecomp(e.attr4, intens);
}
unsavededits = 1;
}
calclight();
}
@@ -460,6 +465,7 @@ bool empty_world(int factor, bool force) // main empty world creation routine
if(copy && oldfactor == factor) return false;
bool shrink = factor < oldfactor;
bool clearmap = !copy && world;
if(clearmap && unsavededits) { xmapbackup("newmap", ""); unsavededits = 0; }
if(copy) ow = blockcopy(shrink ? bs : be);

extern char *mlayout;
@@ -491,6 +497,7 @@ bool empty_world(int factor, bool force) // main empty world creation routine
}
else
{ // all-new map
int oldunsavededits = unsavededits;
memset(&hdr, 0, sizeof(header));
formatstring(hdr.maptitle)("Untitled Map by %s", player1->name);
setvar("waterlevel", (hdr.waterlevel = -100000));
@@ -500,6 +507,7 @@ bool empty_world(int factor, bool force) // main empty world creation routine
block b = { 8, 8, ssize-16, ssize - 16};
edittypexy(SPACE, b);
clearheaderextras();
unsavededits = oldunsavededits;
}
strncpy(hdr.head, "ACMP", 4);
hdr.version = MAPVERSION;
@@ -744,6 +752,7 @@ void mapmrproper(bool manual)
conoutf("before: %d / %d / %d / %d / %d / %d / %d", sta[0], sta[1], sta[2], sta[3], sta[4], sta[5], sta[6]);
conoutf("idealized: %d / %d / %d / %d / %d / %d / %d", stb[0], stb[1], stb[2], stb[3], stb[4], stb[5], stb[6]);
conoutf("final count: %d / %d / %d / %d / %d / %d / %d", stc[0], stc[1], stc[2], stc[3], stc[4], stc[5], stc[6]);
unsavededits = 1;
}
}
COMMANDF(mapmrproper, "", () { mapmrproper(true); });

0 comments on commit b0649b5

Please sign in to comment.
You can’t perform that action at this time.