ref: 2501a66f28dfc3bd04f8e83124ba5003583524bc
parent: 88e2efdc548c93b45b9f84bcab27b1d437873a65
author: qwx <[email protected]>
date: Thu Apr 1 17:21:18 EDT 2021
com/sim: shim Tmove and object references - mobj are referenced by team in a linear array with size and first empty slot; slots are emptied when a mobj is despawned - server will receive reqs with mobj coordinates, idx, uuid and will check consistency before executing command - uuid's are just lrand; read lrand(2) source, it seems perfectly adequate for this; bibliography: linear-feedback shift registers; plan9 implementation by James A Reeds et al, no paper but other bell labs papers on topic exist
--- a/com.c
+++ b/com.c
@@ -14,31 +14,6 @@
};
static int
-vpack(uchar *p, uchar *e, char *fmt, va_list a)
-{
- int n, sz;
- uchar u[8];
- u32int v;
- u64int w;
-
- sz = 0;
- for(;;){
- n = 0;
- switch(*fmt++){
- default: sysfatal("unknown format %c", fmt[-1]);
- copy: if(p + n > e) sysfatal("vpack: buffer overflow");
- memcpy(p, u, n); p += n; break;
- case 0: return sz;
- case 'h': v = va_arg(a, int); PBIT8(u, v); n = sizeof(u8int); goto copy;
- case 's': v = va_arg(a, int); PBIT16(u, v); n = sizeof(u16int); goto copy;
- case 'l': v = va_arg(a, int); PBIT32(u, v); n = sizeof(u32int); goto copy;
- case 'v': w = va_arg(a, vlong); PBIT64(u, w); n = sizeof(u64int); goto copy;
- }
- sz += n;
- }
-}
-
-static int
vunpack(uchar *p, uchar *e, char *fmt, va_list a)
{
int n, sz;
@@ -67,27 +42,29 @@
}
static int
-pack(uchar *p, uchar *e, char *fmt, ...)
+unpack(uchar *p, uchar *e, char *fmt, ...)
{
int n;
va_list a;
va_start(a, fmt);
- n = vpack(p, e, fmt, a);
+ n = vunpack(p, e, fmt, a);
va_end(a);
return n;
}
static int
-unpack(uchar *p, uchar *e, char *fmt, ...)
+reqmovenear(uchar *p, uchar *e)
{
- int n;
- va_list a;
+ USED(p, e);
+ return 0;
+}
- va_start(a, fmt);
- n = vunpack(p, e, fmt, a);
- va_end(a);
- return n;
+static int
+reqmove(uchar *p, uchar *e)
+{
+ USED(p, e);
+ return 0;
}
static int
@@ -95,6 +72,7 @@
{
int dicks;
+ /* FIXME: just a usage example, we don't really want dicks */
if(unpack(p, e, "l", &dicks) < 0){
fprint(2, "reqpause: %r\n");
return -1;
@@ -117,6 +95,7 @@
{
int n, type;
uchar *p, *e;
+ int (*fn)(uchar*, uchar*);
Header h;
if(readhdr(m, &h) < 0)
@@ -126,21 +105,44 @@
while(p < e){
type = *p++;
switch(type){
- case Tpause:
- if((n = reqpause(p, e)) < 0){
- dprint("parse: invalid Tpause: %r\n");
- return -1;
- }
- break;
- default:
- dprint("parse: invalid message type %ux\n", type);
- return -1;
+ case Tpause: fn = reqpause; break;
+ case Tmove: fn = reqmove; break;
+ case Tmovenear: fn = reqmovenear; break;
+ default: dprint("parse: invalid message type %ux\n", type); return -1;
}
- p += n;
+ if((n = fn(p, e)) < 0)
+ dprint("parse: %r\n");
+ else
+ p += n;
}
return 0;
}
+static int
+vpack(uchar *p, uchar *e, char *fmt, va_list a)
+{
+ int n, sz;
+ uchar u[8];
+ u32int v;
+ u64int w;
+
+ sz = 0;
+ for(;;){
+ n = 0;
+ switch(*fmt++){
+ default: sysfatal("unknown format %c", fmt[-1]);
+ copy: if(p + n > e) sysfatal("vpack: buffer overflow");
+ memcpy(p, u, n); p += n; break;
+ case 0: return sz;
+ case 'h': v = va_arg(a, int); PBIT8(u, v); n = sizeof(u8int); goto copy;
+ case 's': v = va_arg(a, int); PBIT16(u, v); n = sizeof(u16int); goto copy;
+ case 'l': v = va_arg(a, int); PBIT32(u, v); n = sizeof(u32int); goto copy;
+ case 'v': w = va_arg(a, vlong); PBIT64(u, w); n = sizeof(u64int); goto copy;
+ }
+ sz += n;
+ }
+}
+
static void
newmsg(Msg *m)
{
@@ -150,19 +152,61 @@
m->sz += Hdrsz;
}
+static int
+pack(Msg *m, char *fmt, ...)
+{
+ int n;
+ va_list a;
+
+ if(m->sz == 0)
+ newmsg(m);
+ va_start(a, fmt);
+ n = vpack(m->buf + m->sz, m->buf + sizeof m->buf, fmt, a);
+ va_end(a);
+ if(n >= 0)
+ m->sz += n;
+ return n;
+}
+
int
+sendmovenear(Mobj *mo, Point click, Mobj *target)
+{
+ Msg *m;
+
+ /* FIXME */
+ m = getclbuf();
+ USED(mo, click, target);
+ if(pack(m, "h", Tmovenear) < 0){
+ fprint(2, "sendmovenear: %r\n");
+ return -1;
+ }
+ return 0;
+}
+
+int
+sendmove(Mobj *mo, Point target)
+{
+ Msg *m;
+
+ /* FIXME */
+ m = getclbuf();
+ USED(mo, target);
+ if(pack(m, "h", Tmove) < 0){
+ fprint(2, "sendmove: %r\n");
+ return -1;
+ }
+ return 0;
+}
+
+int
sendpause(void)
{
- int n;
Msg *m;
m = getclbuf();
- if(m->sz == 0)
- newmsg(m);
- if((n = pack(m->buf + m->sz, m->buf + sizeof m->buf, "hl", Tpause, 0)) < 0){
+ if(pack(m, "hl", Tpause, 0) < 0){
fprint(2, "sendpause: %r\n");
return -1;
}
- m->sz += n;
return 0;
}
--- a/dat.h
+++ b/dat.h
@@ -16,9 +16,13 @@
enum{
Nresource = 3,
- Nteam = 8,
Nselect = 12,
Nrot = 32,
+ /* oh boy */
+ Nteambits = 3,
+ Nteam = 1 << Nteambits,
+ Teamshift = 32 - Nteambits,
+ Teamidxmask = ~(Nteam - 1 << Teamshift),
Tilewidth = 32,
Tileheight = Tilewidth,
Node2Tile = 4,
@@ -136,6 +140,8 @@
};
struct Mobj{
Obj *o;
+ int idx;
+ long uuid;
int state;
int freezefrm;
Point;
@@ -177,14 +183,17 @@
char *name;
int init;
};
-extern Resource resource[Nresource];
+extern Resource resources[Nresource];
struct Team{
int r[Nresource];
int nunit;
int nbuild;
+ Mobj **mo;
+ int sz;
+ int firstempty;
};
-extern Team team[Nteam], *curteam;
+extern Team teams[Nteam], *curteam;
extern int nteam;
extern int lport;
@@ -195,6 +204,8 @@
enum{
Tquit,
Tpause,
+ Tmove,
+ Tmovenear,
Nbuf = 4096,
};
--- a/drw.c
+++ b/drw.c
@@ -75,6 +75,11 @@
p = divpt(addpt(subpt(p, selr.min), pan), scale);
p.x /= Nodewidth;
p.y /= Nodeheight;
+ if(mo != nil)
+ sendmovenear(selected[0], p, mo);
+ else
+ sendmove(selected[0], p);
+ /* FIXME: expunge */
moveone(p, selected[0], mo);
}
--- a/fns.h
+++ b/fns.h
@@ -2,6 +2,8 @@
Msg* readnet(void);
void initnet(char*);
int parsemsg(Msg*);
+int sendmovenear(Mobj*, Point, Mobj*);
+int sendmove(Mobj*, Point);
int sendpause(void);
void stepsnd(void);
void initsnd(void);
--- a/fs.c
+++ b/fs.c
@@ -6,7 +6,7 @@
#include "dat.h"
#include "fns.h"
-Resource resource[Nresource];
+Resource resources[Nresource];
typedef struct Table Table;
typedef struct Objp Objp;
@@ -267,10 +267,10 @@
*va_arg(a, Resource**) = nil;
break;
}
- for(r=resource; r<resource+nelem(resource); r++)
+ for(r=resources; r<resources+nelem(resources); r++)
if(strcmp(s, r->name) == 0)
break;
- if(r == resource + nelem(resource))
+ if(r == resources + nelem(resources))
sysfatal("vunpack: no such resource %s", s);
*va_arg(a, Resource**) = r;
break;
@@ -354,7 +354,7 @@
objp = emalloc(nobjp * sizeof *objp);
op = objp + tab->row;
unpack(fld, "oddd", &op->o, &op->team, &op->x, &op->y);
- if(op->team > nelem(team))
+ if(op->team > nelem(teams))
op->team = 0;
if(op->team > nteam)
nteam = op->team;
@@ -365,8 +365,8 @@
{
Resource *r;
- r = resource + tab->row;
- if(r >= resource + nelem(resource))
+ r = resources + tab->row;
+ if(r >= resources + nelem(resources))
sysfatal("readresource: out of bounds reference");
r->name = estrdup(*fld++);
unpack(fld, "d", &r->init);
--- a/map.c
+++ b/map.c
@@ -101,6 +101,7 @@
if(getspawn(&x, &y, o) < 0)
return nil;
mo = emalloc(sizeof *mo);
+ mo->uuid = lrand();
mo->x = x;
mo->y = y;
mo->px = x * Nodewidth;
--- a/sim.c
+++ b/sim.c
@@ -5,7 +5,7 @@
#include "dat.h"
#include "fns.h"
-Team team[Nteam], *curteam;
+Team teams[Nteam], *curteam;
int nteam;
int initres[Nresource], foodcap;
@@ -44,6 +44,30 @@
}
static void
+refmobj(Mobj *mo)
+{
+ int n, i;
+ Team *t;
+
+ t = teams + mo->team;
+ if(mo->f & Fbuild)
+ t->nbuild++;
+ else
+ t->nunit++;
+ n = t->firstempty;
+ if(n == t->sz){
+ t->mo = erealloc(t->mo, (t->sz + 32) * sizeof *t->mo, t->sz * sizeof *t->mo);
+ t->sz += 32;
+ }
+ t->mo[n] = mo;
+ mo->idx = mo->team << Teamshift | n;
+ for(i=t->firstempty+1; i<t->sz; i++)
+ if(t->mo[i] == nil)
+ break;
+ t->firstempty = i;
+}
+
+static void
resetcoords(Mobj *mo)
{
markmobj(mo, 0);
@@ -141,10 +165,7 @@
return -1;
mo->team = n;
mo->state = OSidle;
- if(mo->f & Fbuild)
- team[n].nbuild++;
- else
- team[n].nunit++;
+ refmobj(mo);
return 0;
}
@@ -345,6 +366,6 @@
if(nteam < 2)
sysfatal("initgame: the only winning move is not to play");
- for(t=team; t<=team+nteam; t++)
+ for(t=teams; t<=teams+nteam; t++)
memcpy(t->r, initres, sizeof initres);
}