Move classes into separate files

FossilOrigin-Name: 14861826d4c1f561aca909afe773366a46b57b20cf41fd668092dfb98d960d80
This commit is contained in:
Jonathan Schleifer 2025-03-05 23:18:28 +00:00
parent 3661ce9a40
commit 623076a034
17 changed files with 366 additions and 322 deletions

View file

@ -1,12 +1,14 @@
project('Cube', ['c', 'objcpp'], project('Cube', ['c', 'objc', 'objcpp'],
meson_version: '>=1.5.0') meson_version: '>=1.5.0')
add_global_arguments( foreach lang : ['objc', 'objcpp']
[ add_global_arguments(
'-fobjc-arc', [
'-fobjc-arc-exceptions' '-fobjc-arc',
], '-fobjc-arc-exceptions'
language: 'objcpp') ],
language: lang)
endforeach
objfw_dep = dependency('objfw') objfw_dep = dependency('objfw')
sdl_dep = dependency('SDL2') sdl_dep = dependency('SDL2')

18
src/Ident.h Normal file
View file

@ -0,0 +1,18 @@
#import <ObjFW/ObjFW.h>
OF_ASSUME_NONNULL_BEGIN
enum IdentType { ID_VAR, ID_COMMAND, ID_ALIAS };
@interface Ident : OFObject
@property (nonatomic) enum IdentType type;
@property (copy, nonatomic) OFString *name;
@property (nonatomic) int min, max; // ID_VAR
@property (nonatomic) int *storage; // ID_VAR
@property (nonatomic) void (*fun)(); // ID_VAR, ID_COMMAND
@property (nonatomic) int narg; // ID_VAR, ID_COMMAND
@property (copy, nonatomic) OFString *action; // ID_ALIAS
@property (nonatomic) bool persist;
@end
OF_ASSUME_NONNULL_END

4
src/Ident.m Normal file
View file

@ -0,0 +1,4 @@
#import "Ident.h"
@implementation Ident
@end

13
src/KeyMapping.h Normal file
View file

@ -0,0 +1,13 @@
#import <ObjFW/ObjFW.h>
OF_ASSUME_NONNULL_BEGIN
@interface KeyMapping : OFObject
@property (readonly) int code;
@property (readonly, nonatomic) OFString *name;
@property (copy, nonatomic) OFString *action;
- (instancetype)initWithCode:(int)code name:(OFString *)name;
@end
OF_ASSUME_NONNULL_END

13
src/KeyMapping.m Normal file
View file

@ -0,0 +1,13 @@
#import "KeyMapping.h"
@implementation KeyMapping
- (instancetype)initWithCode:(int)code name:(OFString *)name
{
self = [super init];
_code = code;
_name = [name copy];
return self;
}
@end

29
src/MD2.h Normal file
View file

@ -0,0 +1,29 @@
#import <ObjFW/ObjFW.h>
OF_ASSUME_NONNULL_BEGIN
@class MapModelInfo;
@interface MD2 : OFObject
@property (nonatomic) MapModelInfo *mmi;
@property (copy, nonatomic) OFString *loadname;
@property (nonatomic) int mdlnum;
@property (nonatomic) bool loaded;
- (bool)loadWithIRI:(OFIRI *)IRI;
- (void)renderWithLight:(OFVector3D &)light
frame:(int)frame
range:(int)range
x:(float)x
y:(float)y
z:(float)z
yaw:(float)yaw
pitch:(float)pitch
scale:(float)scale
speed:(float)speed
snap:(int)snap
basetime:(int)basetime;
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)snap;
@end
OF_ASSUME_NONNULL_END

207
src/MD2.mm Normal file
View file

