Compare commits

...

47 Commits

Author SHA1 Message Date
mid
b7c0b0780c And it all ended with a real bug to fix; how poetic
All checks were successful
k4 Build Test / do_the_build (push) Successful in 43s
2026-01-22 22:44:30 +02:00
mid
46bd5e8d5e this better be all
All checks were successful
k4 Build Test / do_the_build (push) Successful in 44s
2026-01-22 21:59:50 +02:00
mid
d614e2ced4 just use /dev/urandom
All checks were successful
k4 Build Test / do_the_build (push) Successful in 46s
2026-01-22 21:18:29 +02:00
mid
57fffeb0a3 update 12-win32 to 14-win32
All checks were successful
k4 Build Test / do_the_build (push) Successful in 34s
2026-01-21 22:52:32 +02:00
mid
def545450d add freetype and libz
Some checks failed
k4 Build Test / do_the_build (push) Failing after 24s
2026-01-21 22:49:02 +02:00
mid
9b7ecb3ae7 update k3 commit
Some checks failed
k4 Build Test / do_the_build (push) Failing after 24s
2026-01-21 22:27:45 +02:00
mid
9c2e4ffae1 can't be bothered
Some checks failed
k4 Build Test / do_the_build (push) Failing after 12s
2026-01-21 22:25:24 +02:00
mid
3e14195bf7 What about this, dumbfuck
Some checks failed
k4 Build Test / do_the_build (push) Failing after 5s
2026-01-21 22:22:54 +02:00
mid
055ff4f5ce fixes for build
Some checks failed
k4 Build Test / do_the_build (push) Failing after 4s
2026-01-21 22:20:15 +02:00
mid
4d0e043f4c use latest k3 commit
Some checks failed
k4 Build Test / do_the_build (push) Failing after 5s
2026-01-21 20:54:20 +02:00
mid
3da728c768 Try automated build on Debian 9
Some checks failed
k4 Build Test / do_the_build (push) Failing after 8s
2026-01-21 20:46:43 +02:00
mid
8857b93f90 Updated changelog 2026-01-18 13:52:01 +02:00
mid
cf0f402da3 Add changelog 2026-01-18 13:49:18 +02:00
mid
db46d5506c Many bug fixes 2026-01-18 13:43:51 +02:00
mid
e87417603e k3 interface update 2 2026-01-14 12:00:36 +02:00
mid
0f68c8c7ae k3 interface update 2026-01-14 12:00:16 +02:00
mid
2211193a96 Conditionally load Lua package library (for native libs) 2026-01-14 12:00:07 +02:00
mid
6d821cb361 Expose remove_child function 2026-01-14 11:59:35 +02:00
mid
a2039557bb Fix require filename parsing 2026-01-14 11:59:13 +02:00
mid
a1439664ca Add vsync parameter 2025-12-02 00:04:13 +02:00
mid
0453585751 Move to k3 SDF fonts 2025-12-02 00:04:05 +02:00
mid
5f6dc66a0f Update to newest k3 2025-10-12 20:47:41 +03:00
mid
2e730baf33 Scriptable near and far planes 2025-09-30 11:05:33 +03:00
mid
462412c31a Already .k3m has some legacy bullshit 2025-09-30 11:05:12 +03:00
mid
e4b5f8d361 streamloader return value 2025-09-19 23:11:42 +03:00
mid
f7a429cfbc Free font buffer 2025-09-13 12:02:27 +03:00
mid
3c372a3024 Map to newest k3 2025-09-13 12:02:15 +03:00
mid
f65891932a k3Font walls 2025-08-28 23:32:03 +03:00
mid
177d259304 Add scrollbox and image objects 2025-08-28 14:11:40 +03:00
mid
dbced43b2b Introduce animation trees, remove "standard animations" from core 2025-08-10 15:42:45 +03:00
mid
96da001734 Add game.ui.obj 2025-07-27 16:54:32 +03:00
mid
943601bc3a Introduce k3Menu properties to luaapi 2025-07-27 16:15:55 +03:00
mid
b32671567e Switch to strncasecmp
All checks were successful
k4 Build Test / do_the_build (push) Successful in 52s
2025-07-13 10:15:02 +03:00
mid
f4cf597a95 _DEFAULT_SOURCE and _GNU_SOURCE
Some checks failed
k4 Build Test / do_the_build (push) Failing after 30s
2025-07-13 09:57:52 +03:00
mid
5f2e84d8cf Support LOOPPOINT metadata field for ogg files
Some checks failed
k4 Build Test / do_the_build (push) Failing after 30s
2025-07-12 23:27:33 +03:00
mid
7754e410fd EVEN MORE STABLIER
All checks were successful
k4 Build Test / do_the_build (push) Successful in 56s
2025-07-05 14:06:07 +03:00
mid
5a3a524cb3 add libgomp
All checks were successful
k4 Build Test / do_the_build (push) Successful in 50s
2025-07-05 11:26:59 +03:00
mid
55b8e827c2 Strip
All checks were successful
k4 Build Test / do_the_build (push) Successful in 50s
2025-07-05 10:39:43 +03:00
mid
368664d246 Bug fixes
All checks were successful
k4 Build Test / do_the_build (push) Successful in 56s
2025-06-29 22:22:13 +03:00
mid
90f0e2dd42 Physics stability 2025-06-29 20:47:24 +03:00
mid
355df2ee44 Extend network traversal to local addresses 2025-06-29 20:47:14 +03:00
mid
e126db573a Change top-level dir name
All checks were successful
k4 Build Test / do_the_build (push) Successful in 58s
2025-06-28 14:01:32 +03:00
mid
ceb8ccb7d4 README.md 2025-06-28 13:20:38 +03:00
mid
e81750300d Abstract shader parameters (to make them modifiable later) 2025-06-28 13:18:58 +03:00
mid
446ff24fcf Make time per-scene 2025-06-28 13:18:24 +03:00
mid
309af8f59e stopsmooth 2025-06-28 13:17:58 +03:00
mid
7b6ce73fa5 Improve ray-based character controller 2025-06-28 13:17:20 +03:00
23 changed files with 1675 additions and 460 deletions

View File

