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')
add_global_arguments(
[
'-fobjc-arc',
'-fobjc-arc-exceptions'
],
language: 'objcpp')
foreach lang : ['objc', 'objcpp']
add_global_arguments(
[
'-fobjc-arc',
'-fobjc-arc-exceptions'
],
language: lang)
endforeach
objfw_dep = dependency('objfw')
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>
enum { ID_VAR, ID_COMMAND, ID_ALIAS };
@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
#import "Ident.h"
void
itoa(char *s, int i)

View file

@ -5,6 +5,8 @@
#include <ctype.h>
#include <memory>
#import "KeyMapping.h"
struct cline {
char *cref;
int outtime;
@ -93,26 +95,6 @@ renderconsole() // render buffer taking into account time & scrolling
// 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;
void

View file

@ -115,17 +115,6 @@ struct block {
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 {
GUN_FIST = 0,
GUN_SG,

View file

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

View file

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

View file

@ -6,6 +6,8 @@
#include "cube.h"
#import "MapModelInfo.h"
bool
plcollide(dynent *d, dynent *o, float &headspace, float &hi,
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,
float x, float y, float z, float yaw, float pitch, bool teammate,
float scale, float speed, int snap = 0, int basetime = 0);
@class MapModelInfo;
extern MapModelInfo *getmminfo(int i);
// server

View file

@ -2,244 +2,13 @@
#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];
};
@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
#import "MD2.h"
#import "MapModelInfo.h"
static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
static OFMutableArray<MD2 *> *mapmodels = nil;
@implementation MD2
+ (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;
static const int FIRSTMDL = 20;
void
delayedload(MD2 *m)
@ -265,25 +34,30 @@ delayedload(MD2 *m)
}
}
int modelnum = 0;
MD2 *
loadmodel(OFString *name)
{
@autoreleasepool {
static int modelnum = 0;
MD2 *m = mdllookup[name];
if (m != nil)
return m;
m = [[MD2 alloc] init];
m.mdlnum = modelnum++;
MapModelInfo *mmi = [[MapModelInfo alloc] initWithRad:2
h:2
zoff:0
snap:0
name:@""];
m.mmi = mmi;
m.mmi = [[MapModelInfo alloc] initWithRad:2
h:2
zoff:0
snap:0
name:@""];
m.loadname = name;
if (mdllookup == nil)
mdllookup = [[OFMutableDictionary alloc] init];
mdllookup[name] = m;
return m;
}
}
@ -293,13 +67,15 @@ mapmodel(
OFString *rad, OFString *h, OFString *zoff, OFString *snap, OFString *name)
{
MD2 *m = loadmodel(name);
MapModelInfo *mmi =
[[MapModelInfo alloc] initWithRad:(int)rad.longLongValue
h:(int)h.longLongValue
zoff:(int)zoff.longLongValue
snap:(int)snap.longLongValue
name:m.loadname];
m.mmi = mmi;
m.mmi = [[MapModelInfo alloc] initWithRad:(int)rad.longLongValue
h:(int)h.longLongValue
zoff:(int)zoff.longLongValue
snap:(int)snap.longLongValue
name:m.loadname];
if (mapmodels == nil)
mapmodels = [[OFMutableArray alloc] init];
[mapmodels addObject:m];
}
COMMAND(mapmodel, ARG_5STR)
@ -365,23 +141,3 @@ rendermodel(OFString *mdl, int frame, int range, int tex, float rad, float x,
snap:snap
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