@ -0,0 +1,207 @@
#import "MD2.h"
#include "cube.h"
struct md2_header {
int magic;
int version;
int skinWidth, skinHeight;
int frameSize;
int numSkins, numVertices, numTexcoords;
int numTriangles, numGlCommands, numFrames;
int offsetSkins, offsetTexcoords, offsetTriangles;
int offsetFrames, offsetGlCommands, offsetEnd;
};
struct md2_vertex {
uchar vertex[3], lightNormalIndex;
};
struct md2_frame {
float scale[3];
float translate[3];
char name[16];
md2_vertex vertices[1];
};
@implementation MD2 {
int _numGlCommands;
int *_glCommands;
int _numTriangles;
int _frameSize;
int _numFrames;
int _numVerts;
char *_frames;
OFVector3D **_mverts;
int _displaylist;
int _displaylistverts;
}
- (void)dealloc
{
if (_glCommands)
delete[] _glCommands;
if (_frames)
delete[] _frames;
}
- (bool)loadWithIRI:(OFIRI *)IRI
{
@autoreleasepool {
OFSeekableStream *stream;
@try {
stream = (OFSeekableStream *)[[OFIRIHandler
handlerForIRI:IRI] openItemAtIRI:IRI mode:@"r"];
} @catch (id e) {
return false;
}
if (![stream isKindOfClass:[OFSeekableStream class]])
return false;
md2_header header;
[stream readIntoBuffer:&header exactLength:sizeof(md2_header)];
endianswap(
&header, sizeof(int), sizeof(md2_header) / sizeof(int));
if (header.magic != 844121161 || header.version != 8)
return false;
_frames = new char[header.frameSize * header.numFrames];
if (_frames == NULL)
return false;
[stream seekToOffset:header.offsetFrames whence:OFSeekSet];
[stream readIntoBuffer:_frames
exactLength:header.frameSize * header.numFrames];
for (int i = 0; i < header.numFrames; ++i)
endianswap(
_frames + i * header.frameSize, sizeof(float), 6);
_glCommands = new int[header.numGlCommands];
if (_glCommands == NULL)
return false;
[stream seekToOffset:header.offsetGlCommands whence:OFSeekSet];
[stream readIntoBuffer:_glCommands
exactLength:header.numGlCommands * sizeof(int)];
endianswap(_glCommands, sizeof(int), header.numGlCommands);
_numFrames = header.numFrames;
_numGlCommands = header.numGlCommands;
_frameSize = header.frameSize;
_numTriangles = header.numTriangles;
_numVerts = header.numVertices;
[stream close];
_mverts = new OFVector3D *[_numFrames];
loopj(_numFrames) _mverts[j] = NULL;
return true;
}
}
float
snap(int sn, float f)
{
return sn ? (float)(((int)(f + sn * 0.5f)) & (~(sn - 1))) : f;
}
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)sn
{
_mverts[frame] = new OFVector3D[_numVerts];
md2_frame *cf = (md2_frame *)((char *)_frames + _frameSize * frame);
float sc = 16.0f / scale;
loop(vi, _numVerts)
{
uchar *cv = (uchar *)&cf->vertices[vi].vertex;
OFVector3D *v = &(_mverts[frame])[vi];
v->x = (snap(sn, cv[0] * cf->scale[0]) + cf->translate[0]) / sc;
v->y =
-(snap(sn, cv[1] * cf->scale[1]) + cf->translate[1]) / sc;
v->z = (snap(sn, cv[2] * cf->scale[2]) + cf->translate[2]) / sc;
}
}
- (void)renderWithLight:(OFVector3D &)light
frame:(int)frame
range:(int)range
x:(float)x
y:(float)y
z:(float)z
yaw:(float)yaw
pitch:(float)pitch
scale:(float)sc
speed:(float)speed
snap:(int)sn
basetime:(int)basetime
{
loopi(range) if (!_mverts[frame + i])[self scaleWithFrame:frame + i
scale:sc
snap:sn];
glPushMatrix();
glTranslatef(x, y, z);
glRotatef(yaw + 180, 0, -1, 0);
glRotatef(pitch, 0, 0, 1);
glColor3fv((float *)&light);
if (_displaylist && frame == 0 && range == 1) {
glCallList(_displaylist);
xtraverts += _displaylistverts;
} else {
if (frame == 0 && range == 1) {
static int displaylistn = 10;
glNewList(_displaylist = displaylistn++, GL_COMPILE);
_displaylistverts = xtraverts;
}
int time = lastmillis - basetime;
int fr1 = (int)(time / speed);
float frac1 = (time - fr1 * speed) / speed;
float frac2 = 1 - frac1;
fr1 = fr1 % range + frame;
int fr2 = fr1 + 1;
if (fr2 >= frame + range)
fr2 = frame;
OFVector3D *verts1 = _mverts[fr1];
OFVector3D *verts2 = _mverts[fr2];
for (int *command = _glCommands; (*command) != 0;) {
int numVertex = *command++;
if (numVertex > 0) {
glBegin(GL_TRIANGLE_STRIP);
} else {
glBegin(GL_TRIANGLE_FAN);
numVertex = -numVertex;
}
loopi(numVertex)
{
float tu = *((float *)command++);
float tv = *((float *)command++);
glTexCoord2f(tu, tv);
int vn = *command++;
OFVector3D &v1 = verts1[vn];
OFVector3D &v2 = verts2[vn];
#define ip(c) v1.c *frac2 + v2.c *frac1
glVertex3f(ip(x), ip(z), ip(y));
}
xtraverts += numVertex;
glEnd();
}
if (_displaylist) {
glEndList();
_displaylistverts = xtraverts - _displaylistverts;
}
}
glPopMatrix();
}
@end

