shithub: sce

Download patch

ref: 2501a66f28dfc3bd04f8e83124ba5003583524bc
parent: 88e2efdc548c93b45b9f84bcab27b1d437873a65
author: qwx <qwx@sciops.net>
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);
 }