Compare commits
4 Commits
ce465ef449
...
e81750300d
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e81750300d | ||
![]() |
446ff24fcf | ||
![]() |
309af8f59e | ||
![]() |
7b6ce73fa5 |
152
src/game.c
152
src/game.c
@ -5,6 +5,8 @@
|
||||
#include"resman.h"
|
||||
#include<cglm/vec3.h>
|
||||
|
||||
#define SUBFEET(cp) (cp->capsule.radius)
|
||||
|
||||
struct Game Game;
|
||||
|
||||
void game_init() {
|
||||
@ -29,8 +31,8 @@ void game_init() {
|
||||
}
|
||||
|
||||
struct CollisionPair {
|
||||
dGeomID g1; // greater
|
||||
dGeomID g2; // lesser
|
||||
uint16_t e1; // greater
|
||||
uint16_t e2; // lesser
|
||||
uint8_t x;
|
||||
} __attribute__((packed));
|
||||
static size_t activeCollisionCount, activeCollisionCapacity;
|
||||
@ -38,22 +40,22 @@ static struct CollisionPair *activeCollisions;
|
||||
int pair_comparator(const void *a_, const void *b_) {
|
||||
const struct CollisionPair *a = a_;
|
||||
const struct CollisionPair *b = b_;
|
||||
if(a->g1 == b->g1) {
|
||||
return (uintptr_t) a->g2 - (uintptr_t) b->g2;
|
||||
if(a->e1 == b->e1) {
|
||||
return (intmax_t) a->e2 - (intmax_t) b->e2;
|
||||
} else {
|
||||
return (uintptr_t) a->g1 - (uintptr_t) b->g1;
|
||||
return (intmax_t) a->e1 - (intmax_t) b->e1;
|
||||
}
|
||||
}
|
||||
static int activate_pair(dGeomID g1, dGeomID g2) {
|
||||
static int activate_pair(uint16_t e1, uint16_t e2) {
|
||||
struct CollisionPair p = {
|
||||
.g1 = g1 > g2 ? g1 : g2,
|
||||
.g2 = g1 > g2 ? g2 : g1,
|
||||
.e1 = e1 > e2 ? e1 : e2,
|
||||
.e2 = e1 > e2 ? e2 : e1,
|
||||
};
|
||||
|
||||
struct CollisionPair *peepee = bsearch(&p, activeCollisions, activeCollisionCount, sizeof(struct CollisionPair), pair_comparator);
|
||||
|
||||
if(peepee) {
|
||||
peepee->x++;
|
||||
peepee->x = 2;
|
||||
return TRIGGER_EV_CONTINUOUS;
|
||||
}
|
||||
|
||||
@ -72,8 +74,8 @@ static int activate_pair(dGeomID g1, dGeomID g2) {
|
||||
static void tick_pairs() {
|
||||
for(size_t i = 0; i < activeCollisionCount;) {
|
||||
if(--activeCollisions[i].x == 0) {
|
||||
uint16_t e1 = (uintptr_t) dGeomGetData(activeCollisions[i].g1);
|
||||
uint16_t e2 = (uintptr_t) dGeomGetData(activeCollisions[i].g2);
|
||||
uint16_t e1 = activeCollisions[i].e1;
|
||||
uint16_t e2 = activeCollisions[i].e2;
|
||||
|
||||
if(e1 != ENT_ID_INVALID) {
|
||||
struct CPhysics *p1 = game_getcomponent(e1, physics);
|
||||
@ -110,6 +112,8 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
||||
uint16_t e1 = (uintptr_t) dGeomGetData(g1);
|
||||
uint16_t e2 = (uintptr_t) dGeomGetData(g2);
|
||||
|
||||
if(e1 != ENT_ID_INVALID && e1 == e2) return;
|
||||
|
||||
dBodyID b1 = dGeomGetBody(g1);
|
||||
dBodyID b2 = dGeomGetBody(g2);
|
||||
|
||||
@ -133,8 +137,6 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
||||
if(movingPlatform) {
|
||||
const dReal *platvel = dBodyGetLinearVel(movingPlatform == 1 ? b1 : b2);
|
||||
|
||||
//if(i == 0)printf("get %f %f %f\n", platvel[0], platvel[1], platvel[2]);
|
||||
|
||||
contact[i].surface.mode |= dContactMotion1 | dContactMotion2 | dContactMotionN | dContactFDir1;
|
||||
contact[i].surface.mode |= dContactSoftERP;
|
||||
contact[i].surface.soft_erp = 0.9;
|
||||
@ -155,8 +157,11 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
||||
|
||||
int ghost = 0;
|
||||
|
||||
if(dGeomGetCategoryBits(g1) & CATEGORY_GHOST) ghost = 1;
|
||||
if(dGeomGetCategoryBits(g2) & CATEGORY_GHOST) ghost = 1;
|
||||
|
||||
if(numc) {
|
||||
int triggerType = activate_pair(g1, g2);
|
||||
int triggerType = activate_pair(e1, e2);
|
||||
|
||||
if(e1 != ENT_ID_INVALID) {
|
||||
struct CPhysics *cp = game_getcomponent(e1, physics);
|
||||
@ -168,6 +173,11 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
||||
if(cp->dynamics & CPHYSICS_GHOST) {
|
||||
ghost = 1;
|
||||
}
|
||||
|
||||
struct CMovement *cm = game_getcomponent(e1, movement);
|
||||
if(cm && cm->holding != ENT_ID_INVALID && cm->holding == e2) {
|
||||
ghost = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(e2 != ENT_ID_INVALID) {
|
||||
@ -180,6 +190,11 @@ static void contact_callback(void *data, dGeomID g1, dGeomID g2) {
|
||||
if(cp->dynamics & CPHYSICS_GHOST) {
|
||||
ghost = 1;
|
||||
}
|
||||
|
||||
struct CMovement *cm = game_getcomponent(e2, movement);
|
||||
if(cm && cm->holding != ENT_ID_INVALID && cm->holding == e1) {
|
||||
ghost = 1;
|
||||
}
|
||||
}
|
||||
|
||||
float friction = 1;
|
||||
@ -318,30 +333,35 @@ static void game_character_controller_raycast_handler(void *data, dGeomID g1, dG
|
||||
|
||||
vec3 n = {0, -1, 0};
|
||||
|
||||
struct CPhysics *cp1 = game_getcomponent(e1, physics);
|
||||
struct CPhysics *cp2 = game_getcomponent(e2, physics);
|
||||
|
||||
if((cp2 && (cp2->dynamics & CPHYSICS_GHOST)) || (cp1 && (cp1->dynamics & CPHYSICS_GHOST))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(dGeomGetClass(g1) == dRayClass) {
|
||||
dBodyID bid = dGeomGetBody(cp1->geom);
|
||||
|
||||
struct CMovement *cm = game_getcomponent(e1, movement);
|
||||
|
||||
struct CPhysics *cp2 = game_getcomponent(e2, physics);
|
||||
if(cp2 && (cp2->dynamics & CPHYSICS_GHOST)) {
|
||||
return;
|
||||
}
|
||||
cm->groundDepth = dGeomRayGetLength(g1) - contact[0].geom.depth;
|
||||
|
||||
if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) {
|
||||
cm->canJump = 1;
|
||||
glm_vec3_scale(contact[0].geom.normal, 1, cm->groundNormal);
|
||||
}
|
||||
} else if(dGeomGetClass(g2) == dRayClass) {
|
||||
struct CMovement *cm = game_getcomponent(e2, movement);
|
||||
|
||||
struct CPhysics *cp1 = game_getcomponent(e1, physics);
|
||||
if(cp1 && (cp1->dynamics & CPHYSICS_GHOST)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7) {
|
||||
if(glm_vec3_dot(contact[0].geom.normal, n) <= -0.7 && cm->groundDepth > SUBFEET(cp1)) {
|
||||
cm->canJump = 1;
|
||||
glm_vec3_scale(contact[0].geom.normal, -1, cm->groundNormal);
|
||||
}
|
||||
} else if(dGeomGetClass(g2) == dRayClass) {
|
||||
dBodyID bid = dGeomGetBody(cp2->geom);
|
||||
|
||||
struct CMovement *cm = game_getcomponent(e2, movement);
|
||||
|
||||
cm->groundDepth = dGeomRayGetLength(g2) - contact[0].geom.depth;
|
||||
|
||||
if(glm_vec3_dot(contact[0].geom.normal, n) >= +0.7 && cm->groundDepth > SUBFEET(cp2)) {
|
||||
cm->canJump = 1;
|
||||
glm_vec3_scale(contact[0].geom.normal, +1, cm->groundNormal);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -349,6 +369,10 @@ static void game_character_controller_raycast_handler(void *data, dGeomID g1, dG
|
||||
void game_character_controller_raycast() {
|
||||
dGeomID rayGeoms[Game.entities.movementCount];
|
||||
|
||||
for(size_t i = 0; i < Game.entities.movementCount; i++) {
|
||||
Game.entities.movement[i].canJump = 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < Game.entities.movementCount; i++) {
|
||||
struct CPhysics *cp = game_getcomponent(Game.entities.movement[i].entity, physics);
|
||||
|
||||
@ -357,9 +381,7 @@ void game_character_controller_raycast() {
|
||||
continue;
|
||||
}
|
||||
|
||||
const float raylen = 0.5;
|
||||
|
||||
rayGeoms[i] = dCreateRay(Game.space, raylen);
|
||||
rayGeoms[i] = dCreateRay(Game.space, cp->capsule.length / 2 + cp->capsule.radius + SUBFEET(cp));
|
||||
|
||||
dGeomSetData(rayGeoms[i], (void*) (uintptr_t) Game.entities.movement[i].entity);
|
||||
|
||||
@ -370,7 +392,7 @@ void game_character_controller_raycast() {
|
||||
|
||||
const float *position = dBodyGetPosition(bid);
|
||||
|
||||
dGeomRaySet(rayGeoms[i], position[0], position[1] - cp->capsule.length / 2 - cp->capsule.radius + raylen / 2, position[2], 0, -1, 0);
|
||||
dGeomRaySet(rayGeoms[i], position[0], position[1], position[2], 0, -1, 0);
|
||||
}
|
||||
|
||||
dSpaceCollide(Game.space, NULL, game_character_controller_raycast_handler);
|
||||
@ -430,9 +452,18 @@ void game_update() {
|
||||
if(cp && cp->geom) {
|
||||
dBodyID bid = dGeomGetBody(cp->geom);
|
||||
if(Game.entities.movement[i].canJump) {
|
||||
dBodySetLinearVel(bid, 0, 0, 0);
|
||||
if(dBodyGetLinearVel(bid)[1] <= 0) {
|
||||
Game.entities.movement[i].isJumping = false;
|
||||
}
|
||||
|
||||
if(!Game.entities.movement[i].isJumping) {
|
||||
const float *pos = dBodyGetPosition(bid);
|
||||
dBodySetPosition(bid, pos[0], pos[1] + Game.entities.movement[i].groundDepth - cp->capsule.radius / 2 - SUBFEET(cp), pos[2]);
|
||||
|
||||
dBodySetLinearVel(bid, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
dBodySetGravityMode(bid, !Game.entities.movement[i].canJump);
|
||||
dBodySetGravityMode(bid, Game.entities.movement[i].canJump && !Game.entities.movement[i].isJumping ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,14 +499,21 @@ void game_update() {
|
||||
Game.entities.physics[i].box.l);
|
||||
|
||||
break;
|
||||
case CPHYSICS_CAPSULE:
|
||||
Game.entities.physics[i].geom = dCreateCapsule(Game.space,
|
||||
case CPHYSICS_CAPSULE: {
|
||||
dGeomID top = dCreateCapsule(Game.space,
|
||||
Game.entities.physics[i].capsule.radius,
|
||||
Game.entities.physics[i].capsule.length);
|
||||
Game.entities.physics[i].capsule.length - Game.entities.physics[i].capsule.radius);
|
||||
|
||||
dGeomID feet = dCreateSphere(Game.space,
|
||||
Game.entities.physics[i].capsule.radius);
|
||||
|
||||
Game.entities.physics[i].geom = top;
|
||||
Game.entities.physics[i].geom2 = feet;
|
||||
|
||||
dMassSetCapsuleTotal(&mass, Game.entities.physics[i].mass, 2, Game.entities.physics[i].capsule.radius, Game.entities.physics[i].capsule.length);
|
||||
|
||||
break;
|
||||
}
|
||||
case CPHYSICS_SPHERE:
|
||||
Game.entities.physics[i].geom = dCreateSphere(Game.space,
|
||||
Game.entities.physics[i].sphere.radius);
|
||||
@ -489,6 +527,12 @@ void game_update() {
|
||||
dGeomSetCollideBits(Game.entities.physics[i].geom, Game.entities.physics[i].collide);
|
||||
dGeomSetData(Game.entities.physics[i].geom, (void*) Game.entities.physics[i].entity);
|
||||
|
||||
if(Game.entities.physics[i].type == CPHYSICS_CAPSULE) {
|
||||
dGeomSetCategoryBits(Game.entities.physics[i].geom2, CATEGORY_ENTITY | CATEGORY_GHOST);
|
||||
dGeomSetCollideBits(Game.entities.physics[i].geom2, Game.entities.physics[i].collide);
|
||||
dGeomSetData(Game.entities.physics[i].geom2, (void*) Game.entities.physics[i].entity);
|
||||
}
|
||||
|
||||
if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) != CPHYSICS_STATIC) {
|
||||
dBodyID body = dBodyCreate(Game.phys);
|
||||
|
||||
@ -499,10 +543,16 @@ void game_update() {
|
||||
}
|
||||
|
||||
dGeomSetBody(Game.entities.physics[i].geom, body);
|
||||
if(Game.entities.physics[i].geom2) {
|
||||
dGeomSetBody(Game.entities.physics[i].geom2, body);
|
||||
}
|
||||
|
||||
if(Game.entities.physics[i].type == CPHYSICS_CAPSULE) {
|
||||
dBodySetMaxAngularSpeed(body, 0);
|
||||
|
||||
dGeomSetOffsetPosition(Game.entities.physics[i].geom, 0, Game.entities.physics[i].capsule.radius / 2, 0);
|
||||
dGeomSetOffsetPosition(Game.entities.physics[i].geom2, 0, -Game.entities.physics[i].capsule.length / 2, 0);
|
||||
|
||||
// Rotate to Y-up
|
||||
dQuaternion q;
|
||||
dQFromAxisAndAngle(q, 1, 0, 0, M_PI * 0.5);
|
||||
@ -589,23 +639,19 @@ void game_update() {
|
||||
dQFromAxisAndAngle(q, 0, 1, 0, Game.entities.movement[mi].pointing + M_PI);
|
||||
dBodySetQuaternion(bid, q);
|
||||
|
||||
if(Game.entities.movement[mi].jump && (0||Game.entities.movement[mi].canJump)) {
|
||||
Game.entities.movement[mi].canJump = 0;
|
||||
|
||||
dVector3 force;
|
||||
dWorldImpulseToForce(Game.phys, 1.f / GAME_TPS, 0, 5, 0, force);
|
||||
if(Game.entities.movement[mi].jump && Game.entities.movement[mi].canJump) {
|
||||
dVector3 force = {};
|
||||
dWorldImpulseToForce(Game.phys, 1.f / GAME_TPS, 0, 6.5, 0, force);
|
||||
|
||||
if(bid) {
|
||||
dBodyAddForce(bid, force[0], force[1], force[2]);
|
||||
}
|
||||
|
||||
Game.entities.movement[mi].isJumping = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < Game.entities.movementCount; i++) {
|
||||
Game.entities.movement[i].canJump = 0;
|
||||
}
|
||||
|
||||
dSpaceCollide(Game.space, 0, &contact_callback);
|
||||
|
||||
tick_pairs();
|
||||
@ -955,10 +1001,14 @@ void game_killentity(uint16_t eid) {
|
||||
if(cp) {
|
||||
dBodyID bid = dGeomGetBody(cp->geom);
|
||||
|
||||
dGeomDestroy(cp->geom);
|
||||
|
||||
if(bid) {
|
||||
for(dGeomID gid = dBodyGetFirstGeom(bid); gid; gid = dBodyGetNextGeom(gid)) {
|
||||
dGeomDestroy(gid);
|
||||
}
|
||||
|
||||
dBodyDestroy(bid);
|
||||
} else {
|
||||
dGeomDestroy(cp->geom);
|
||||
}
|
||||
|
||||
game_killcomponent_ptr(cp, physics);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#define CATEGORY_STATIC 1
|
||||
#define CATEGORY_RAY 2
|
||||
#define CATEGORY_ENTITY 4
|
||||
#define CATEGORY_GHOST 8
|
||||
|
||||
#define TRIGGER_INVALID 0
|
||||
|
||||
@ -47,7 +48,7 @@ struct TrimeshData {
|
||||
#define CPHYSICS_GHOST 128
|
||||
struct CPhysics {
|
||||
uint16_t entity;
|
||||
dGeomID geom;
|
||||
dGeomID geom, geom2;
|
||||
uint16_t trigger;
|
||||
|
||||
uint8_t type;
|
||||
@ -87,8 +88,9 @@ struct CMovement {
|
||||
uint16_t entity;
|
||||
vec3 dir;
|
||||
float pointing;
|
||||
char jump, canJump;
|
||||
char jump, canJump, isJumping;
|
||||
vec3 groundNormal;
|
||||
float groundDepth;
|
||||
uint16_t holding;
|
||||
};
|
||||
|
||||
|
19
src/k3mix.c
19
src/k3mix.c
@ -161,12 +161,13 @@ static void queue_clone(struct k3MixWave *this, struct k3MixWave *new) {
|
||||
new->clone = queue_clone;
|
||||
new->close = queue_close;
|
||||
|
||||
new->end = this->end;
|
||||
new->loop = this->loop;
|
||||
new->dam = this->dam;
|
||||
new->volume = this->volume;
|
||||
}
|
||||
struct k3MixWave *k3MixQueue() {
|
||||
struct k3MixWave *ret = malloc(sizeof(*ret));
|
||||
struct k3MixWave *ret = calloc(1, sizeof(*ret));
|
||||
ret->refs = 1;
|
||||
ret->sampleRate = FinalSampleRate;
|
||||
ret->channels = FinalChannels;
|
||||
@ -182,6 +183,7 @@ struct k3MixWave *k3MixQueue() {
|
||||
ret->loop = 0;
|
||||
ret->dam = 0;
|
||||
ret->volume = 1;
|
||||
ret->end = false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -260,6 +262,7 @@ static void power_measurement_clone(struct k3MixWave *this, struct k3MixWave *ne
|
||||
new->clone = power_measurement_clone;
|
||||
new->close = power_measurement_close;
|
||||
|
||||
new->end = this->end;
|
||||
new->loop = this->loop;
|
||||
new->dam = this->dam;
|
||||
new->volume = this->volume;
|
||||
@ -308,6 +311,10 @@ struct k3MixWave *k3MixPowerMeasurement(struct k3MixWave *child) {
|
||||
static size_t playingCount, playingCapacity;
|
||||
static struct k3MixWave **playings;
|
||||
|
||||
void k3MixStopSmooth(struct k3MixWave *wav) {
|
||||
wav->fade = -0.01;
|
||||
}
|
||||
|
||||
void k3MixStop(struct k3MixWave *wav) {
|
||||
for(size_t i = 0; i < playingCount; i++) {
|
||||
if(playings[i] == wav) {
|
||||
@ -346,6 +353,16 @@ __attribute__((optimize("Ofast"))) static void k3MixDoYourThang(size_t sampleCou
|
||||
for(size_t i = 0; i < playingCount;) {
|
||||
intmax_t read = playings[i]->read(playings[i], sampleCount, FinalData);
|
||||
|
||||
if(playings[i]->fade) {
|
||||
playings[i]->volume += playings[i]->fade;
|
||||
if(playings[i]->volume > 1) {
|
||||
playings[i]->volume = 1;
|
||||
playings[i]->fade = 0;
|
||||
} else if(playings[i]->volume < 0) {
|
||||
playings[i]->end = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(playings[i]->end) {
|
||||
k3MixStop(playings[i]);
|
||||
} else i++;
|
||||
|
@ -29,6 +29,7 @@ struct k3MixWave {
|
||||
bool end;
|
||||
uint16_t dam;
|
||||
float volume;
|
||||
float fade;
|
||||
};
|
||||
|
||||
void k3MixInit(uint32_t sampleRate, uint8_t channels);
|
||||
@ -44,6 +45,7 @@ struct k3MixWave *k3MixPowerMeasurement(struct k3MixWave *child);
|
||||
float k3MixPowerMeasurementGetRMS(struct k3MixWave*);
|
||||
|
||||
void k3MixStop(struct k3MixWave*);
|
||||
void k3MixStopSmooth(struct k3MixWave*);
|
||||
struct k3MixWave *k3MixPlay(struct k3MixWave*);
|
||||
void k3MixPlayDirect(struct k3MixWave*);
|
||||
|
||||
|
119
src/luaapi.c
119
src/luaapi.c
@ -17,6 +17,8 @@
|
||||
#include"net_hi.h"
|
||||
#include"k3particles.h"
|
||||
#include<GLFW/glfw3.h>
|
||||
#include"ssort.h"
|
||||
#include<ctype.h>
|
||||
|
||||
/*
|
||||
* This is by far the least clean or well-maintained source in the
|
||||
@ -722,6 +724,17 @@ static int dagame_mixstop(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dagame_mixstopsmooth(lua_State *L) {
|
||||
struct mixitem *i = lua_touserdata(L, 1);
|
||||
|
||||
assert(i->type != MIXITEM_SOURCE);
|
||||
k3MixStopSmooth(i->thing);
|
||||
|
||||
lua_pushvalue(L, 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dagame_mixpower(lua_State *L) {
|
||||
struct mixitem *i = lua_touserdata(L, 1);
|
||||
|
||||
@ -2404,7 +2417,7 @@ static int dagame_mdl_desc_append(lua_State *L) {
|
||||
}
|
||||
|
||||
static int os_time(lua_State *L) {
|
||||
lua_pushnumber(L, glfwGetTime() - LuaapiStartTime);
|
||||
lua_pushnumber(L, isnan(LuaapiStartTime) ? 0 : glfwGetTime() - LuaapiStartTime);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2755,6 +2768,9 @@ void luaapi_init() {
|
||||
lua_pushcfunction(L, dagame_mixstop);
|
||||
lua_setfield(L, -2, "stop");
|
||||
|
||||
lua_pushcfunction(L, dagame_mixstopsmooth);
|
||||
lua_setfield(L, -2, "stopsmooth");
|
||||
|
||||
lua_pushcfunction(L, game_mixqueue);
|
||||
lua_setfield(L, -2, "queue");
|
||||
|
||||
@ -3113,6 +3129,8 @@ void luaapi_init() {
|
||||
}
|
||||
|
||||
void luaapi_load(const char *name) {
|
||||
LuaapiStartTime = NAN;
|
||||
|
||||
lua_getglobal(L, "require");
|
||||
lua_pushstring(L, name);
|
||||
if(lua_pcall(L, 1, 1, 0) != LUA_OK) {
|
||||
@ -3123,7 +3141,7 @@ void luaapi_load(const char *name) {
|
||||
|
||||
lua_getfield(L, -1, "load");
|
||||
if(lua_pcall(L, 0, 0, 0) != LUA_OK) {
|
||||
puts(lua_tostring(L, -1));
|
||||
k3Log(k3_ERR, "%s", lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
return;
|
||||
}
|
||||
@ -3131,6 +3149,8 @@ void luaapi_load(const char *name) {
|
||||
if(Game.isAuthority) {
|
||||
luaapi_join(NULL, 0);
|
||||
}
|
||||
|
||||
LuaapiStartTime = glfwGetTime();
|
||||
}
|
||||
|
||||
void luaapi_render(double dt, double alpha) {
|
||||
@ -3265,26 +3285,99 @@ static const char *k3glslloader(const char *fn) {
|
||||
return data;
|
||||
}
|
||||
|
||||
#define KV_STORE_SIZE 128
|
||||
struct KVPair {
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
typedef struct KVPair KVStore[KV_STORE_SIZE];
|
||||
|
||||
static intmax_t kvpair_compare(const void *a_, const void *b_) {
|
||||
const struct KVPair *a = a_;
|
||||
const struct KVPair *b = b_;
|
||||
|
||||
if(!a->key) {
|
||||
return 1;
|
||||
} else if(!b->key) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return strcmp(a->key, b->key);
|
||||
}
|
||||
static char *kvstore_tostring(KVStore store) {
|
||||
ssort(store, KV_STORE_SIZE, sizeof(struct KVPair), kvpair_compare);
|
||||
|
||||
const size_t sz = 2048;
|
||||
char *ret = calloc(1, sz);
|
||||
|
||||
for(size_t i = 0; i < KV_STORE_SIZE; i++) {
|
||||
if(store[i].key == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
char def[256];
|
||||
snprintf(def, sizeof(def), "%s\x1F%s\x1E", store[i].key, store[i].value);
|
||||
|
||||
strncat(ret, def, sz - strlen(ret) - 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
static bool kvstore_add(KVStore store, char *key, char *value) {
|
||||
for(size_t i = 0; i < KV_STORE_SIZE; i++) {
|
||||
if(store[i].key == NULL) {
|
||||
store[i].key = key;
|
||||
store[i].value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static bool kvstore_add_fmt(KVStore store, char *key, const char *format, ...) {
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
|
||||
va_list vl2;
|
||||
va_copy(vl2, vl);
|
||||
size_t len = vsnprintf(NULL, 0, format, vl2);
|
||||
|
||||
char *def = malloc(len);
|
||||
vsnprintf(def, len, format, vl);
|
||||
|
||||
va_end(vl);
|
||||
va_end(vl2);
|
||||
|
||||
return kvstore_add(store, key, def);
|
||||
}
|
||||
static void kvstore_free(KVStore store) {
|
||||
for(size_t i = 0; i < KV_STORE_SIZE; i++) {
|
||||
free(store[i].key);
|
||||
free(store[i].value);
|
||||
}
|
||||
}
|
||||
|
||||
// The glsl field of a material table is cached and stored
|
||||
// in the resource manager. This function generates its name.
|
||||
static char *glsl_table_fullname() {
|
||||
KVStore store = {};
|
||||
|
||||
lua_getfield(L, -1, "vs");
|
||||
lua_geti(L, -1, 1); // Version
|
||||
size_t vsVer = lua_tointeger(L, -1);
|
||||
lua_geti(L, -2, 2); // Filename
|
||||
char *vsFile = strdup(lua_tostring(L, -1));
|
||||
kvstore_add(store, strdup("vs"), strdup(lua_tostring(L, -1)));
|
||||
kvstore_add_fmt(store, strdup("vsv"), "%lu", vsVer);
|
||||
lua_pop(L, 3);
|
||||
|
||||
lua_getfield(L, -1, "fs");
|
||||
lua_geti(L, -1, 1); // Version
|
||||
size_t fsVer = lua_tointeger(L, -1);
|
||||
lua_geti(L, -2, 2); // Filename
|
||||
char *fsFile = strdup(lua_tostring(L, -1));
|
||||
kvstore_add(store, strdup("fs"), strdup(lua_tostring(L, -1)));
|
||||
kvstore_add_fmt(store, strdup("fsv"), "%lu", fsVer);
|
||||
lua_pop(L, 3);
|
||||
|
||||
char ret[1024];
|
||||
snprintf(ret, sizeof(ret), "\x1E%u\x1E%s\x1E%u\x1E%s\x1E", vsVer, vsFile, fsVer, fsFile);
|
||||
|
||||
lua_getfield(L, -1, "defs");
|
||||
lua_pushnil(L);
|
||||
while(lua_next(L, -2)) {
|
||||
@ -3294,19 +3387,17 @@ static char *glsl_table_fullname() {
|
||||
continue;
|
||||
}
|
||||
|
||||
char def[128];
|
||||
snprintf(def, sizeof(def), "%s\x1F%s\x1E", lua_tostring(L, -2), lua_tostring(L, -1));
|
||||
|
||||
strncat(ret, def, sizeof(ret) - strlen(ret) - 1);
|
||||
kvstore_add(store, strdup(lua_tostring(L, -2)), strdup(lua_tostring(L, -1)));
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
free(vsFile);
|
||||
free(fsFile);
|
||||
char *fullname = kvstore_tostring(store);
|
||||
|
||||
return strdup(ret);
|
||||
kvstore_free(store);
|
||||
|
||||
return fullname;
|
||||
}
|
||||
|
||||
static int parse_glsl_table(struct k3Mat *mat) {
|
||||
|
13
src/main.c
13
src/main.c
@ -416,8 +416,6 @@ int main(int argc_, char **argv_) {
|
||||
|
||||
eng_ui_init();
|
||||
|
||||
LuaapiStartTime = glfwGetTime();
|
||||
|
||||
LastTime = glfwGetTime();
|
||||
|
||||
double accumulator = 0;
|
||||
@ -523,11 +521,16 @@ int main(int argc_, char **argv_) {
|
||||
InstantCamShift--;
|
||||
}
|
||||
if(LuaapiFirstPerson) {
|
||||
struct CRender *c = game_getcomponent(Game.spectated, render);
|
||||
struct CRender *cr = game_getcomponent(Game.spectated, render);
|
||||
struct CPhysics *cp = game_getcomponent(Game.spectated, physics);
|
||||
|
||||
if(c) {
|
||||
if(cr) {
|
||||
vec3 p;
|
||||
glm_vec3_lerp(c->posLast, c->pos, alpha, p);
|
||||
glm_vec3_lerp(cr->posLast, cr->pos, alpha, p);
|
||||
|
||||
if(cp && cp->type == CPHYSICS_CAPSULE) {
|
||||
p[1] += cp->capsule.length / 2;
|
||||
}
|
||||
|
||||
mat4 view;
|
||||
glm_look(p, cameraForwardDir, (vec3) {0, 1, 0}, view);
|
||||
|
Loading…
Reference in New Issue
Block a user