shithub: sce

Download patch

ref: 1c2e71622257f7c2bc0d962bc3875358be9c82c5
parent: 2501a66f28dfc3bd04f8e83124ba5003583524bc
author: qwx <qwx@sciops.net>
date: Sun Apr 4 08:24:57 EDT 2021

Tmove/Tmovenear and protocol adjustments

- Tmove to move to target node and Tmovenear to move towards target
object; these two are different in that clicking inside an object
implies finding the closest free and reachable spot near the object,
which jps cannot handle.  we already employ some shitty heuristics
which don't really work well.  the pathfinding system will have to
be changed to handle both cases since one is a general case of the
other.
- terminate messages
- put message size inside header, check it, and use that; we used
to attempt to parse the entire message buffer, which is obviously
wrong
- T* values should not begin with 0 to avoid weird undetected bugs
- allow spaces in packing strings for readability

--- a/com.c
+++ b/com.c
@@ -6,11 +6,11 @@
 #include "fns.h"
 
 enum{
-	Hdrsz = 4,
+	Hdrsz = 2,
 };
 typedef struct Header Header;
 struct Header{
-	int empty;
+	ushort size;
 };
 
 static int
@@ -20,10 +20,12 @@
 
 	sz = 0;
 	for(;;){
+		n = 0;
 		switch(*fmt++){
 		default: sysfatal("vunpack: unknown format %c", fmt[-1]);
 		error: werrstr("vunpack: truncated message"); return -1;
 		case 0: return sz;
+		case ' ': break;
 		case 'h': n = sizeof(u8int); if(p + n > e) goto error;
 			*va_arg(a, int*) = GBIT8(p); p += n;
 			break;
@@ -30,9 +32,12 @@
 		case 's': n = sizeof(u16int); if(p + n > e) goto error;
 			*va_arg(a, int*) = GBIT16(p); p += n;
 			break;
-		case 'l': n = sizeof(u32int); if(p + n > e) goto error;
+		case 'd': n = sizeof(u32int); if(p + n > e) goto error;
 			*va_arg(a, int*) = GBIT32(p); p += n;
 			break;
+		case 'l': n = sizeof(u32int); if(p + n > e) goto error;
+			*va_arg(a, long*) = GBIT32(p); p += n;
+			break;
 		case 'v': n = sizeof(u64int); if(p + n > e) goto error;
 			*va_arg(a, vlong*) = GBIT64(p); p += n;
 			break;
@@ -53,30 +58,86 @@
 	return n;
 }
 
-static int
-reqmovenear(uchar *p, uchar *e)
+static Mobj *
+getmobj(Mobj *r)
 {
-	USED(p, e);
-	return 0;
+	int n;
+	Mobj *mo;
+	Team *t;
+
+	n = r->idx >> Teamshift & Nteam - 1;
+	if(n > nteam){
+		werrstr("invalid team number %d", n);
+		return nil;
+	}
+	t = teams + n;
+	n = r->idx & Teamidxmask;
+	if(n > t->sz || (mo = t->mo[n]) == nil){
+		werrstr("obj index %d out of bounds", n);
+		return nil;
+	}
+	if(mo->idx != r->idx || mo->uuid != r->uuid
+	|| mo->x != r->x || mo->y != r->y){
+		werrstr("phase error: %s at %d,%d has %#ux,%ld, req has %d,%d %#ux,%ld",
+			mo->o->name, mo->x, mo->y, mo->idx, mo->uuid,
+			r->x, r->y, r->idx, r->uuid);
+		return nil;
+	}
+	return mo;
 }
 
 static int
-reqmove(uchar *p, uchar *e)
+reqmovenear(uchar *p, uchar *e)
 {
-	USED(p, e);
-	return 0;
+	int n;
+	Point click;
+	Mobj reqm, reqt, *mo, *tgt;
+
+	if((n = unpack(p, e, "dldd dd dldd",
+	&reqm.idx, &reqm.uuid, &reqm.x, &reqm.y,
+	&click.x, &click.y,
+	&reqt.idx, &reqt.uuid, &reqt.x, &reqt.y)) < 0)
+		goto error;
+	if((mo = getmobj(&reqm)) == nil)
+		goto error;
+	if((tgt = getmobj(&reqt)) == nil)
+		goto error;
+	if(click.x >= nodemapwidth || click.y >= nodemapheight){
+		werrstr("reqmove: invalid location %d,%d", click.x, click.y);
+		return -1;
+	}
+	moveone(click, mo, tgt);
+	return n;
+error:
+	return -1;
 }
 
 static int
-reqpause(uchar *p, uchar *e)
+reqmove(uchar *p, uchar *e)
 {
-	int dicks;
+	int n;
+	Point tgt;
+	Mobj reqm, *mo;
 
-	/* FIXME: just a usage example, we don't really want dicks */
-	if(unpack(p, e, "l", &dicks) < 0){
-		fprint(2, "reqpause: %r\n");
+	if((n = unpack(p, e, "dldd dd",
+	&reqm.idx, &reqm.uuid, &reqm.x, &reqm.y,
+	&tgt.x, &tgt.y)) < 0)
+		goto error;
+	if((mo = getmobj(&reqm)) == nil)
+		goto error;
+	if(tgt.x >= nodemapwidth || tgt.y >= nodemapheight){
+		werrstr("reqmove: invalid target %d,%d", tgt.x, tgt.y);
 		return -1;
 	}
+	moveone(tgt, mo, nil);
+	return n;
+error:
+	return -1;
+}
+
+static int
+reqpause(uchar *, uchar *)
+{
 	pause ^= 1;
 	return 0;
 }
@@ -84,9 +145,12 @@
 static int
 readhdr(Msg *m, Header *h)
 {
-	USED(h);
-	if(m->sz <= Hdrsz)
+	if(unpack(m->buf, m->buf + m->sz, "s", &h->size) < 0
+	|| h->size <= 0
+	|| h->size != m->sz - Hdrsz){
+		werrstr("readhdr: malformed message");
 		return -1;
+	}
 	return 0;
 }
 
@@ -98,10 +162,12 @@
 	int (*fn)(uchar*, uchar*);
 	Header h;
 
-	if(readhdr(m, &h) < 0)
+	if(readhdr(m, &h) < 0){
+		dprint("parsemsg: %r\n");
 		return -1;
+	}
 	p = m->buf + Hdrsz;
-	e = p + sizeof(m->buf) - Hdrsz;
+	e = m->buf + m->sz;
 	while(p < e){
 		type = *p++;
 		switch(type){
@@ -108,10 +174,14 @@
 		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;
+		case Teom:
+			if(p < e)
+				dprint("parsemsg: trailing data\n");
+			return 0;
+		default: dprint("parsemsg: invalid message type %ux\n", type); return -1;
 		}
 		if((n = fn(p, e)) < 0)
-			dprint("parse: %r\n");
+			dprint("parsemsg: %r\n");
 		else
 			p += n;
 	}
@@ -134,9 +204,11 @@
 		copy: if(p + n > e) sysfatal("vpack: buffer overflow");
 			memcpy(p, u, n); p += n; break;
 		case 0: return sz;
+		case ' ': break;
 		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 'd': v = va_arg(a, int); PBIT32(u, v); n = sizeof(u32int); goto copy;
+		case 'l': v = va_arg(a, long); 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;
@@ -146,18 +218,27 @@
 static void
 newmsg(Msg *m)
 {
-	Header h;
-
-	USED(h);
 	m->sz += Hdrsz;
 }
 
 static int
-pack(Msg *m, char *fmt, ...)
+pack(uchar *p, uchar *e, char *fmt, ...)
 {
 	int n;
 	va_list a;
 
+	va_start(a, fmt);
+	n = vpack(p, e, fmt, a);
+	va_end(a);
+	return n;
+}
+
+static int
+packmsg(Msg *m, char *fmt, ...)
+{
+	int n;
+	va_list a;
+
 	if(m->sz == 0)
 		newmsg(m);
 	va_start(a, fmt);
@@ -168,15 +249,23 @@
 	return n;
 }
 
+void
+endmsg(Msg *m)
+{
+	packmsg(m, "h", Teom);
+	pack(m->buf, m->buf + Hdrsz, "s", m->sz - Hdrsz);
+}
+
 int
-sendmovenear(Mobj *mo, Point click, Mobj *target)
+sendmovenear(Mobj *mo, Point click, Mobj *tgt)
 {
 	Msg *m;
 
-	/* FIXME */
 	m = getclbuf();
-	USED(mo, click, target);
-	if(pack(m, "h", Tmovenear) < 0){
+	if(packmsg(m, "h dldd dd dldd", Tmovenear,
+	mo->idx, mo->uuid, mo->x, mo->y,
+	click.x, click.y,
+	tgt->idx, tgt->uuid, tgt->x, tgt->y) < 0){
 		fprint(2, "sendmovenear: %r\n");
 		return -1;
 	}
@@ -184,14 +273,14 @@
 }
 
 int
-sendmove(Mobj *mo, Point target)
+sendmove(Mobj *mo, Point tgt)
 {
 	Msg *m;
 
-	/* FIXME */
 	m = getclbuf();
-	USED(mo, target);
-	if(pack(m, "h", Tmove) < 0){
+	if(packmsg(m, "h dldd dd", Tmove,
+	mo->idx, mo->uuid, mo->x, mo->y,
+	tgt.x, tgt.y) < 0){
 		fprint(2, "sendmove: %r\n");
 		return -1;
 	}
@@ -204,7 +293,7 @@
 	Msg *m;
 
 	m = getclbuf();
-	if(pack(m, "hl", Tpause, 0) < 0){
+	if(packmsg(m, "h", Tpause) < 0){
 		fprint(2, "sendpause: %r\n");
 		return -1;
 	}
--- a/dat.h
+++ b/dat.h
@@ -202,10 +202,11 @@
 extern int scale;
 
 enum{
-	Tquit,
+	Tquit = 0x1f,
 	Tpause,
 	Tmove,
 	Tmovenear,
+	Teom,
 
 	Nbuf = 4096,
 };
--- a/drw.c
+++ b/drw.c
@@ -79,8 +79,6 @@
 		sendmovenear(selected[0], p, mo);
 	else
 		sendmove(selected[0], p);
-	/* FIXME: expunge */
-	moveone(p, selected[0], mo);
 }
 
 static void
--- a/fns.h
+++ b/fns.h
@@ -2,6 +2,7 @@
 Msg*	readnet(void);
 void	initnet(char*);
 int	parsemsg(Msg*);
+void	endmsg(Msg*);
 int	sendmovenear(Mobj*, Point, Mobj*);
 int	sendmove(Mobj*, Point);
 int	sendpause(void);
--- a/net.c
+++ b/net.c
@@ -61,6 +61,7 @@
 {
 	if(clbuf.sz == 0)
 		return;
+	endmsg(&clbuf);
 	write(clpfd[0], clbuf.buf, clbuf.sz);
 	clbuf.sz = 0;
 }