16
src/MapModelInfo.h Normal file
View file

@ -0,0 +1,16 @@
#import <ObjFW/ObjFW.h>
OF_ASSUME_NONNULL_BEGIN
@interface MapModelInfo : OFObject
@property (nonatomic) int rad, h, zoff, snap;
@property (copy, nonatomic) OFString *name;
- (instancetype)initWithRad:(int)rad
h:(int)h
zoff:(int)zoff
snap:(int)snap
name:(OFString *)name;
@end
OF_ASSUME_NONNULL_END

20
src/MapModelInfo.m Normal file
View file

@ -0,0 +1,20 @@
#import "MapModelInfo.h"
@implementation MapModelInfo
- (instancetype)initWithRad:(int)rad
h:(int)h
zoff:(int)zoff
snap:(int)snap
name:(OFString *)name
{
self = [super init];
_rad = rad;
_h = h;
_zoff = zoff;
_snap = snap;
_name = [name copy];
return self;
}
@end

View file

@ -5,21 +5,7 @@
#include <memory> #include <memory>
enum { ID_VAR, ID_COMMAND, ID_ALIAS }; #import "Ident.h"
@interface Ident : OFObject
@property (nonatomic) int type; // one of ID_* above
@property (copy, nonatomic) OFString *name;
@property (nonatomic) int min, max; // ID_VAR
@property (nonatomic) int *storage; // ID_VAR
@property (nonatomic) void (*fun)(); // ID_VAR, ID_COMMAND
@property (nonatomic) int narg; // ID_VAR, ID_COMMAND
@property (copy, nonatomic) OFString *action; // ID_ALIAS
@property (nonatomic) bool persist;
@end
@implementation Ident
@end
void void
itoa(char *s, int i) itoa(char *s, int i)

View file