@@ -14,11 +14,12 @@ jobs:
with:
submodules: 'true'
- run: mkdir build build/k3 build/k3/compr bin bin/assets
- run: CC="i686-w64-mingw32-gcc" CFLAGS="-I/usr/i686-w64-mingw32/include -I/usr/i686-w64-mingw32/include/lua5.3 -L/usr/i686-w64-mingw32/lib -Wno-error" make -B
- run: CC="i686-linux-gnu-gcc" CFLAGS="-I/usr/i686-linux-gnu/include -I/usr/i686-linux-gnu/include/lua5.3 -L/usr/i686-linux-gnu/lib -Wno-error -include /home/git/force_link_glibc_2.20.h" make -B
- run: cp /usr/lib/gcc/i686-w64-mingw32/12-win32/libgcc_s_dw2-1.dll /usr/lib/gcc/i686-w64-mingw32/12-win32/libstdc++-6.dll /usr/i686-w64-mingw32/lib/libportaudio-2.dll /usr/i686-w64-mingw32/lib/libwinpthread-1.dll bin/
- run: LIBS="-lfreetype -l:libz.a" CC="i686-w64-mingw32-gcc" CFLAGS="-I/usr/i686-w64-mingw32/include -I/usr/i686-w64-mingw32/include/lua5.3 -L/usr/i686-w64-mingw32/lib -Wno-error" make -B
- run: cp /usr/lib/gcc/i686-w64-mingw32/14-win32/libgcc_s_dw2-1.dll /usr/lib/gcc/i686-w64-mingw32/14-win32/libstdc++-6.dll /usr/i686-w64-mingw32/lib/libportaudio-2.dll /usr/i686-w64-mingw32/lib/libwinpthread-1.dll /usr/lib/gcc/i686-w64-mingw32/14-win32/libgomp-1.dll bin/
- run: curl "http://127.0.0.1:9898/build?root=${{ github.workspace }}"
- run: cp -r /home/git/k4templateassets/* bin/assets/
- run: zip -9r "k4${{ github.ref_name }}.zip" bin/
- run: mv bin k4
- run: zip -9r "k4${{ github.ref_name }}.zip" k4/
- name: Create package
uses: akkuman/gitea-release-action@v1
with:

View File

@@ -10,14 +10,14 @@ k3_HDRS := $(call rwildcard,k3/src,*.h)
k3_OBJS := $(patsubst k3/src/%.c, build/k3/%.o, $(k3_SRCS))
k3_DEPS := $(patsubst k3/src/%.c, build/k3/%.d, $(k3_SRCS))
CFLAGS := $(CFLAGS) -Ik3/src -O2 -fopenmp
CFLAGS := $(CFLAGS) -D_GNU_SOURCE -D_DEFAULT_SOURCE -DGLCA_CUSTOM_GLYPH_DATA -Ik3/src -fopenmp -O2 -flto -fwhole-program -Wno-error=incompatible-pointer-types -Wno-error=int-conversion
ifneq (,$(findstring mingw,$(CC)))
CFLAGS := -static-libgcc -static-libstdc++ -std=gnu99 -march=pentium4 -D_WIN32_WINNT=0x600 -DENET_FEATURE_ADDRESS_MAPPING -fno-pic -no-pie -fms-extensions -fno-pie -Isrc $(CFLAGS)
LIBS := -l:libglfw3.a -lopengl32 -pthread -lm -l:libode.a -l:libvorbisfile.a -l:libvorbis.a -l:libogg.a -lportaudio -lgdi32 -lws2_32 -lwinmm -lstdc++ -lole32 -lsetupapi -lhid -l:liblua5.3.a $(LIBS)
LIBS := -l:libglfw3.a -lopengl32 -pthread -lm -l:libode.a -l:libvorbisfile.a -l:libvorbis.a -l:libogg.a -lportaudio -lgdi32 -lws2_32 -lwinmm -lstdc++ -lole32 -lsetupapi -lhid -l:liblua5.3.a -liphlpapi $(LIBS)
else
CFLAGS := -march=opteron $(SAN) -std=gnu99 -DENET_FEATURE_ADDRESS_MAPPING -fms-extensions -fno-pic -no-pie -fno-pie -Isrc $(CFLAGS)
LIBS := -lglfw3 -pthread -ldl -lm -lode -lstdc++ -llua5.3 -lvorbis -lvorbisfile -lportaudio $(LIBS)
LIBS := -lglfw3 -pthread -ldl -lm -lode -lstdc++ -llua5.3 -lvorbis -lvorbisfile -logg -lasound -lfreetype -lportaudio -lz $(LIBS)
endif
CFLAGS := $(CFLAGS) -DLOCALHOST_ONLY

21
README.md Normal file
View File

@@ -0,0 +1,21 @@
Homepage: https://mid.net.ua/k4.html
## Changelog
## v2
1. k3Menu objects now have stylable properties ala CSS
2. Exposed `game.ui.obj` "base object" which allows you to create your own widgets
3. Revamped the animation system to one with blend trees
4. Added scrollboxes and image objects to k3Menu
5. Replaced the font subsystem with one that uses TrueType fonts directly, and they are drawn using signed distance fields when possible
6. Added `game.near` and `game.far` values for editing the camera planes
7. Added vsync parameter to command line
8. Graphics bug fixes
9. Improved mipmapping
10. Frustum culling
11. Added support for 32-bit indices in models
## v1
Initial release.

2
k3

Submodule k3 updated: 4d74b5e3e9...56ecba05b1

View File

@@ -115,6 +115,8 @@ def write_some_data(context, filepath, doExportEverything):
out.write(struct.pack("4f", m.col[c][0], m.col[c][1], m.col[c][2], m.col[c][3]))
for b in dabones:
out.write(struct.pack("B", dabones.index(b.parent) if b.parent else 255))
for b in dabones:
out.write(b.name.encode("UTF-8") + b'\x00')
for v in vertdict.keys():
out.write(struct.pack("3f", v[0][0], v[0][2], -v[0][1]))

View File

@@ -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) {
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,21 +639,17 @@ 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]);
}
}
}
}
for(size_t i = 0; i < Game.entities.movementCount; i++) {
Game.entities.movement[i].canJump = 0;
Game.entities.movement[mi].isJumping = true;
}
}
}
dSpaceCollide(Game.space, 0, &contact_callback);
@@ -639,7 +685,7 @@ void game_update() {
size_t boneCount = Game.entities.render[ci].cache ? k3MdlGetBoneCount(Game.entities.render[ci].cache) : 0;
if(boneCount) {
struct CBoned *cb = game_getcomponent(Game.entities.render[ci].entity, boned);
/*struct CBoned *cb = game_getcomponent(Game.entities.render[ci].entity, boned);
if(!cb) {
cb = game_ensurecomponent(Game.entities.render[ci].entity, boned);
@@ -695,7 +741,7 @@ void game_update() {
glm_decompose(cb->anim.cache.inter[m], cb->bones[m].translation, rot, scaleignore);
glm_mat4_quat(cb->anim.cache.inter[m], cb->bones[m].rotation);
}
}
}*/
}
dGeomID gid = cp->geom;
@@ -730,7 +776,7 @@ void game_update() {
for(size_t cm = 0; cm < Game.entities.movementCount; cm++) {
struct CBoned *cb = game_getcomponent(Game.entities.movement[cm].entity, boned);
if(cb && cb->anim.standard) {
/*if(cb && cb->anim.standard) {
struct CPhysics *cp = game_getcomponent(Game.entities.movement[cm].entity, physics);
if(cp && cp->geom) {
dBodyID bid = dGeomGetBody(cp->geom);
@@ -743,7 +789,7 @@ void game_update() {
}
}
}
}
}*/
}
for(size_t i = 0; i < Game.conveyorCount; i++) {
@@ -830,7 +876,6 @@ void game_update() {
vec3 dif;
glm_vec3_sub(conveyor->points[nextPoint], conveyor->points[currentPoint], dif);
glm_vec3_scale_as(dif, conveyor->speed * (conveyor->active <= 0 ? -1 : 1), dif);
//printf("set %f %f %f\n", dif[0], dif[1], dif[2]);
dBodySetLinearVel(bid, dif[0], dif[1], dif[2]); // doesn't affect movement, but necessary for proper collision response
}
}
@@ -904,7 +949,7 @@ void game_cleanup() {
Game.entities.renderCount = 0;
for(size_t i = 0; i < Game.entities.bonedCount; i++) {
free(Game.entities.boned[i].bones);
//free(Game.entities.boned[i].bones);
}
Game.entities.bonedCount = 0;
@@ -940,8 +985,8 @@ void game_cleanup() {
Game.phys = dWorldCreate();
dWorldSetGravity(Game.phys, 0, -15, 0);
dWorldSetCFM(Game.phys, 0.0001);
dWorldSetERP(Game.phys, 0.5);
dWorldSetCFM(Game.phys, 0.00002);
dWorldSetERP(Game.phys, 0.1);
Game.space = dHashSpaceCreate(NULL);
@@ -955,10 +1000,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);
@@ -968,7 +1017,7 @@ void game_killentity(uint16_t eid) {
if(cr) {
if(cr->cache) {
if(resman_rev(cr->cache)) {
resman_unref(RESMAN_MODEL, cr->cache);
resman_unref_ptr(RESMAN_MODEL, cr->cache);
}
}

View File

@@ -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;
};
@@ -116,14 +118,7 @@ struct CPlayerCtrl {
struct CBoned {
uint16_t entity;
size_t size;
struct k3AnimationBone *bones;
struct {
uint16_t id;
struct k3Animator cache;
bool standard;
} anim;
struct k3Animator animator;
};
#define CONVEYOR_TYPE_LOOP 0

143
src/gl.h
View File

@@ -1,11 +1,11 @@
/**
* Loader generated by glad 2.0.8 on Fri May 9 09:20:04 2025
* Loader generated by glad 2.0.8 on Sun Oct 12 16:54:54 2025
*
* SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
*
* Generator: C/C++
* Specification: gl
* Extensions: 37
* Extensions: 40
*
* APIs:
* - gl:compatibility=4.6
@@ -19,10 +19,10 @@
* - ON_DEMAND = False
*
* Commandline:
* --api='gl:compatibility=4.6' --extensions='GL_ARB_compatibility,GL_ARB_debug_output,GL_ARB_fragment_program,GL_ARB_fragment_shader,GL_ARB_framebuffer_sRGB,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shading_language_100,GL_ARB_texture_compression_bptc,GL_ARB_texture_float,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_2_10_10_10_rev,GL_EXT_direct_state_access,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_shader4,GL_EXT_shader_image_load_store,GL_EXT_texture_array,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_integer,GL_EXT_texture_sRGB,GL_EXT_transform_feedback,GL_INTEL_conservative_rasterization,GL_KHR_texture_compression_astc_ldr,GL_NV_conservative_raster' c --header-only
* --api='gl:compatibility=4.6' --extensions='GL_ARB_compatibility,GL_ARB_debug_output,GL_ARB_direct_state_access,GL_ARB_fragment_program,GL_ARB_fragment_shader,GL_ARB_framebuffer_sRGB,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shading_language_100,GL_ARB_texture_compression_bptc,GL_ARB_texture_float,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_timer_query,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_2_10_10_10_rev,GL_EXT_direct_state_access,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_multisample,GL_EXT_framebuffer_multisample_blit_scaled,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_shader4,GL_EXT_shader_image_load_store,GL_EXT_texture_array,GL_EXT_texture_compression_rgtc,GL_EXT_texture_compression_s3tc,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_integer,GL_EXT_texture_sRGB,GL_EXT_transform_feedback,GL_INTEL_conservative_rasterization,GL_KHR_debug,GL_KHR_texture_compression_astc_ldr,GL_NV_conservative_raster' c --header-only
*
* Online:
* http://glad.sh/#api=gl%3Acompatibility%3D4.6&extensions=GL_ARB_compatibility%2CGL_ARB_debug_output%2CGL_ARB_fragment_program%2CGL_ARB_fragment_shader%2CGL_ARB_framebuffer_sRGB%2CGL_ARB_shader_image_load_store%2CGL_ARB_shader_image_size%2CGL_ARB_shader_objects%2CGL_ARB_shader_storage_buffer_object%2CGL_ARB_shading_language_100%2CGL_ARB_texture_compression_bptc%2CGL_ARB_texture_float%2CGL_ARB_texture_rg%2CGL_ARB_texture_rgb10_a2ui%2CGL_ARB_vertex_buffer_object%2CGL_ARB_vertex_program%2CGL_ARB_vertex_shader%2CGL_ARB_vertex_type_2_10_10_10_rev%2CGL_EXT_direct_state_access%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_multisample%2CGL_EXT_framebuffer_multisample_blit_scaled%2CGL_EXT_framebuffer_object%2CGL_EXT_framebuffer_sRGB%2CGL_EXT_geometry_shader4%2CGL_EXT_gpu_shader4%2CGL_EXT_shader_image_load_store%2CGL_EXT_texture_array%2CGL_EXT_texture_compression_rgtc%2CGL_EXT_texture_compression_s3tc%2CGL_EXT_texture_filter_anisotropic%2CGL_EXT_texture_integer%2CGL_EXT_texture_sRGB%2CGL_EXT_transform_feedback%2CGL_INTEL_conservative_rasterization%2CGL_KHR_texture_compression_astc_ldr%2CGL_NV_conservative_raster&generator=c&options=HEADER_ONLY
* http://glad.sh/#api=gl%3Acompatibility%3D4.6&extensions=GL_ARB_compatibility%2CGL_ARB_debug_output%2CGL_ARB_direct_state_access%2CGL_ARB_fragment_program%2CGL_ARB_fragment_shader%2CGL_ARB_framebuffer_sRGB%2CGL_ARB_shader_image_load_store%2CGL_ARB_shader_image_size%2CGL_ARB_shader_objects%2CGL_ARB_shader_storage_buffer_object%2CGL_ARB_shading_language_100%2CGL_ARB_texture_compression_bptc%2CGL_ARB_texture_float%2CGL_ARB_texture_rg%2CGL_ARB_texture_rgb10_a2ui%2CGL_ARB_timer_query%2CGL_ARB_vertex_buffer_object%2CGL_ARB_vertex_program%2CGL_ARB_vertex_shader%2CGL_ARB_vertex_type_2_10_10_10_rev%2CGL_EXT_direct_state_access%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_multisample%2CGL_EXT_framebuffer_multisample_blit_scaled%2CGL_EXT_framebuffer_object%2CGL_EXT_framebuffer_sRGB%2CGL_EXT_geometry_shader4%2CGL_EXT_gpu_shader4%2CGL_EXT_shader_image_load_store%2CGL_EXT_texture_array%2CGL_EXT_texture_compression_rgtc%2CGL_EXT_texture_compression_s3tc%2CGL_EXT_texture_filter_anisotropic%2CGL_EXT_texture_integer%2CGL_EXT_texture_sRGB%2CGL_EXT_transform_feedback%2CGL_INTEL_conservative_rasterization%2CGL_KHR_debug%2CGL_KHR_texture_compression_astc_ldr%2CGL_NV_conservative_raster&generator=c&options=HEADER_ONLY
*
*/
@@ -2916,6 +2916,8 @@ GLAD_API_CALL int GLAD_GL_VERSION_4_6;
GLAD_API_CALL int GLAD_GL_ARB_compatibility;
#define GL_ARB_debug_output 1
GLAD_API_CALL int GLAD_GL_ARB_debug_output;
#define GL_ARB_direct_state_access 1
GLAD_API_CALL int GLAD_GL_ARB_direct_state_access;
#define GL_ARB_fragment_program 1
GLAD_API_CALL int GLAD_GL_ARB_fragment_program;
#define GL_ARB_fragment_shader 1
@@ -2940,6 +2942,8 @@ GLAD_API_CALL int GLAD_GL_ARB_texture_float;
GLAD_API_CALL int GLAD_GL_ARB_texture_rg;
#define GL_ARB_texture_rgb10_a2ui 1
GLAD_API_CALL int GLAD_GL_ARB_texture_rgb10_a2ui;
#define GL_ARB_timer_query 1
GLAD_API_CALL int GLAD_GL_ARB_timer_query;
#define GL_ARB_vertex_buffer_object 1
GLAD_API_CALL int GLAD_GL_ARB_vertex_buffer_object;
#define GL_ARB_vertex_program 1
@@ -2982,6 +2986,8 @@ GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB;
GLAD_API_CALL int GLAD_GL_EXT_transform_feedback;
#define GL_INTEL_conservative_rasterization 1
GLAD_API_CALL int GLAD_GL_INTEL_conservative_rasterization;
#define GL_KHR_debug 1
GLAD_API_CALL int GLAD_GL_KHR_debug;
#define GL_KHR_texture_compression_astc_ldr 1
GLAD_API_CALL int GLAD_GL_KHR_texture_compression_astc_ldr;
#define GL_NV_conservative_raster 1
@@ -7530,6 +7536,7 @@ int GLAD_GL_VERSION_4_5 = 0;
int GLAD_GL_VERSION_4_6 = 0;
int GLAD_GL_ARB_compatibility = 0;
int GLAD_GL_ARB_debug_output = 0;
int GLAD_GL_ARB_direct_state_access = 0;
int GLAD_GL_ARB_fragment_program = 0;
int GLAD_GL_ARB_fragment_shader = 0;
int GLAD_GL_ARB_framebuffer_sRGB = 0;
@@ -7542,6 +7549,7 @@ int GLAD_GL_ARB_texture_compression_bptc = 0;
int GLAD_GL_ARB_texture_float = 0;
int GLAD_GL_ARB_texture_rg = 0;
int GLAD_GL_ARB_texture_rgb10_a2ui = 0;
int GLAD_GL_ARB_timer_query = 0;
int GLAD_GL_ARB_vertex_buffer_object = 0;
int GLAD_GL_ARB_vertex_program = 0;
int GLAD_GL_ARB_vertex_shader = 0;
@@ -7563,6 +7571,7 @@ int GLAD_GL_EXT_texture_integer = 0;
int GLAD_GL_EXT_texture_sRGB = 0;
int GLAD_GL_EXT_transform_feedback = 0;
int GLAD_GL_INTEL_conservative_rasterization = 0;
int GLAD_GL_KHR_debug = 0;
int GLAD_GL_KHR_texture_compression_astc_ldr = 0;
int GLAD_GL_NV_conservative_raster = 0;
@@ -10179,6 +10188,106 @@ static void glad_gl_load_GL_ARB_debug_output( GLADuserptrloadfunc load, void* us
glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load(userptr, "glDebugMessageInsertARB");
glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load(userptr, "glGetDebugMessageLogARB");
}
static void glad_gl_load_GL_ARB_direct_state_access( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_ARB_direct_state_access) return;
glad_glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC) load(userptr, "glBindTextureUnit");
glad_glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC) load(userptr, "glBlitNamedFramebuffer");
glad_glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckNamedFramebufferStatus");
glad_glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC) load(userptr, "glClearNamedBufferData");
glad_glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC) load(userptr, "glClearNamedBufferSubData");
glad_glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) load(userptr, "glClearNamedFramebufferfi");
glad_glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) load(userptr, "glClearNamedFramebufferfv");
glad_glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) load(userptr, "glClearNamedFramebufferiv");
glad_glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) load(userptr, "glClearNamedFramebufferuiv");
glad_glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) load(userptr, "glCompressedTextureSubImage1D");
glad_glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) load(userptr, "glCompressedTextureSubImage2D");
glad_glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) load(userptr, "glCompressedTextureSubImage3D");
glad_glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC) load(userptr, "glCopyNamedBufferSubData");
glad_glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC) load(userptr, "glCopyTextureSubImage1D");
glad_glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC) load(userptr, "glCopyTextureSubImage2D");
glad_glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC) load(userptr, "glCopyTextureSubImage3D");
glad_glCreateBuffers = (PFNGLCREATEBUFFERSPROC) load(userptr, "glCreateBuffers");
glad_glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC) load(userptr, "glCreateFramebuffers");
glad_glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC) load(userptr, "glCreateProgramPipelines");
glad_glCreateQueries = (PFNGLCREATEQUERIESPROC) load(userptr, "glCreateQueries");
glad_glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC) load(userptr, "glCreateRenderbuffers");
glad_glCreateSamplers = (PFNGLCREATESAMPLERSPROC) load(userptr, "glCreateSamplers");
glad_glCreateTextures = (PFNGLCREATETEXTURESPROC) load(userptr, "glCreateTextures");
glad_glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC) load(userptr, "glCreateTransformFeedbacks");
glad_glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC) load(userptr, "glCreateVertexArrays");
glad_glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC) load(userptr, "glDisableVertexArrayAttrib");
glad_glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC) load(userptr, "glEnableVertexArrayAttrib");
glad_glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) load(userptr, "glFlushMappedNamedBufferRange");
glad_glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC) load(userptr, "glGenerateTextureMipmap");
glad_glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) load(userptr, "glGetCompressedTextureImage");
glad_glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) load(userptr, "glGetNamedBufferParameteri64v");
glad_glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedBufferParameteriv");
glad_glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC) load(userptr, "glGetNamedBufferPointerv");
glad_glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC) load(userptr, "glGetNamedBufferSubData");
glad_glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferAttachmentParameteriv");
glad_glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferParameteriv");
glad_glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedRenderbufferParameteriv");
glad_glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC) load(userptr, "glGetQueryBufferObjecti64v");
glad_glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC) load(userptr, "glGetQueryBufferObjectiv");
glad_glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC) load(userptr, "glGetQueryBufferObjectui64v");
glad_glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC) load(userptr, "glGetQueryBufferObjectuiv");
glad_glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC) load(userptr, "glGetTextureImage");
glad_glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC) load(userptr, "glGetTextureLevelParameterfv");
glad_glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC) load(userptr, "glGetTextureLevelParameteriv");
glad_glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC) load(userptr, "glGetTextureParameterIiv");
glad_glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC) load(userptr, "glGetTextureParameterIuiv");
glad_glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC) load(userptr, "glGetTextureParameterfv");
glad_glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC) load(userptr, "glGetTextureParameteriv");
glad_glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC) load(userptr, "glGetTransformFeedbacki64_v");
glad_glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC) load(userptr, "glGetTransformFeedbacki_v");
glad_glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC) load(userptr, "glGetTransformFeedbackiv");
glad_glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC) load(userptr, "glGetVertexArrayIndexed64iv");
glad_glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC) load(userptr, "glGetVertexArrayIndexediv");
glad_glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC) load(userptr, "glGetVertexArrayiv");
glad_glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) load(userptr, "glInvalidateNamedFramebufferData");
glad_glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) load(userptr, "glInvalidateNamedFramebufferSubData");
glad_glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC) load(userptr, "glMapNamedBuffer");
glad_glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC) load(userptr, "glMapNamedBufferRange");
glad_glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC) load(userptr, "glNamedBufferData");
glad_glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC) load(userptr, "glNamedBufferStorage");
glad_glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC) load(userptr, "glNamedBufferSubData");
glad_glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) load(userptr, "glNamedFramebufferDrawBuffer");
glad_glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) load(userptr, "glNamedFramebufferDrawBuffers");
glad_glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) load(userptr, "glNamedFramebufferParameteri");
glad_glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) load(userptr, "glNamedFramebufferReadBuffer");
glad_glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glNamedFramebufferRenderbuffer");
glad_glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) load(userptr, "glNamedFramebufferTexture");
glad_glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glNamedFramebufferTextureLayer");
glad_glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC) load(userptr, "glNamedRenderbufferStorage");
glad_glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glNamedRenderbufferStorageMultisample");
glad_glTextureBuffer = (PFNGLTEXTUREBUFFERPROC) load(userptr, "glTextureBuffer");
glad_glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC) load(userptr, "glTextureBufferRange");
glad_glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC) load(userptr, "glTextureParameterIiv");
glad_glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC) load(userptr, "glTextureParameterIuiv");
glad_glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC) load(userptr, "glTextureParameterf");
glad_glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC) load(userptr, "glTextureParameterfv");
glad_glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC) load(userptr, "glTextureParameteri");
glad_glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC) load(userptr, "glTextureParameteriv");
glad_glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC) load(userptr, "glTextureStorage1D");
glad_glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC) load(userptr, "glTextureStorage2D");
glad_glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) load(userptr, "glTextureStorage2DMultisample");
glad_glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC) load(userptr, "glTextureStorage3D");
glad_glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) load(userptr, "glTextureStorage3DMultisample");
glad_glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC) load(userptr, "glTextureSubImage1D");
glad_glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC) load(userptr, "glTextureSubImage2D");
glad_glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC) load(userptr, "glTextureSubImage3D");
glad_glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) load(userptr, "glTransformFeedbackBufferBase");
glad_glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) load(userptr, "glTransformFeedbackBufferRange");
glad_glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC) load(userptr, "glUnmapNamedBuffer");
glad_glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC) load(userptr, "glVertexArrayAttribBinding");
glad_glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC) load(userptr, "glVertexArrayAttribFormat");
glad_glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC) load(userptr, "glVertexArrayAttribIFormat");
glad_glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC) load(userptr, "glVertexArrayAttribLFormat");
glad_glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC) load(userptr, "glVertexArrayBindingDivisor");
glad_glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC) load(userptr, "glVertexArrayElementBuffer");
glad_glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC) load(userptr, "glVertexArrayVertexBuffer");
glad_glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC) load(userptr, "glVertexArrayVertexBuffers");
}
static void glad_gl_load_GL_ARB_fragment_program( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_ARB_fragment_program) return;
glad_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB");
@@ -10252,6 +10361,12 @@ static void glad_gl_load_GL_ARB_shader_storage_buffer_object( GLADuserptrloadfun
if(!GLAD_GL_ARB_shader_storage_buffer_object) return;
glad_glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC) load(userptr, "glShaderStorageBlockBinding");
}
static void glad_gl_load_GL_ARB_timer_query( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_ARB_timer_query) return;
glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v");
glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v");
glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter");
}
static void glad_gl_load_GL_ARB_vertex_buffer_object( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_ARB_vertex_buffer_object) return;
glad_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) load(userptr, "glBindBufferARB");
@@ -10776,6 +10891,20 @@ static void glad_gl_load_GL_EXT_transform_feedback( GLADuserptrloadfunc load, vo
glad_glGetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) load(userptr, "glGetTransformFeedbackVaryingEXT");
glad_glTransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) load(userptr, "glTransformFeedbackVaryingsEXT");
}
static void glad_gl_load_GL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_KHR_debug) return;
glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load(userptr, "glDebugMessageCallback");
glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load(userptr, "glDebugMessageControl");
glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load(userptr, "glDebugMessageInsert");
glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load(userptr, "glGetDebugMessageLog");
glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load(userptr, "glGetObjectLabel");
glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load(userptr, "glGetObjectPtrLabel");
glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv");
glad_glObjectLabel = (PFNGLOBJECTLABELPROC) load(userptr, "glObjectLabel");
glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load(userptr, "glObjectPtrLabel");
glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load(userptr, "glPopDebugGroup");
glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load(userptr, "glPushDebugGroup");
}
static void glad_gl_load_GL_NV_conservative_raster( GLADuserptrloadfunc load, void* userptr) {
if(!GLAD_GL_NV_conservative_raster) return;
glad_glSubpixelPrecisionBiasNV = (PFNGLSUBPIXELPRECISIONBIASNVPROC) load(userptr, "glSubpixelPrecisionBiasNV");
@@ -10877,6 +11006,7 @@ static int glad_gl_find_extensions_gl(void) {
GLAD_GL_ARB_compatibility = glad_gl_has_extension(exts, exts_i, "GL_ARB_compatibility");
GLAD_GL_ARB_debug_output = glad_gl_has_extension(exts, exts_i, "GL_ARB_debug_output");
GLAD_GL_ARB_direct_state_access = glad_gl_has_extension(exts, exts_i, "GL_ARB_direct_state_access");
GLAD_GL_ARB_fragment_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_program");
GLAD_GL_ARB_fragment_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_shader");
GLAD_GL_ARB_framebuffer_sRGB = glad_gl_has_extension(exts, exts_i, "GL_ARB_framebuffer_sRGB");
@@ -10889,6 +11019,7 @@ static int glad_gl_find_extensions_gl(void) {
GLAD_GL_ARB_texture_float = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_float");
GLAD_GL_ARB_texture_rg = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rg");
GLAD_GL_ARB_texture_rgb10_a2ui = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rgb10_a2ui");
GLAD_GL_ARB_timer_query = glad_gl_has_extension(exts, exts_i, "GL_ARB_timer_query");
GLAD_GL_ARB_vertex_buffer_object = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_buffer_object");
GLAD_GL_ARB_vertex_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_program");
GLAD_GL_ARB_vertex_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_shader");
@@ -10910,6 +11041,7 @@ static int glad_gl_find_extensions_gl(void) {
GLAD_GL_EXT_texture_sRGB = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_sRGB");
GLAD_GL_EXT_transform_feedback = glad_gl_has_extension(exts, exts_i, "GL_EXT_transform_feedback");
GLAD_GL_INTEL_conservative_rasterization = glad_gl_has_extension(exts, exts_i, "GL_INTEL_conservative_rasterization");
GLAD_GL_KHR_debug = glad_gl_has_extension(exts, exts_i, "GL_KHR_debug");
GLAD_GL_KHR_texture_compression_astc_ldr = glad_gl_has_extension(exts, exts_i, "GL_KHR_texture_compression_astc_ldr");
GLAD_GL_NV_conservative_raster = glad_gl_has_extension(exts, exts_i, "GL_NV_conservative_raster");
@@ -10994,10 +11126,12 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
if (!glad_gl_find_extensions_gl()) return 0;
glad_gl_load_GL_ARB_debug_output(load, userptr);
glad_gl_load_GL_ARB_direct_state_access(load, userptr);
glad_gl_load_GL_ARB_fragment_program(load, userptr);
glad_gl_load_GL_ARB_shader_image_load_store(load, userptr);
glad_gl_load_GL_ARB_shader_objects(load, userptr);
glad_gl_load_GL_ARB_shader_storage_buffer_object(load, userptr);
glad_gl_load_GL_ARB_timer_query(load, userptr);
glad_gl_load_GL_ARB_vertex_buffer_object(load, userptr);
glad_gl_load_GL_ARB_vertex_program(load, userptr);
glad_gl_load_GL_ARB_vertex_shader(load, userptr);
@@ -11012,6 +11146,7 @@ int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
glad_gl_load_GL_EXT_texture_array(load, userptr);
glad_gl_load_GL_EXT_texture_integer(load, userptr);
glad_gl_load_GL_EXT_transform_feedback(load, userptr);
glad_gl_load_GL_KHR_debug(load, userptr);
glad_gl_load_GL_NV_conservative_raster(load, userptr);

View File

@@ -6,6 +6,11 @@
#include<math.h>
#include<pthread.h>
#include<assert.h>
#include"k3.h"
#ifdef _WIN32
#define strncasecmp _strnicmp
#endif
static uint32_t FinalSampleRate;
static uint8_t FinalChannels;
@@ -19,12 +24,22 @@ struct k3MixSource {
char *filepath;
OggVorbis_File vf;
int bitstream;
size_t looppoint;
};
struct k3MixSource *k3MixSourceFile(const char *path) {
struct k3MixSource *ret = calloc(1, sizeof(*ret));
ret->filepath = strdup(path);
ov_fopen(path, &ret->vf);
ret->bitstream = 0;
ret->looppoint = 0;
for(size_t ci = 0; ci < ret->vf.vc->comments; ci++) {
if(strncasecmp(ret->vf.vc->user_comments[ci], "looppoint=", 10) == 0) {
ret->looppoint = strtol(ret->vf.vc->user_comments[ci] + 10, NULL, 0);
k3Log(k3_DEBUG, "%s has loop point %lu", path, ret->looppoint);
}
}
return ret;
}
void k3MixSourceClose(struct k3MixSource *src) {
@@ -42,7 +57,7 @@ __attribute__((optimize("Ofast"))) static intmax_t ogg_read(struct k3MixWave *th
long lastRead = ov_read_float(&od->vf, &ni, sampleCount, &od->bitstream);
if(this->loop && lastRead == 0) {
ov_pcm_seek(&od->vf, 0);
ov_pcm_seek(&od->vf, od->looppoint);
continue;
} else if(lastRead <= 0) {
this->end = true;
@@ -161,12 +176,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 +198,7 @@ struct k3MixWave *k3MixQueue() {
ret->loop = 0;
ret->dam = 0;
ret->volume = 1;
ret->end = false;
return ret;
}
@@ -260,6 +277,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 +326,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 +368,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++;

View File

@@ -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*);

View File

@@ -45,3 +45,5 @@ void k4_set_texture_reduction(int);
void k4_set_clipboard_text(const char *str);
const char *k4_get_clipboard_text();
void k4_set_ui_mode(bool yes);

View File

@@ -25,6 +25,9 @@ static int mdlloader(void *ud, struct ResManRes *res) {
} header;
fread(&header, 4, 4, f);
// ' ' or '1'
char version = ((char*) &header.magic)[3];
int colorsEnabled = header.flags & 1;
mat4 *invBind = _mm_malloc(sizeof(*invBind) * header.boneCount, 16);
@@ -33,6 +36,17 @@ static int mdlloader(void *ud, struct ResManRes *res) {
uint8_t *boneParents = malloc(header.boneCount);
fread(boneParents, 1, header.boneCount, f);
char boneNames[1500] = {};
size_t boneNamesLen = 0;
for(size_t b = 0; b < header.boneCount; b++) {
while(1) {
fread(boneNames + boneNamesLen, 1, 1, f);
if(boneNames[boneNamesLen++] == 0) {
break;
}
}
}
vec3 *pos = malloc(sizeof(*pos) * header.vertCount);
fread(pos, sizeof(vec3), header.vertCount, f);
@@ -59,6 +73,8 @@ static int mdlloader(void *ud, struct ResManRes *res) {
struct k3Mdl *mdl = k3MdlCreate(header.vertCount, header.indCount, header.boneCount, pos, nrm, uvs, cols, boneIDs, boneWeights, inds, invBind, boneParents);
k3MdlSetBoneNames(mdl, boneNames);
k3MdlSetDebugName(mdl, res->name);
free(pos);
@@ -70,8 +86,11 @@ static int mdlloader(void *ud, struct ResManRes *res) {
fread(&meshes, sizeof(uint16_t), 1, f);
for(uint32_t i = 0; i < meshes; i++) {
uint16_t startnum[2];
fread(startnum, sizeof(uint16_t), 2, f);
uint32_t start = 0;
uint32_t number = 0;
fread(&start, version == ' ' ? sizeof(uint16_t) : sizeof(uint32_t), 1, f);
fread(&number, version == ' ' ? sizeof(uint16_t) : sizeof(uint32_t), 1, f);
char buf[256] = {};
for(int c = 0; c < sizeof(buf) - 1; c++) {
@@ -81,28 +100,25 @@ static int mdlloader(void *ud, struct ResManRes *res) {
}
}
k3MdlAddMesh(mdl, resman_ref(RESMAN_MATERIAL, buf), startnum[0], startnum[1]);
k3MdlAddMesh(mdl, resman_ref(RESMAN_MATERIAL, buf), start, number);
}
for(size_t i = 0; i < header.animCount; i++) {
struct {
uint16_t id;
uint16_t frames;
uint16_t frameCount;
uint16_t fps;
uint16_t zero;
} info;
fread(&info, sizeof(info), 1, f);
struct k3Animation *anim = malloc(sizeof(*anim));
anim->frames = _mm_malloc(sizeof(*anim->frames) * info.frames * header.boneCount, 16);
anim->boneParents = boneParents;
anim->invBind = invBind;
struct k3AnimationFountain *anim = _mm_malloc(sizeof(*anim) + sizeof(*anim->frames) * info.frameCount * header.boneCount, 16);
anim->id = info.id;
anim->fps = info.fps;
anim->frameCount = info.frames;
anim->boneCount = header.boneCount;
anim->frameCount = info.frameCount;
anim->bones = header.boneCount;
fread(anim->frames, sizeof(*anim->frames), info.frames * header.boneCount, f);
fread(anim->frames, sizeof(*anim->frames), info.frameCount * header.boneCount, f);
k3MdlAddAnim(mdl, anim);
}
@@ -168,7 +184,7 @@ static int streamloader(void *ud, struct ResManRes *res) {
snprintf(namebuf, sizeof(namebuf), "assets/aud/%s", res->name);
res->thing = k3MixSourceFile(namebuf);
return 1;
return !!res->thing;
}
static int refresh_texture(struct ResManRes *res) {
@@ -317,19 +333,11 @@ static int texloader(void *ud, struct ResManRes *res) {
}
static int fontloader(void *ud, struct ResManRes *res) {
FILE *fntf = fopen(res->name, "rb");
fseek(fntf, 0, SEEK_END);
size_t fntfsz = ftell(fntf);
fseek(fntf, 0, SEEK_SET);
char *fntbuf = malloc(fntfsz);
fread(fntbuf, 1, fntfsz, fntf);
char namebuf[256];
snprintf(namebuf, sizeof(namebuf), "assets/%s", res->name);
struct k3Font *fnt = k3FontCreate();
struct k3Tex *fnttexldr(struct k3Font *fnt, const char *name) {
return resman_ref(RESMAN_TEXTURE, name);
}
k3FontLoad(fnt, fntbuf, fntfsz, fnttexldr);
k3FontLoad(fnt, namebuf);
res->thing = fnt;
return 1;

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,8 @@ extern int LuaapiFirstPerson;
extern double LuaapiStartTime;
extern float LuaapiFov;
extern float LuaapiNear;
extern float LuaapiFar;
extern struct k3Tex *LuaapiSkybox;
extern vec4 LuaapiSkyboxRotation;

View File

@@ -28,6 +28,7 @@
#include"k3font.h"
#include"k3menu.h"
#include"k3bloom.h"
#include"k3batch.h"
#include"resman.h"
@@ -37,10 +38,13 @@
#include"net_server.h"
#include"net_client.h"
#include"net_hi.h"
#include<ctype.h>
GLFWwindow *GameWnd;
uint16_t GameWndW;
uint16_t GameWndH;
static int TextureResolutionReduction = 0;
@@ -58,7 +62,7 @@ static double LastTime;
#include"loaders.inc"
void set_ui_mode(int yes) {
void k4_set_ui_mode(bool yes) {
glfwSetInputMode(GameWnd, GLFW_CURSOR, yes ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
}
@@ -70,9 +74,6 @@ static double xposold, yposold;
static void buttoncallback(GLFWwindow *GameWnd, int button, int action, int mods) {
if(button == GLFW_MOUSE_BUTTON_LEFT) {
if(UiActive) {
int ww, wh;
glfwGetWindowSize(GameWnd, &ww, &wh);
struct k3MEvent ev = {
.original = (void*) UiActive,
.target = (void*) UiActive,
@@ -80,8 +81,8 @@ static void buttoncallback(GLFWwindow *GameWnd, int button, int action, int mods
.code = action == GLFW_PRESS ? k3M_EVENT_MOUSE_PRESS : k3M_EVENT_MOUSE_RELEASE,
.mouse = {
.button = k3M_MOUSE_BUTTON_0,
.x = xposold * UiActive->w / ww,
.y = (wh - yposold - 1) * UiActive->h / wh,
.x = xposold * UiActive->w / GameWndW,
.y = yposold * UiActive->h / GameWndH,
},
};
@@ -110,11 +111,8 @@ static void motioncallback(GLFWwindow *GameWnd, double xpos, double ypos) {
first = 0;
if(UiActive) {
int ww, wh;
glfwGetWindowSize(GameWnd, &ww, &wh);
uint16_t uix = xposold * UiActive->w / ww;
uint16_t uiy = (wh - yposold - 1) * UiActive->h / wh;
uint16_t uix = xposold * UiActive->w / GameWndW;
uint16_t uiy = yposold * UiActive->h / GameWndH;
struct k3MEvent ev = {
.original = (void*) UiActive,
@@ -134,7 +132,7 @@ static void motioncallback(GLFWwindow *GameWnd, double xpos, double ypos) {
static void keycallback(GLFWwindow *GameWnd, int key, int scancode, int action, int mods) {
if(action == GLFW_RELEASE && key == GLFW_KEY_ESCAPE) {
luaapi_escape();
set_ui_mode(!!UiActive);
k4_set_ui_mode(!!UiActive);
} else {
if(UiActive) {
struct k3MEvent ev = {
@@ -172,8 +170,16 @@ static void charcallback(GLFWwindow *window, unsigned int codepoint) {
static void fix_resol();
static void resizecallback(GLFWwindow *window, int width, int height) {
k3Resize(width, height);
k3Resize(GameWndW = width, GameWndH = height);
fix_resol();
if(UiActive) {
UiActive->w = UiActive->wDesired = GameWndW;
UiActive->h = UiActive->hDesired = GameWndH;
k3MMeasure(UiActive);
k3MArrange(UiActive);
}
}
static int argc;
@@ -189,7 +195,10 @@ const char *k4_get_arg(const char *name) {
#include<signal.h>
void k4k3LogCallback(enum k3LogLevel lvl, const char *str, size_t len) {
if(lvl == k3_TRACE) return;
static const char *prefixes[] = {
[k3_TRACE] = "[\x1B[95mTRACE\x1B[0m]",
[k3_DEBUG] = "[\x1B[95mDEBUG\x1B[0m]",
[k3_INFO] = "[\x1B[97mINFO\x1B[0m] ",
[k3_WARN] = "[\x1B[93mWARN\x1B[0m] ",
@@ -198,7 +207,7 @@ void k4k3LogCallback(enum k3LogLevel lvl, const char *str, size_t len) {
//if(lvl == k3_ERR) raise(SIGINT);
fprintf(stderr, "%s : %s\n", prefixes[lvl], str);
fprintf(stdout, "%s : %s\n", prefixes[lvl], str);
}
struct k4Control {
@@ -218,13 +227,16 @@ static int eng_init() {
#define START_HEIGHT 540
#define START_TITLE "k4"
GameWndW = START_WIDTH;
GameWndH = START_HEIGHT;
// Prefer core
if(!k4_get_arg("core") || strcmp(k4_get_arg("core"), "0")) {
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL);
GameWnd = glfwCreateWindow(GameWndW, GameWndH, START_TITLE, NULL, NULL);
}
// Attempt compatibility
@@ -233,7 +245,7 @@ static int eng_init() {
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL);
GameWnd = glfwCreateWindow(GameWndW, GameWndH, START_TITLE, NULL, NULL);
}
k3MixInit(44100, 2);
@@ -267,8 +279,16 @@ static int eng_init() {
GLAD_GL_ARB_framebuffer_sRGB = 0;
GLAD_GL_EXT_framebuffer_object = 0;
}
if(k4_get_arg("dsa") && strtol(k4_get_arg("dsa"), NULL, 0) == 0) {
GLAD_GL_EXT_direct_state_access = 0;
GLAD_GL_ARB_direct_state_access = 0;
}
if(k4_get_arg("vsync")) {
glfwSwapInterval(strtol(k4_get_arg("vsync"), NULL, 0));
} else {
glfwSwapInterval(0);
}
printf("GL version: %s\n", glGetString(GL_VERSION));
printf("GL renderer: %s\n", glGetString(GL_RENDERER));
@@ -276,7 +296,9 @@ static int eng_init() {
k3SetLogCallback(k4k3LogCallback);
k3Init();
k3Init(
!k4_get_arg("tc") || strtol(k4_get_arg("tc"), NULL, 0) != 0,
!k4_get_arg("mipmap") || strtol(k4_get_arg("mipmap"), NULL, 0) != 0);
k3BatchInit();
@@ -300,7 +322,7 @@ static void fix_resol() {
}
static void eng_ui_init() {
set_ui_mode(!!UiActive);
k4_set_ui_mode(!!UiActive);
}
static void fps_counter_step(double newDT) {
@@ -416,8 +438,6 @@ int main(int argc_, char **argv_) {
eng_ui_init();
LuaapiStartTime = glfwGetTime();
LastTime = glfwGetTime();
double accumulator = 0;
@@ -435,6 +455,9 @@ int main(int argc_, char **argv_) {
net_hi_update(CurrentTime);
int windowW, windowH;
glfwGetWindowSize(GameWnd, &windowW, &windowH);
float alpha = fmodf(accumulator * GAME_TPS, 1.f);
vec3 cameraForwardDir = {0, 0, -1};
@@ -495,7 +518,7 @@ int main(int argc_, char **argv_) {
glfwGetFramebufferSize(GameWnd, &width, &height);
mat4 proj;
glm_perspective(glm_rad(LuaapiFov), (float) width / height, 0.1f, 80.f, proj);
glm_perspective(glm_rad(LuaapiFov), (float) width / height, LuaapiNear, LuaapiFar, proj);
/* Third-person camera movement */
struct LocalRay camray = {};
@@ -523,11 +546,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);
@@ -562,6 +590,7 @@ int main(int argc_, char **argv_) {
glm_mat4_copy(cam, LuaapiCamMatrix);
k3Update();
k3SetTime(glfwGetTime());
size_t lightCount;
@@ -587,12 +616,16 @@ int main(int argc_, char **argv_) {
if(c->cache) {
struct CBoned *b = game_getcomponent(c->entity, boned);
k3Batch(c->cache, transform, b ? b->bones : NULL);
if(b && b->animator.anim) {
k3AnimatorStep(&b->animator, dt);
}
k3Batch(c->cache, transform, b ? b->animator.bones : NULL);
}
}
if(!IrregularShadows) {
k3PassShadowmap(proj, cam, shadowmapOffscreen);
k3PassShadowmap(proj, cam, shadowmapOffscreen, 8);
}
if(lowresOffscreen) {
@@ -637,13 +670,7 @@ int main(int argc_, char **argv_) {
glClear(GL_DEPTH_BUFFER_BIT);
if(!k3IsCore) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 3600, 0, 2025, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
k3BatchSetResolution(windowW, windowH);
luaapi_render2d();

View File

@@ -26,11 +26,7 @@ void net_client_init() {
Game.isAuthority = 0;
}
bool net_client_connect(const char *addr, uint16_t port) {
ENetAddress eaddr;
enet_address_set_host(&eaddr, addr);
eaddr.port = port;
bool net_client_connect(ENetAddress eaddr) {
peer = enet_host_connect(host, &eaddr, 1, 0);
ENetEvent ev;
@@ -118,7 +114,7 @@ static void interpret_pkt(ENetPacket *pkt) {
c->holding = b_ru16(&b);
} if(ctype == CMD_CTYPE_BONED) {
struct CBoned *c = game_ensurecomponent(ent, boned);
c->anim.standard = b_ru8(&b);
/*c->anim.standard =*/ b_ru8(&b);
}
} else if(cmd == CMD_SC_POSUPDATE) {
uint16_t lastOurTick = b_ru16(&b);

View File

@@ -1,7 +1,9 @@
#pragma once
#include"enet.h"
void net_client_init();
bool net_client_connect(const char *addr, uint16_t port);
bool net_client_connect(ENetAddress addr);
void net_client_receive();
void net_client_update();
void net_client_dejitter();

View File

@@ -7,9 +7,15 @@
#include"net_server.h"
#include"net_client.h"
#include<math.h>
#include"k3.h"
/*
* Handles networking on a higher-level, combining hole punching with
* basic client & server interface
* */
static void *ReqPeercodeUD;
static void(*ReqPeercodeCB)(void*, const char *peercode);
static void(*ReqPeercodeCB)(void*, struct StoonPeercode *peercode);
static struct Stoon stoon;
@@ -17,11 +23,11 @@ static bool inited = false;
static bool isHost;
typedef struct {
#define MASK_IPv4 1
#define MASK_IPv6 2
int mask;
ENetAddress v4;
ENetAddress v6;
ENetAddress pv4;
ENetAddress pv6;
ENetAddress lv4;
ENetAddress lv6;
} ToPunch;
static ToPunch *topunch = NULL;
static size_t topunchCount = 0;
@@ -30,13 +36,22 @@ static double Timeout = 0;
static bool connected = false;
bool net_hi_request_peercode(void *ud, void(*callback)(void*, const char *peercode)) {
static uint16_t servport = 0;
bool net_hi_request_peercode(void *ud, void(*callback)(void*, struct StoonPeercode *peercode)) {
if(inited) return false;
ReqPeercodeUD = ud;
ReqPeercodeCB = callback;
stoon = stoon_init("stun.easybell.de", 3478, 26656);
for(size_t port = 25000; port <= 26656; port++) {
stoon = stoon_init("stun.easybell.de", 3478, port);
if(stoon.fd4 >= 0 || stoon.fd6 >= 0) {
servport = port;
break;
}
}
Timeout = 0;
@@ -52,7 +67,7 @@ bool net_hi_setup(bool host) {
isHost = host;
if(host) {
net_server_init();
net_server_init(servport);
} else {
net_client_init();
}
@@ -67,16 +82,17 @@ void net_hi_update(double now) {
if(stoon_req(&stoon)) {
if(stoon_listen(&stoon)) {
uint8_t peercode[STOON_CONN_INFO_SIZE] = {};
stoon_serialize(&stoon, peercode);
ReqPeercodeCB(ReqPeercodeUD, peercode);
ReqPeercodeCB(ReqPeercodeUD, &stoon.peercode);
ReqPeercodeCB = NULL;
} else {
k3Log(k3_INFO, "stoon_listen failure");
Timeout = now + 1;
}
} else {
k3Log(k3_INFO, "stoon_req failure");
Timeout = now + 1;
}
@@ -97,11 +113,11 @@ void net_hi_update(double now) {
for(size_t tpi = 0; tpi < topunchCount; tpi++) {
ToPunch *tp = &topunch[tpi];
if(tp->mask & MASK_IPv4) {
enet_socket_send(h->socket, &tp->v4, &buf, 1);
} else if(tp->mask & MASK_IPv6) {
enet_socket_send(h->socket, &tp->v6, &buf, 1);
}
if(tp->lv6.port) enet_socket_send(h->socket, &tp->lv6, &buf, 1);
if(tp->lv4.port) enet_socket_send(h->socket, &tp->lv4, &buf, 1);
if(tp->pv6.port) enet_socket_send(h->socket, &tp->pv6, &buf, 1);
if(tp->pv4.port) enet_socket_send(h->socket, &tp->pv4, &buf, 1);
}
}
@@ -111,57 +127,85 @@ void net_hi_update(double now) {
}
}
static void stoonpeer_to_enets(const char *peercode, ENetAddress *v4, ENetAddress *v6, int *mask) {
uint8_t *addr8 = (uint8_t*) &v4->host;
static bool stoonpeer_to_enet4(uint8_t *publicV4, uint8_t *publicP4, ENetAddress *enet) {
memset(enet, 0, sizeof(*enet));
if(*(uint32_t*) publicV4 == 0 || *(uint16_t*) publicP4 == 0) {
return false;
}
uint8_t *addr8 = (uint8_t*) &enet->host;
memset(addr8, 0, 16);
addr8[10] = 0xFF;
addr8[11] = 0xFF;
addr8[12] = peercode[0];
addr8[13] = peercode[1];
addr8[14] = peercode[2];
addr8[15] = peercode[3];
v4->port = ntohs(*(uint16_t*) &peercode[4]);
addr8[12] = publicV4[0];
addr8[13] = publicV4[1];
addr8[14] = publicV4[2];
addr8[15] = publicV4[3];
enet->port = *(uint16_t*) publicP4;
memcpy(&v6->host, peercode + 6, 16);
v6->port = ntohs(*(uint16_t*) &peercode[22]);
*mask = 0;
if(v4->port) {
*mask |= MASK_IPv4;
}
if(v6->port) {
*mask |= MASK_IPv6;
}
return true;
}
void net_hi_add_punch(const char *peercode) {
int mask;
ENetAddress v4 = {}, v6 = {};
stoonpeer_to_enets(peercode, &v4, &v6, &mask);
static bool stoonpeer_to_enet6(uint8_t *publicV6, uint8_t *publicP6, ENetAddress *enet) {
memset(enet, 0, sizeof(*enet));
if(*(uint32_t*) publicV6 == 0 || *(uint16_t*) publicP6 == 0) {
return false;
}
uint8_t *addr8 = (uint8_t*) &enet->host;
memcpy(addr8, publicV6, 16);
enet->port = *(uint16_t*) publicP6;
return true;
}
void net_hi_add_punch(struct StoonPeercode *peercode) {
topunch = realloc(topunch, sizeof(*topunch) * (++topunchCount));
topunch[topunchCount - 1] = (ToPunch) {
.v4 = v4,
.v6 = v6,
.mask = mask,
};
ToPunch *tp = &topunch[topunchCount - 1];
stoonpeer_to_enet4(peercode->publicV4, peercode->publicP4, &tp->pv4);
stoonpeer_to_enet6(peercode->publicV6, peercode->publicP6, &tp->pv6);
stoonpeer_to_enet4(peercode->localV4, peercode->localP4, &tp->lv4);
stoonpeer_to_enet6(peercode->localV6, peercode->localP6, &tp->lv6);
}
bool net_hi_connect(const char *peercode) {
bool net_hi_connect(struct StoonPeercode *peercode) {
if(!inited) return false;
if(connected) return false;
char ip[64];
int port;
if(*(uint16_t*) (peercode + 22) == 0) {
inet_ntop(AF_INET, peercode, ip, sizeof(ip));
port = ntohs(*(uint16_t*) (peercode + 4));
} else {
inet_ntop(AF_INET6, peercode + 6, ip, sizeof(ip));
port = ntohs(*(uint16_t*) (peercode + 22));
ENetAddress pv4, pv6;
stoonpeer_to_enet4(peercode->publicV4, peercode->publicP4, &pv4);
stoonpeer_to_enet6(peercode->publicV6, peercode->publicP6, &pv6);
ENetAddress lv4, lv6;
stoonpeer_to_enet4(peercode->localV4, peercode->localP4, &lv4);
stoonpeer_to_enet6(peercode->localV6, peercode->localP6, &lv6);
if(lv6.port && net_client_connect(lv6)) {
k3Log(k3_INFO, "Found local IPv6");
return true;
}
if(lv4.port && net_client_connect(lv4)) {
k3Log(k3_INFO, "Found local IPv4");
return true;
}
return net_client_connect(ip, port);
if(pv6.port && net_client_connect(pv6)) {
k3Log(k3_INFO, "Found remote IPv6");
return true;
}
if(pv4.port && net_client_connect(pv4)) {
k3Log(k3_INFO, "Found remote IPv4");
return true;
}
k3Log(k3_INFO, "Failed to establish connection");
return false;
}

View File

@@ -2,10 +2,12 @@
#include<stdbool.h>
bool net_hi_request_peercode(void *ud, void(*callback)(void*, const char *peercode));
struct StoonPeercode;
bool net_hi_request_peercode(void *ud, void(*callback)(void*, struct StoonPeercode *peercode));
bool net_hi_setup(bool host);
void net_hi_update(double now);
void net_hi_add_punch(const char *peercode);
void net_hi_add_punch(struct StoonPeercode *peercode);
bool net_hi_connect(const char *peercode);
bool net_hi_connect(struct StoonPeercode *peercode);

View File

@@ -18,8 +18,8 @@ struct Conn {
#define MAX_PLAYERS 64
static struct Conn conns[MAX_PLAYERS];
void net_server_init() {
host = enet_host_create(&(ENetAddress) {.host = ENET_HOST_ANY, .port = 26656}, 16, 1, 0, 0);
void net_server_init(uint16_t port) {
host = enet_host_create(&(ENetAddress) {.host = ENET_HOST_ANY, .port = port}, 16, 1, 0, 0);
Game.isMultiplayer = 1;
Game.isAuthority = 1;
@@ -121,7 +121,7 @@ static void send_full_state(ENetPeer **peers, size_t peerCount) {
b_wu16(&b, c->entity);
b_wu8(&b, c->anim.standard);
b_wu8(&b, 0/*c->anim.standard*/);
}
if(peers) {

View File

@@ -5,7 +5,7 @@
struct _ENetPeer;
struct bstr;
void net_server_init();
void net_server_init(uint16_t port);
void net_server_receive();
void net_server_update();

View File

@@ -4,11 +4,12 @@
#include<winsock2.h>
#include<ws2tcpip.h>
#include<ntsecapi.h>
#include<iphlpapi.h>
#else
#include<netdb.h>
#include<sys/socket.h>
#include<sys/random.h>
#include<arpa/inet.h>
#include<ifaddrs.h>
#endif
#include<unistd.h>
#include<sys/types.h>
@@ -34,6 +35,13 @@
#define RAND(b, i) RtlGenRandom(b, i)
#else
#define RAND(b, i) getrandom(b, i, 0)
static void getrandom(void *buf, size_t amount, int flags) {
static FILE *f;
if(!f) {
f = fopen("/dev/urandom", "rb");
}
fread(buf, 1, amount, f);
}
#endif
struct StunMsg {
@@ -43,7 +51,7 @@ struct StunMsg {
uint8_t id[12];
};
static int stoon_init_mini(struct addrinfo *serv, uint16_t myport) {
static int stoon_init_mini(struct Stoon *this, struct addrinfo *serv, uint16_t myport) {
#ifdef _WIN32
errno = 0;
int fd = socket(serv->ai_family, serv->ai_socktype, serv->ai_protocol);
@@ -59,16 +67,79 @@ static int stoon_init_mini(struct addrinfo *serv, uint16_t myport) {
char p[6];
sprintf(p, "%u", myport);
struct addrinfo *myaddr;
if(getaddrinfo(NULL, p, &(struct addrinfo) {.ai_family = serv->ai_family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_flags = AI_PASSIVE}, &myaddr)) {
struct addrinfo *myaddrinfo;
if(getaddrinfo(NULL, p, &(struct addrinfo) {.ai_family = serv->ai_family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_flags = AI_PASSIVE}, &myaddrinfo)) {
close(fd);
return -1;
}
if(bind(fd, myaddr->ai_addr, myaddr->ai_addrlen)) {
if(bind(fd, myaddrinfo->ai_addr, myaddrinfo->ai_addrlen)) {
close(fd);
return -2;
}
freeaddrinfo(myaddr);
freeaddrinfo(myaddrinfo);
#ifdef _WIN32
size_t sz = 1024 * 64;
IP_ADAPTER_ADDRESSES *addrs = malloc(sz);
if(GetAdaptersAddresses(serv->ai_family, GAA_FLAG_SKIP_MULTICAST, NULL, addrs, &sz) == NO_ERROR) {
for(IP_ADAPTER_ADDRESSES *ifa = addrs; ifa; ifa = ifa->Next) {
if(!ifa->FirstUnicastAddress) {
continue;
}
if(serv->ai_family == AF_INET6) {
uint8_t *addr = (void*) &((struct sockaddr_in6*) ifa->FirstUnicastAddress->Address.lpSockaddr)->sin6_addr;
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 && addr[4] == 0 && addr[5] == 0 && addr[6] == 0 && addr[7] == 0 && addr[8] == 0 && addr[9] == 0 && addr[10] == 0 && addr[11] == 0 && addr[12] == 0 && addr[13] == 0 && addr[14] == 0 && (addr[15] == 0 || addr[15] == 1)) {
continue;
}
memcpy(this->peercode.localV6, addr, 16);
memcpy(this->peercode.localP6, &myport, 2);
} else {
uint8_t *addr = (void*) &((struct sockaddr_in*) ifa->FirstUnicastAddress->Address.lpSockaddr)->sin_addr;
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 || addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) {
continue;
}
memcpy(this->peercode.localV4, addr, 4);
memcpy(this->peercode.localP4, &myport, 2);
}
}
}
free(addrs);
#else
struct ifaddrs *ifaddr;
if(getifaddrs(&ifaddr) >= 0) {
for(struct ifaddrs *ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if(!ifa->ifa_addr || ifa->ifa_addr->sa_family != serv->ai_family) {
continue;
}
if(serv->ai_family == AF_INET6) {
uint8_t *addr = (void*) &((struct sockaddr_in6*) ifa->ifa_addr)->sin6_addr;
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 && addr[4] == 0 && addr[5] == 0 && addr[6] == 0 && addr[7] == 0 && addr[8] == 0 && addr[9] == 0 && addr[10] == 0 && addr[11] == 0 && addr[12] == 0 && addr[13] == 0 && addr[14] == 0 && (addr[15] == 0 || addr[15] == 1)) {
continue;
}
memcpy(this->peercode.localV6, addr, 16);
memcpy(this->peercode.localP6, &myport, 2);
} else {
uint8_t *addr = (void*) &((struct sockaddr_in*) ifa->ifa_addr)->sin_addr;
if(addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 || addr[0] == 127 && addr[1] == 0 && addr[2] == 0 && addr[3] == 1) {
continue;
}
memcpy(this->peercode.localV4, addr, 4);
memcpy(this->peercode.localP4, &myport, 2);
}
break;
}
freeifaddrs(ifaddr);
}
#endif
return fd;
}
@@ -92,18 +163,16 @@ struct Stoon stoon_init(const char *stunhost, uint16_t stunport, uint16_t myport
}
}
struct Stoon ret;
struct Stoon ret = {};
memset(&ret.my4, 0, sizeof(ret.my4));
if(v4) {
memcpy(&ret.stu4, v4->ai_addr, v4->ai_addrlen);
ret.fd4 = stoon_init_mini(v4, myport);
ret.fd4 = stoon_init_mini(&ret, v4, myport);
} else ret.fd4 = -1;
memset(&ret.my6, 0, sizeof(ret.my6));
if(v6) {
memcpy(&ret.stu6, v6->ai_addr, v6->ai_addrlen);
ret.fd6 = stoon_init_mini(v6, myport);
ret.fd6 = stoon_init_mini(&ret, v6, myport);
} else ret.fd6 = -1;
ret.poonchstage = 0;
@@ -121,12 +190,21 @@ static int stoon_req_mini(struct Stoon *this, int *fd, struct sockaddr *serv, in
if(errno == ENETUNREACH) {
close(*fd);
*fd = -1;
return false;
}
}
return true;
}
int stoon_req(struct Stoon *this) {
if(this->fd4 >= 0) stoon_req_mini(this, &this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in));
if(this->fd6 >= 0) stoon_req_mini(this, &this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6));
if(this->fd4 < 0 && this->fd6 < 0) {
return false;
}
return true;
}
static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv, int servlen) {
@@ -161,11 +239,10 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
uint16_t netfam = ntohs(((uint16_t*) d)[2]);
uint16_t publicPort = ntohs(((uint16_t*) d)[3]) ^ (STUN_MAGIC >> 16);
if(netfam == STUN_NETFAM_IPV4) {
uint32_t publicIp = ntohl(((uint32_t*) d)[2]) ^ STUN_MAGIC;
uint32_t publicIp = htonl(ntohl(((uint32_t*) d)[2]) ^ STUN_MAGIC);
this->my4.sin_family = AF_INET;
memcpy(&this->my4.sin_addr, &publicIp, 4);
this->my4.sin_port = htons(publicPort);
memcpy(this->peercode.publicV4, &publicIp, 4);
memcpy(this->peercode.publicP4, &publicPort, 2);
return 1;
} else if(netfam == STUN_NETFAM_IPV6) {
@@ -175,9 +252,8 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
publicIp[2] = ((uint32_t*) d)[4] ^ ((uint32_t*) res.base.id)[1];
publicIp[3] = ((uint32_t*) d)[5] ^ ((uint32_t*) res.base.id)[2];
this->my6.sin6_family = AF_INET6;
memcpy(&this->my6.sin6_addr, &publicIp, 16);
this->my6.sin6_port = htons(publicPort);
memcpy(this->peercode.publicV6, &publicIp, 16);
memcpy(this->peercode.publicP6, &publicPort, 2);
return 1;
} else {
@@ -188,12 +264,12 @@ static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv,
d += 4 + attribLen;
}
return 0;
return false;
}
int stoon_listen(struct Stoon *this) {
if(this->fd4 >= 0) if(stoon_listen_mini(this, this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in)) < 0) return 0;
if(this->fd6 >= 0) if(stoon_listen_mini(this, this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6)) < 0) return 0;
return 1;
return true;
}
void stoon_keepalive(struct Stoon *this) {
@@ -217,31 +293,7 @@ void stoon_kill(struct Stoon *this) {
this->fd6 = -1;
}
int stoon_v4_available(struct Stoon *this) {
return this->fd4 >= 0;
}
int stoon_v6_available(struct Stoon *this) {
return this->fd6 >= 0;
}
void stoon_serialize(struct Stoon *this, uint8_t ret[static STOON_CONN_INFO_SIZE]) {
if(this->fd4 >= 0) {
memcpy(ret + 0, &this->my4.sin_addr, 4);
memcpy(ret + 4, &this->my4.sin_port, 2);
} else {
memset(ret, 0, 6);
}
if(this->fd6 >= 0) {
memcpy(ret + 6, &this->my6.sin6_addr, 16);
memcpy(ret + 22, &this->my6.sin6_port, 2);
} else {
memset(ret + 6, 0, 18);
}
}
int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]) {
/*int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]) {
struct {
uint32_t addr4;
uint16_t port4;
@@ -303,7 +355,7 @@ int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_IN
}
return STOON_POONCH_NO_KNOCK;
}
}*/
#ifdef STOON_STANDALONE
int main() {

View File

@@ -6,6 +6,7 @@
#include<stddef.h>
#include<stdint.h>
#include<stdbool.h>
#ifdef _WIN32
#include<winsock2.h>
@@ -16,8 +17,6 @@
/* Standalone hole punching libary (IPv4 & IPv6 compatible) */
#define STOON_CONN_INFO_SIZE (4 + 2 + 16 + 2)
#define POONCH_MAGIC 0x504F4348
#define POONCH_STAGE_KNOCKING 0
#define POONCH_STAGE_ACK 1
@@ -26,16 +25,30 @@ struct Poonch {
uint32_t stage;
};
struct StoonPeercode {
uint8_t publicV4[4];
uint8_t publicP4[2];
uint8_t publicV6[16];
uint8_t publicP6[2];
uint8_t localV4[4];
uint8_t localP4[2];
uint8_t localV6[16];
uint8_t localP6[2];
};
struct Stoon {
struct sockaddr_in stu4;
struct sockaddr_in my4;
int fd4;
struct sockaddr_in6 stu6;
struct sockaddr_in6 my6;
int fd6;
uint8_t poonchstage;
struct StoonPeercode peercode;
};
// stunhost: Self-explanatory
@@ -53,12 +66,8 @@ void stoon_keepalive(struct Stoon*);
void stoon_kill(struct Stoon*);
int stoon_v4_available(struct Stoon*);
int stoon_v6_available(struct Stoon*);
void stoon_serialize(struct Stoon*, uint8_t ret[static STOON_CONN_INFO_SIZE]);
#define STOON_POONCH_INCOMPATIBLE_NETFAMS (-1)
/*#define STOON_POONCH_INCOMPATIBLE_NETFAMS (-1)
#define STOON_POONCH_NO_KNOCK 0
#define STOON_POONCH_ACKED 1
int stoon_poonch(struct Stoon*, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]);
*/