@ -5,6 +5,8 @@
#include <ctype.h> #include <ctype.h>
#include <memory> #include <memory>
#import "KeyMapping.h"
struct cline { struct cline {
char *cref; char *cref;
int outtime; int outtime;
@ -93,26 +95,6 @@ renderconsole() // render buffer taking into account time & scrolling
// keymap is defined externally in keymap.cfg // keymap is defined externally in keymap.cfg
@interface KeyMapping : OFObject
@property (readonly) int code;
@property (readonly, nonatomic) OFString *name;
@property (copy, nonatomic) OFString *action;
- (instancetype)initWithCode:(int)code name:(OFString *)name;
@end
@implementation KeyMapping
- (instancetype)initWithCode:(int)code name:(OFString *)name
{
self = [super init];
_code = code;
_name = [name copy];
return self;
}
@end
static OFMutableArray<KeyMapping *> *keyMappings = nil; static OFMutableArray<KeyMapping *> *keyMappings = nil;
void void

View file

@ -115,17 +115,6 @@ struct block {
int x, y, xs, ys; int x, y, xs, ys;
}; };
@interface MapModelInfo : OFObject
@property (nonatomic) int rad, h, zoff, snap;
@property (copy, nonatomic) OFString *name;
- (instancetype)initWithRad:(int)rad
h:(int)h
zoff:(int)zoff
snap:(int)snap
name:(OFString *)name;
@end
enum { enum {
GUN_FIST = 0, GUN_FIST = 0,
GUN_SG, GUN_SG,

View file

@ -2,6 +2,8 @@
#include "cube.h" #include "cube.h"
#import "MapModelInfo.h"
vector<entity> ents; vector<entity> ents;
static OFString *entmdlnames[] = { static OFString *entmdlnames[] = {

View file

@ -1,6 +1,10 @@
executable('client', executable('client',
[ [
'Cube.mm', 'Cube.mm',
'Ident.m',
'KeyMapping.m',
'MD2.mm',
'MapModelInfo.m',
'client.mm', 'client.mm',
'clientextras.mm', 'clientextras.mm',
'clientgame.mm', 'clientgame.mm',

View file

@ -6,6 +6,8 @@
#include "cube.h" #include "cube.h"
#import "MapModelInfo.h"
bool bool
plcollide(dynent *d, dynent *o, float &headspace, float &hi, plcollide(dynent *d, dynent *o, float &headspace, float &hi,
float &lo) // collide with player or monster float &lo) // collide with player or monster

View file

@ -210,6 +210,7 @@ extern void cleansound();
extern void rendermodel(OFString *mdl, int frame, int range, int tex, float rad, extern void rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
float x, float y, float z, float yaw, float pitch, bool teammate, float x, float y, float z, float yaw, float pitch, bool teammate,
float scale, float speed, int snap = 0, int basetime = 0); float scale, float speed, int snap = 0, int basetime = 0);
@class MapModelInfo;
extern MapModelInfo *getmminfo(int i); extern MapModelInfo *getmminfo(int i);
// server // server

View file

@ -2,244 +2,13 @@
#include "cube.h" #include "cube.h"
struct md2_header { #import "MD2.h"
int magic; #import "MapModelInfo.h"
int version;
int skinWidth, skinHeight;
int frameSize;
int numSkins, numVertices, numTexcoords;
int numTriangles, numGlCommands, numFrames;
int offsetSkins, offsetTexcoords, offsetTriangles;
int offsetFrames, offsetGlCommands, offsetEnd;
};
struct md2_vertex {
uchar vertex[3], lightNormalIndex;
};
struct md2_frame {
float scale[3];
float translate[3];
char name[16];
md2_vertex vertices[1];
};
@interface MD2 : OFObject {
int _numGlCommands;
int *_glCommands;
int _numTriangles;
int _frameSize;
int _numFrames;
int _numVerts;
char *_frames;
OFVector3D **_mverts;
int _displaylist;
int _displaylistverts;
}
@property (nonatomic) MapModelInfo *mmi;
@property (copy, nonatomic) OFString *loadname;
@property (nonatomic) int mdlnum;
@property (nonatomic) bool loaded;
- (bool)loadWithIRI:(OFIRI *)IRI;
- (void)renderWithLight:(OFVector3D &)light
frame:(int)frame
range:(int)range
x:(float)x
y:(float)y
z:(float)z
yaw:(float)yaw
pitch:(float)pitch
scale:(float)scale
speed:(float)speed
snap:(int)snap
basetime:(int)basetime;
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)snap;
@end
static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil; static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
static OFMutableArray<MD2 *> *mapmodels = nil; static OFMutableArray<MD2 *> *mapmodels = nil;
@implementation MD2 static const int FIRSTMDL = 20;
+ (void)initialize
{
if (self != [MD2 class])
return;
mdllookup = [[OFMutableDictionary alloc] init];
mapmodels = [[OFMutableArray alloc] init];
}
- (void)dealloc
{
if (_glCommands)
delete[] _glCommands;
if (_frames)
delete[] _frames;
}
- (bool)loadWithIRI:(OFIRI *)IRI
{
@autoreleasepool {
OFSeekableStream *stream;
@try {
stream = (OFSeekableStream *)[[OFIRIHandler
handlerForIRI:IRI] openItemAtIRI:IRI mode:@"r"];
} @catch (id e) {
return false;
}
if (![stream isKindOfClass:[OFSeekableStream class]])
return false;
md2_header header;
[stream readIntoBuffer:&header exactLength:sizeof(md2_header)];
endianswap(
&header, sizeof(int), sizeof(md2_header) / sizeof(int));
if (header.magic != 844121161 || header.version != 8)
return false;
_frames = new char[header.frameSize * header.numFrames];
if (_frames == NULL)
return false;
[stream seekToOffset:header.offsetFrames whence:OFSeekSet];
[stream readIntoBuffer:_frames
exactLength:header.frameSize * header.numFrames];
for (int i = 0; i < header.numFrames; ++i)
endianswap(
_frames + i * header.frameSize, sizeof(float), 6);
_glCommands = new int[header.numGlCommands];
if (_glCommands == NULL)
return false;
[stream seekToOffset:header.offsetGlCommands whence:OFSeekSet];
[stream readIntoBuffer:_glCommands
exactLength:header.numGlCommands * sizeof(int)];
endianswap(_glCommands, sizeof(int), header.numGlCommands);
_numFrames = header.numFrames;
_numGlCommands = header.numGlCommands;
_frameSize = header.frameSize;
_numTriangles = header.numTriangles;
_numVerts = header.numVertices;
[stream close];
_mverts = new OFVector3D *[_numFrames];
loopj(_numFrames) _mverts[j] = NULL;
return true;
}
}
float
snap(int sn, float f)
{
return sn ? (float)(((int)(f + sn * 0.5f)) & (~(sn - 1))) : f;
}
- (void)scaleWithFrame:(int)frame scale:(float)scale snap:(int)sn
{
_mverts[frame] = new OFVector3D[_numVerts];
md2_frame *cf = (md2_frame *)((char *)_frames + _frameSize * frame);
float sc = 16.0f / scale;
loop(vi, _numVerts)
{
uchar *cv = (uchar *)&cf->vertices[vi].vertex;
OFVector3D *v = &(_mverts[frame])[vi];
v->x = (snap(sn, cv[0] * cf->scale[0]) + cf->translate[0]) / sc;
v->y =
-(snap(sn, cv[1] * cf->scale[1]) + cf->translate[1]) / sc;
v->z = (snap(sn, cv[2] * cf->scale[2]) + cf->translate[2]) / sc;
}
}
- (void)renderWithLight:(OFVector3D &)light
frame:(int)frame
range:(int)range
x:(float)x
y:(float)y
z:(float)z
yaw:(float)yaw
pitch:(float)pitch
scale:(float)sc
speed:(float)speed
snap:(int)sn
basetime:(int)basetime
{
loopi(range) if (!_mverts[frame + i])[self scaleWithFrame:frame + i
scale:sc
snap:sn];
glPushMatrix();
glTranslatef(x, y, z);
glRotatef(yaw + 180, 0, -1, 0);
glRotatef(pitch, 0, 0, 1);
glColor3fv((float *)&light);
if (_displaylist && frame == 0 && range == 1) {
glCallList(_displaylist);
xtraverts += _displaylistverts;
} else {
if (frame == 0 && range == 1) {
static int displaylistn = 10;
glNewList(_displaylist = displaylistn++, GL_COMPILE);
_displaylistverts = xtraverts;
}
int time = lastmillis - basetime;
int fr1 = (int)(time / speed);
float frac1 = (time - fr1 * speed) / speed;
float frac2 = 1 - frac1;
fr1 = fr1 % range + frame;
int fr2 = fr1 + 1;
if (fr2 >= frame + range)
fr2 = frame;
OFVector3D *verts1 = _mverts[fr1];
OFVector3D *verts2 = _mverts[fr2];
for (int *command = _glCommands; (*command) != 0;) {
int numVertex = *command++;
if (numVertex > 0) {
glBegin(GL_TRIANGLE_STRIP);
} else {
glBegin(GL_TRIANGLE_FAN);
numVertex = -numVertex;
}
loopi(numVertex)
{
float tu = *((float *)command++);
float tv = *((float *)command++);
glTexCoord2f(tu, tv);
int vn = *command++;
OFVector3D &v1 = verts1[vn];
OFVector3D &v2 = verts2[vn];
#define ip(c) v1.c *frac2 + v2.c *frac1
glVertex3f(ip(x), ip(z), ip(y));
}
xtraverts += numVertex;
glEnd();
}
if (_displaylist) {
glEndList();
_displaylistverts = xtraverts - _displaylistverts;
}
}
glPopMatrix();
}
const int FIRSTMDL = 20;
void void
delayedload(MD2 *m) delayedload(MD2 *m)
@ -265,25 +34,30 @@ delayedload(MD2 *m)
} }
} }
int modelnum = 0;
MD2 * MD2 *
loadmodel(OFString *name) loadmodel(OFString *name)
{ {
@autoreleasepool { @autoreleasepool {
static int modelnum = 0;
MD2 *m = mdllookup[name]; MD2 *m = mdllookup[name];
if (m != nil) if (m != nil)
return m; return m;
m = [[MD2 alloc] init]; m = [[MD2 alloc] init];
m.mdlnum = modelnum++; m.mdlnum = modelnum++;
MapModelInfo *mmi = [[MapModelInfo alloc] initWithRad:2 m.mmi = [[MapModelInfo alloc] initWithRad:2
h:2 h:2
zoff:0 zoff:0
snap:0 snap:0
name:@""]; name:@""];
m.mmi = mmi;
m.loadname = name; m.loadname = name;
if (mdllookup == nil)
mdllookup = [[OFMutableDictionary alloc] init];
mdllookup[name] = m; mdllookup[name] = m;
return m; return m;
} }
} }
@ -293,13 +67,15 @@ mapmodel(
OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name) OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
{ {
MD2 *m = loadmodel(name); MD2 *m = loadmodel(name);
MapModelInfo *mmi = m.mmi = [[MapModelInfo alloc] initWithRad:(int)rad.longLongValue
[[MapModelInfo alloc] initWithRad:(int)rad.longLongValue h:(int)h.longLongValue
h:(int)h.longLongValue zoff:(int)zoff.longLongValue
zoff:(int)zoff.longLongValue snap:(int)snap.longLongValue
snap:(int)snap.longLongValue name:m.loadname];
name:m.loadname];
m.mmi = mmi; if (mapmodels == nil)
mapmodels = [[OFMutableArray alloc] init];
[mapmodels addObject:m]; [mapmodels addObject:m];
} }
COMMAND(mapmodel, ARG_5STR) COMMAND(mapmodel, ARG_5STR)
@ -365,23 +141,3 @@ rendermodel(OFString *mdl, int frame, int range, int tex, float rad, float x,
snap:snap snap:snap
basetime:basetime]; basetime:basetime];
} }
@end
@implementation MapModelInfo
- (instancetype)initWithRad:(int)rad
h:(int)h
zoff:(int)zoff
snap:(int)snap
name:(OFString *)name
{
self = [super init];
_rad = rad;
_h = h;
_zoff = zoff;
_snap = snap;
_name = [name copy];
return self;
}
@end