├── .editorconfig
├── .gitattributes
├── resources
├── icon.rc
├── icon.ico
├── icon.png
├── kv6
│ ├── cp.kv6
│ ├── block.kv6
│ ├── intel.kv6
│ ├── spade.kv6
│ ├── .gitignore
│ ├── grenade.kv6
│ ├── playerarms.kv6
│ ├── playerdead.kv6
│ ├── playerhead.kv6
│ ├── playerleg.kv6
│ ├── playerlegc.kv6
│ ├── semicasing.kv6
│ ├── semitracer.kv6
│ ├── smgcasing.kv6
│ ├── smgtracer.kv6
│ ├── playertorso.kv6
│ ├── playertorsoc.kv6
│ ├── shotguncasing.kv6
│ └── shotguntracer.kv6
├── png
│ ├── block.png
│ ├── intel.png
│ ├── ui
│ │ ├── bg.png
│ │ ├── exit.png
│ │ ├── join.png
│ │ ├── knob.png
│ │ ├── ping.png
│ │ ├── wait.png
│ │ ├── alert.png
│ │ ├── arrow.png
│ │ ├── arrow2.png
│ │ ├── flags.png
│ │ ├── input.png
│ │ ├── reload.png
│ │ ├── box_check.png
│ │ ├── box_empty.png
│ │ ├── collapsed.png
│ │ ├── expanded.png
│ │ └── joystick.png
│ ├── white.png
│ ├── command.png
│ ├── grenade.png
│ ├── health.png
│ ├── medical.png
│ ├── player.png
│ ├── smgammo.png
│ ├── splash.png
│ ├── tracer.png
│ ├── .gitignore
│ ├── semiammo.png
│ └── shotgunammo.png
├── cache
│ └── .gitignore
├── fonts
│ ├── ft88.ttf
│ ├── Fixedsys.ttf
│ └── Terminal.ttf
├── logs
│ └── .gitignore
├── wav
│ └── .gitignore
├── screenshots
│ └── .gitignore
└── config.ini
├── docs
├── apoc.png
├── chat.png
├── babel.png
├── custom.png
├── custom_def.png
├── icon_small.png
└── playerlist.png
├── resources.override
└── png
│ ├── target.png
│ ├── splash_icon.png
│ └── splashloader.png
├── .gitignore
├── src
├── gmi.h
├── list.h
├── stb_truetype.c
├── http.c
├── rpc.h
├── grenade.h
├── ping.h
├── gmi.c
├── utils.h
├── font.h
├── entitysystem.h
├── tracer.h
├── main.h
├── particle.h
├── file.h
├── channel.h
├── cameracontroller.h
├── aabb.h
├── log.h
├── weapon.h
├── minheap.h
├── glx.h
├── chunk.h
├── matrix.h
├── map.h
├── hud.h
├── entitysystem.c
├── camera.h
├── model.h
├── tesselator.h
├── config.h
├── list.c
├── hashtable.h
├── utils.c
├── sound.h
├── window.h
├── texture.h
├── matrix.c
├── aabb.c
├── rpc.c
├── common.h
├── minheap.c
├── log.c
├── tracer.c
├── grenade.c
├── player.h
├── ping.c
├── channel.c
├── ini.h
├── file.c
├── particle.c
├── font.c
├── model_normals.h
├── CMakeLists.txt
└── ini.c
├── cmake
└── Modules
│ ├── Findglfw3.cmake
│ ├── Finddeflate.cmake
│ └── Findenet.cmake
├── .clang-format
├── CMakeLists.txt
└── README.md
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | indent_style = tab
3 | indent_size = 4
4 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.c text eol=crlf
2 | *.h text eol=crlf
3 | * text=auto
--------------------------------------------------------------------------------
/resources/icon.rc:
--------------------------------------------------------------------------------
1 | IDI_WINLOGO ICON icon.ico
2 | GLFW_ICON ICON icon.ico
--------------------------------------------------------------------------------
/docs/apoc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/docs/apoc.png
--------------------------------------------------------------------------------
/docs/chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/docs/chat.png
--------------------------------------------------------------------------------
/docs/babel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/docs/babel.png
--------------------------------------------------------------------------------
/docs/custom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/docs/custom.png
--------------------------------------------------------------------------------
/resources/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/icon.ico
--------------------------------------------------------------------------------
/resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/icon.png
--------------------------------------------------------------------------------
/docs/custom_def.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/docs/custom_def.png
--------------------------------------------------------------------------------
/docs/icon_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/docs/icon_small.png
--------------------------------------------------------------------------------
/docs/playerlist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/docs/playerlist.png
--------------------------------------------------------------------------------
/resources/kv6/cp.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/cp.kv6
--------------------------------------------------------------------------------
/resources/kv6/block.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/block.kv6
--------------------------------------------------------------------------------
/resources/kv6/intel.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/intel.kv6
--------------------------------------------------------------------------------
/resources/kv6/spade.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/spade.kv6
--------------------------------------------------------------------------------
/resources/png/block.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/block.png
--------------------------------------------------------------------------------
/resources/png/intel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/intel.png
--------------------------------------------------------------------------------
/resources/png/ui/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/bg.png
--------------------------------------------------------------------------------
/resources/png/white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/white.png
--------------------------------------------------------------------------------
/resources/cache/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/resources/fonts/ft88.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/fonts/ft88.ttf
--------------------------------------------------------------------------------
/resources/kv6/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/resources/kv6/grenade.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/grenade.kv6
--------------------------------------------------------------------------------
/resources/logs/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/resources/png/command.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/command.png
--------------------------------------------------------------------------------
/resources/png/grenade.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/grenade.png
--------------------------------------------------------------------------------
/resources/png/health.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/health.png
--------------------------------------------------------------------------------
/resources/png/medical.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/medical.png
--------------------------------------------------------------------------------
/resources/png/player.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/player.png
--------------------------------------------------------------------------------
/resources/png/smgammo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/smgammo.png
--------------------------------------------------------------------------------
/resources/png/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/splash.png
--------------------------------------------------------------------------------
/resources/png/tracer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/tracer.png
--------------------------------------------------------------------------------
/resources/png/ui/exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/exit.png
--------------------------------------------------------------------------------
/resources/png/ui/join.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/join.png
--------------------------------------------------------------------------------
/resources/png/ui/knob.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/knob.png
--------------------------------------------------------------------------------
/resources/png/ui/ping.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/ping.png
--------------------------------------------------------------------------------
/resources/png/ui/wait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/wait.png
--------------------------------------------------------------------------------
/resources/wav/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/resources/fonts/Fixedsys.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/fonts/Fixedsys.ttf
--------------------------------------------------------------------------------
/resources/fonts/Terminal.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/fonts/Terminal.ttf
--------------------------------------------------------------------------------
/resources/kv6/playerarms.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/playerarms.kv6
--------------------------------------------------------------------------------
/resources/kv6/playerdead.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/playerdead.kv6
--------------------------------------------------------------------------------
/resources/kv6/playerhead.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/playerhead.kv6
--------------------------------------------------------------------------------
/resources/kv6/playerleg.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/playerleg.kv6
--------------------------------------------------------------------------------
/resources/kv6/playerlegc.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/playerlegc.kv6
--------------------------------------------------------------------------------
/resources/kv6/semicasing.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/semicasing.kv6
--------------------------------------------------------------------------------
/resources/kv6/semitracer.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/semitracer.kv6
--------------------------------------------------------------------------------
/resources/kv6/smgcasing.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/smgcasing.kv6
--------------------------------------------------------------------------------
/resources/kv6/smgtracer.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/smgtracer.kv6
--------------------------------------------------------------------------------
/resources/png/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | /*.png
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/resources/png/semiammo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/semiammo.png
--------------------------------------------------------------------------------
/resources/png/ui/alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/alert.png
--------------------------------------------------------------------------------
/resources/png/ui/arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/arrow.png
--------------------------------------------------------------------------------
/resources/png/ui/arrow2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/arrow2.png
--------------------------------------------------------------------------------
/resources/png/ui/flags.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/flags.png
--------------------------------------------------------------------------------
/resources/png/ui/input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/input.png
--------------------------------------------------------------------------------
/resources/png/ui/reload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/reload.png
--------------------------------------------------------------------------------
/resources/kv6/playertorso.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/playertorso.kv6
--------------------------------------------------------------------------------
/resources/kv6/playertorsoc.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/playertorsoc.kv6
--------------------------------------------------------------------------------
/resources/png/shotgunammo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/shotgunammo.png
--------------------------------------------------------------------------------
/resources/png/ui/box_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/box_check.png
--------------------------------------------------------------------------------
/resources/png/ui/box_empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/box_empty.png
--------------------------------------------------------------------------------
/resources/png/ui/collapsed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/collapsed.png
--------------------------------------------------------------------------------
/resources/png/ui/expanded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/expanded.png
--------------------------------------------------------------------------------
/resources/png/ui/joystick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/png/ui/joystick.png
--------------------------------------------------------------------------------
/resources/screenshots/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore everything in this directory
2 | *
3 | # Except this file
4 | !.gitignore
--------------------------------------------------------------------------------
/resources.override/png/target.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources.override/png/target.png
--------------------------------------------------------------------------------
/resources/kv6/shotguncasing.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/shotguncasing.kv6
--------------------------------------------------------------------------------
/resources/kv6/shotguntracer.kv6:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources/kv6/shotguntracer.kv6
--------------------------------------------------------------------------------
/resources.override/png/splash_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources.override/png/splash_icon.png
--------------------------------------------------------------------------------
/resources.override/png/splashloader.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/utf-4096/butterspades/HEAD/resources.override/png/splashloader.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Thumbs.db
2 | Desktop.ini
3 | /nongithub
4 | /dist
5 | /build
6 | *.lib
7 | *.a
8 | *.o
9 | *.vxl
10 | *.exe
11 | *.zip
12 | *.kv6
13 | *.lib
14 | *.dll
15 | /bsresources.zip
16 |
--------------------------------------------------------------------------------
/src/gmi.h:
--------------------------------------------------------------------------------
1 | #ifndef GMI_H
2 | #define GMI_H
3 |
4 | enum gmi_mode {
5 | GMI_MODE_UNDETECTED,
6 | GMI_MODE_UNKNOWN,
7 | GMI_MODE_ARENA,
8 | GMI_MODE_BABEL,
9 | GMI_MODE_TDM
10 | };
11 |
12 | extern enum gmi_mode gmi_mode;
13 | extern unsigned int gmi_tdm_kills[2];
14 | void gmi_mode_detect_message(char* message);
15 |
16 | #endif
--------------------------------------------------------------------------------
/src/list.h:
--------------------------------------------------------------------------------
1 | #ifndef LIST_H
2 | #define LIST_H
3 |
4 | struct list {
5 | void* data;
6 | size_t elements, element_size, mem_size;
7 | };
8 |
9 | enum list_traverse_direction {
10 | LIST_TRAVERSE_FORWARD,
11 | LIST_TRAVERSE_BACKWARD,
12 | };
13 |
14 | int list_created(struct list* l);
15 | void list_create(struct list* l, size_t element_size);
16 | void list_free(struct list* l);
17 | void list_sort(struct list* l, int (*cmp)(const void* obj, const void* ref));
18 | void* list_find(struct list* l, const void* ref, enum list_traverse_direction dir, int (*cmp)(const void* a, const void* b));
19 | void* list_get(struct list* l, size_t i);
20 | void* list_add(struct list* l, void* e);
21 | void list_remove(struct list* l, size_t i);
22 | void list_clear(struct list* l);
23 | int list_size(struct list* l);
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/src/stb_truetype.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #define STB_TRUETYPE_IMPLEMENTATION
21 | #define STBTT_RASTERIZER_VERSION 1
22 |
23 | #include "stb_truetype.h"
24 |
--------------------------------------------------------------------------------
/src/http.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #define HTTP_IMPLEMENTATION
21 |
22 | #ifdef _WIN32
23 | #define _WIN32_WINNT 0x0501
24 | #endif
25 |
26 | #include
27 |
28 | #include "http.h"
29 |
--------------------------------------------------------------------------------
/src/rpc.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef RPC_H
21 | #define RPC_H
22 |
23 | enum RPC_VALUE {
24 | RPC_VALUE_SERVERNAME,
25 | RPC_VALUE_PLAYERS,
26 | RPC_VALUE_SLOTS,
27 | RPC_VALUE_SERVERURL,
28 | };
29 |
30 | void rpc_init(void);
31 | void rpc_deinit(void);
32 | void rpc_setv(enum RPC_VALUE v, char* x);
33 | void rpc_seti(enum RPC_VALUE v, int x);
34 | void rpc_update(void);
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/src/grenade.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef GRENADE_H
21 | #define GRENADE_H
22 |
23 | struct Grenade {
24 | unsigned char team;
25 | float fuse_length;
26 | float created;
27 | struct Position pos;
28 | struct Velocity velocity;
29 | };
30 |
31 | void grenade_init(void);
32 | void grenade_add(struct Grenade* g);
33 | void grenade_update(float dt);
34 | void grenade_render(void);
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/src/ping.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef PING_H
21 | #define PING_H
22 |
23 | #include
24 |
25 | struct ping_entry {
26 | ENetAddress addr;
27 | char aos[64];
28 | float time_start;
29 | int trycount;
30 | };
31 |
32 | void ping_init();
33 | void ping_deinit();
34 | void ping_check(char* addr, int port, char* aos);
35 | void* ping_update(void* data);
36 | void ping_start(void (*result)(void*, float, char*));
37 | void ping_stop();
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/cmake/Modules/Findglfw3.cmake:
--------------------------------------------------------------------------------
1 | # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 | # file Copyright.txt or https://cmake.org/licensing for details.
3 |
4 | #.rst:
5 | # Findglfw3
6 | # -------
7 | #
8 | # Finds the glfw3 library
9 | #
10 | # This will define the following variables::
11 | #
12 | # glfw3_FOUND - True if the system has the glfw3 library
13 | #
14 | # and also the following imported target:
15 | #
16 | # glfw3::glfw3
17 | #
18 | find_package(PkgConfig)
19 | pkg_check_modules(PC_glfw3 QUIET glfw3)
20 |
21 | find_path(glfw3_INCLUDE_DIR
22 | NAMES GLFW/glfw3.h
23 | PATHS ${PC_glfw3_INCLUDE_DIRS} ../../deps
24 | PATH_SUFFIXES GLFW
25 | )
26 | find_library(glfw3_LIBRARY
27 | NAMES glfw glfw3
28 | PATHS ${PC_glfw3_LIBRARY_DIRS} ../../deps
29 | )
30 |
31 | include(FindPackageHandleStandardArgs)
32 | find_package_handle_standard_args(glfw3
33 | FOUND_VAR glfw3_FOUND
34 | REQUIRED_VARS
35 | glfw3_LIBRARY
36 | glfw3_INCLUDE_DIR
37 | )
38 |
39 | if (glfw3_FOUND)
40 | add_library(glfw3::glfw3 STATIC IMPORTED)
41 | set_target_properties(glfw3::glfw3 PROPERTIES
42 | IMPORTED_LOCATION ${glfw3_LIBRARY}
43 | INTERFACE_INCLUDE_DIRECTORIES ${glfw3_INCLUDE_DIR}
44 | )
45 | endif (glfw3_FOUND)
46 |
--------------------------------------------------------------------------------
/src/gmi.c:
--------------------------------------------------------------------------------
1 | // #include "network.h"
2 | #include
3 | #include
4 | #include
5 | #include "gmi.h"
6 | #include "log.h"
7 |
8 | enum gmi_mode gmi_mode = GMI_MODE_UNDETECTED;
9 | unsigned int gmi_tdm_kills[] = {0, 0};
10 |
11 | void gmi_mode_detect_message(char* message) {
12 | char* lower = malloc(sizeof(char) * strlen(message) + 1);
13 | for(unsigned int i = 0; *(message + i) != '\0'; i++) {
14 | lower[i] = tolower(message[i]);
15 | }
16 |
17 | lower[strlen(message)] = '\0';
18 |
19 | char* ptr;
20 | if((ptr = strstr(lower, "game mode: ")) != NULL) {
21 | ptr += 11;
22 | } else if((ptr = strstr(lower, "gamemode: ")) != NULL) {
23 | ptr += 10;
24 | } else {
25 | goto end;
26 | return;
27 | }
28 |
29 | if(!strcmp(ptr, "arena") || !strcmp(ptr, "arena by yourself")) { gmi_mode = GMI_MODE_ARENA; }
30 | else if(!strcmp(ptr, "babel")) { gmi_mode = GMI_MODE_BABEL; }
31 | else if(!strcmp(ptr, "tdm")) { gmi_mode = GMI_MODE_TDM; }
32 | else {
33 | gmi_mode = GMI_MODE_UNKNOWN;
34 | log_info("unknown mode %s", ptr);
35 | goto end;
36 | }
37 |
38 | log_info("DETERMINED GAMEMODE: %s", ptr);
39 |
40 | end:
41 | free(lower);
42 | }
43 |
44 | void gmi_parse_tdm(char* message) {
45 |
46 | }
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | BasedOnStyle: WebKit
3 | AlignAfterOpenBracket: Align
4 | AlignConsecutiveAssignments: 'false'
5 | AlignConsecutiveDeclarations: 'false'
6 | AlignTrailingComments: 'true'
7 | AllowAllParametersOfDeclarationOnNextLine: 'true'
8 | AllowShortBlocksOnASingleLine: 'true'
9 | AllowShortCaseLabelsOnASingleLine: 'true'
10 | AllowShortFunctionsOnASingleLine: Empty
11 | AllowShortIfStatementsOnASingleLine: 'false'
12 | AllowShortLoopsOnASingleLine: 'false'
13 | AlwaysBreakAfterDefinitionReturnType: None
14 | AlwaysBreakAfterReturnType: None
15 | AlwaysBreakBeforeMultilineStrings: 'false'
16 | BreakBeforeBraces: Attach
17 | BreakBeforeTernaryOperators: 'false'
18 | Cpp11BracedListStyle: 'true'
19 | ExperimentalAutoDetectBinPacking: 'false'
20 | IndentCaseLabels: 'true'
21 | KeepEmptyLinesAtTheStartOfBlocks: 'false'
22 | Language: Cpp
23 | PointerAlignment: Left
24 | SortIncludes: 'false'
25 | SpaceAfterCStyleCast: 'false'
26 | SpaceBeforeAssignmentOperators: 'true'
27 | SpaceBeforeParens: Never
28 | SpaceInEmptyParentheses: 'false'
29 | SpacesInCStyleCastParentheses: 'false'
30 | SpacesInParentheses: 'false'
31 | SpacesInSquareBrackets: 'false'
32 | TabWidth: '4'
33 | UseTab: Always
34 | MaxEmptyLinesToKeep: 1
35 | ReflowComments: true
36 | ColumnLimit: 120
37 |
38 | ...
39 |
--------------------------------------------------------------------------------
/cmake/Modules/Finddeflate.cmake:
--------------------------------------------------------------------------------
1 | # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 | # file Copyright.txt or https://cmake.org/licensing for details.
3 |
4 | #.rst:
5 | # Finddeflate
6 | # -------
7 | #
8 | # Finds the libdeflate library
9 | #
10 | # This will define the following variables::
11 | #
12 | # deflate_FOUND - True if the system has the deflate library
13 | #
14 | # and also the following imported target:
15 | #
16 | # deflate::deflate
17 | #
18 |
19 | find_package(PkgConfig)
20 | pkg_check_modules(PC_deflate QUIET deflate)
21 |
22 | find_path(deflate_INCLUDE_DIR
23 | NAMES libdeflate.h
24 | PATHS ${PC_deflate_INCLUDE_DIRS} ../../deps
25 | PATH_SUFFIXES deflate
26 | )
27 | find_library(deflate_LIBRARY
28 | NAMES deflate
29 | PATHS ${PC_deflate_LIBRARY_DIRS} ../../deps
30 | )
31 |
32 | include(FindPackageHandleStandardArgs)
33 | find_package_handle_standard_args(deflate
34 | FOUND_VAR deflate_FOUND
35 | REQUIRED_VARS
36 | deflate_LIBRARY
37 | deflate_INCLUDE_DIR
38 | )
39 |
40 | if (deflate_FOUND)
41 | add_library(deflate::deflate STATIC IMPORTED)
42 | set_target_properties(deflate::deflate PROPERTIES
43 | IMPORTED_LOCATION ${deflate_LIBRARY}
44 | INTERFACE_INCLUDE_DIRECTORIES ${deflate_INCLUDE_DIR}
45 | )
46 | endif (deflate_FOUND)
47 |
--------------------------------------------------------------------------------
/src/utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef UTILS_H
21 | #define UTILS_H
22 |
23 | #include
24 | #include
25 |
26 | #include "hashtable.h"
27 |
28 | int base64_decode(char* data, int len);
29 |
30 | int int_cmp(void* first_key, void* second_key, size_t key_size);
31 | size_t int_hash(void* raw_key, size_t key_size);
32 | void ht_iterate_remove(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user));
33 | bool ht_iterate(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user));
34 |
35 | #endif
36 |
--------------------------------------------------------------------------------
/src/font.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef FONT_H
21 | #define FONT_H
22 |
23 | enum font_type {
24 | FONT_FIXEDSYS,
25 | FONT_SMALLFNT,
26 | FONT_FANTASY,
27 | };
28 |
29 | void font_init(void);
30 | void font_reset(void);
31 | float font_length(float h, char* text);
32 | void font_render(float x, float y, float h, char* text);
33 | void font_render_shadow(float x, float y, float h, char* text, float a);
34 | void font_centered(float x, float y, float h, char* text);
35 | void font_centered_shadow(float x, float y, float h, char* text, float a);
36 | void font_select(enum font_type type);
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.14)
2 | project(BetterSpades C)
3 |
4 | set(BETTERSPADES_MAJOR 0)
5 | set(BETTERSPADES_MINOR 1)
6 | set(BETTERSPADES_PATCH 5)
7 |
8 | option(ENABLE_TOUCH "Enable touch support including ingame overlay" OFF)
9 | option(ENABLE_ANDROID_FILE "Use SDL's file functions" OFF)
10 | option(ENABLE_OPENGLES "Build for OpenGL ES" OFF)
11 | option(ENABLE_SDL "Build against SDL backend" OFF)
12 | option(ENABLE_GLFW "Build against GLFW3 backend" ON)
13 | option(ENABLE_SOUND "Enable sound support using OpenAL" ON)
14 | option(ENABLE_RPC "Enable Discord Rich Presence support" OFF)
15 |
16 |
17 | if((ENABLE_ANDROID_FILE OR ENABLE_TOUCH OR ENABLE_OPENGLES) AND NOT ENABLE_SDL)
18 | message(FATAL_ERROR "Enable SDL to use ENABLE_ANDROID_FILE, ENABLE_TOUCH or ENABLE_OPENGLES")
19 | endif()
20 | if(ENABLE_SDL AND ENABLE_GLFW)
21 | message(FATAL_ERROR "Only one backend must be selected")
22 | endif()
23 | if(NOT ENABLE_SDL AND NOT ENABLE_GLFW)
24 | message(FATAL_ERROR "Enable SDL or GLFW")
25 | endif()
26 |
27 | message(STATUS "Compiler is ${CMAKE_CXX_COMPILER_ID}")
28 | message(STATUS "Build type is ${CMAKE_BUILD_TYPE}")
29 |
30 | if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
31 | if(CMAKE_BUILD_TYPE STREQUAL "Release")
32 | add_compile_options(-Ofast)
33 | else()
34 | add_compile_options(-Ofast -g -march=native)
35 | endif()
36 | endif()
37 |
38 | add_subdirectory(src)
39 |
--------------------------------------------------------------------------------
/src/entitysystem.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef ENTITY_SYSTEM_H
21 | #define ENTITY_SYSTEM_H
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | struct entity_system {
28 | void* buffer;
29 | size_t count;
30 | size_t length;
31 | size_t object_size;
32 | pthread_mutex_t lock;
33 | };
34 |
35 | void entitysys_create(struct entity_system* es, size_t object_size, size_t initial_size);
36 |
37 | void entitysys_add(struct entity_system* es, void* object);
38 |
39 | void entitysys_iterate(struct entity_system* es, void* user, bool (*callback)(void* object, void* user));
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/src/tracer.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef TRACER_H
21 | #define TRACER_H
22 |
23 | #include "aabb.h"
24 | #include "player.h"
25 | #include "camera.h"
26 |
27 | struct Tracer {
28 | struct Camera_HitType hit;
29 | float x, y, z;
30 | Ray r;
31 | int type;
32 | float created;
33 | };
34 |
35 | void tracer_minimap(int large, float scalef, float minimap_x, float minimap_y);
36 | void tracer_pvelocity(float* o, struct Player* p);
37 | void tracer_add(int type, float x, float y, float z, float dx, float dy, float dz);
38 | void tracer_update(float dt);
39 | void tracer_render(void);
40 | void tracer_init(void);
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/src/main.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef MAIN_H
21 | #define MAIN_H
22 |
23 | #include "window.h"
24 |
25 | void reshape(struct window_instance* window, int width, int height);
26 | void text_input(struct window_instance* window, unsigned int codepoint);
27 | void keys(struct window_instance* window, int key, int scancode, int action, int mods);
28 | void mouse_click(struct window_instance* window, int button, int action, int mods);
29 | void mouse(struct window_instance* window, double x, double y);
30 | void mouse_scroll(struct window_instance* window, double xoffset, double yoffset);
31 | void on_error(int i, const char* s);
32 |
33 | #endif
34 |
--------------------------------------------------------------------------------
/src/particle.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef PARTICLE_H
21 | #define PARTICLE_H
22 |
23 | #include "player.h"
24 |
25 | struct Particle {
26 | float x, y, z;
27 | float vx, vy, vz;
28 | float ox, oy, oz;
29 | unsigned char type;
30 | float size;
31 | float fade;
32 | unsigned int color;
33 | };
34 |
35 | void particle_init(void);
36 | void particle_update(float dt);
37 | void particle_render(void);
38 | void particle_create_casing(struct Player* p);
39 | void particle_create(unsigned int color, float x, float y, float z, float velocity, float velocity_y, int amount,
40 | float min_size, float max_size);
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/cmake/Modules/Findenet.cmake:
--------------------------------------------------------------------------------
1 | # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 | # file Copyright.txt or https://cmake.org/licensing for details.
3 |
4 | #.rst:
5 | # Findenet
6 | # -------
7 | #
8 | # Finds the libenet library
9 | #
10 | # This will define the following variables::
11 | #
12 | # enet_FOUND - True if the system has the enet library
13 | #
14 | # and also the following imported target:
15 | #
16 | # enet::enet
17 | #
18 | find_package(PkgConfig)
19 | pkg_check_modules(PC_enet QUIET enet)
20 |
21 | find_path(enet_INCLUDE_DIR
22 | NAMES enet/enet.h
23 | PATHS ${PC_enet_INCLUDE_DIRS} ../../deps
24 | PATH_SUFFIXES enet
25 | )
26 |
27 | find_library(enet_LIBRARY
28 | NAMES enet
29 | PATHS ${PC_enet_LIBRARY_DIRS} ../../deps
30 | )
31 |
32 | include(FindPackageHandleStandardArgs)
33 | find_package_handle_standard_args(enet
34 | FOUND_VAR enet_FOUND
35 | REQUIRED_VARS
36 | enet_LIBRARY
37 | enet_INCLUDE_DIR
38 | )
39 |
40 | if (enet_FOUND)
41 | add_library(enet::enet STATIC IMPORTED)
42 | set_target_properties(enet::enet PROPERTIES
43 | IMPORTED_LOCATION ${enet_LIBRARY}
44 | INTERFACE_INCLUDE_DIRECTORIES ${enet_INCLUDE_DIR}
45 | )
46 | #target_include_directories(enet::enet INTERFACE ${enet_INCLUDE_DIR})
47 | if (WIN32)
48 | set_target_properties(enet::enet PROPERTIES
49 | INTERFACE_LINK_LIBRARIES "ws2_32;winmm"
50 | )
51 | endif (WIN32)
52 | endif (enet_FOUND)
53 |
--------------------------------------------------------------------------------
/src/file.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef FILE_H
21 | #define FILE_H
22 |
23 | void* file_open(const char* name, const char* mode);
24 | void file_printf(void* file, const char* fmt, ...);
25 | void file_close(void* file);
26 | int file_size(const char* name);
27 | int file_dir_exists(const char* path);
28 | int file_dir_create(const char* path);
29 | int file_exists(const char* name);
30 | unsigned char* file_load(const char* name);
31 | float buffer_readf(unsigned char* buffer, int index);
32 | unsigned int buffer_read32(unsigned char* buffer, int index);
33 | unsigned short buffer_read16(unsigned char* buffer, int index);
34 | unsigned char buffer_read8(unsigned char* buffer, int index);
35 | void file_url(char* url);
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/src/channel.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef CHANNEL_H
21 | #define CHANNEL_H
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | struct channel {
28 | size_t object_size;
29 | size_t initial_length;
30 | size_t length;
31 | size_t count;
32 | size_t loc_insert;
33 | size_t loc_remove;
34 | void* queue;
35 | pthread_mutex_t lock;
36 | pthread_cond_t signal;
37 | };
38 |
39 | bool channel_create(struct channel* ch, size_t object_size, size_t length);
40 |
41 | size_t channel_size(struct channel* ch);
42 |
43 | void channel_destroy(struct channel* ch);
44 |
45 | void channel_put(struct channel* ch, void* object);
46 |
47 | void channel_await(struct channel* ch, void* object);
48 |
49 | void channel_clear(struct channel* ch);
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/src/cameracontroller.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef CAMERACONTROLLER_H
21 | #define CAMERACONTROLLER_H
22 |
23 | extern int cameracontroller_bodyview_mode;
24 | extern int cameracontroller_bodyview_player;
25 | extern int cameracontroller_yclamp;
26 | extern float cameracontroller_bodyview_zoom;
27 |
28 | void cameracontroller_death_init(int player, float x, float y, float z);
29 |
30 | void cameracontroller_fps(float dt);
31 | void cameracontroller_spectator(float dt);
32 | void cameracontroller_bodyview(float dt);
33 | void cameracontroller_selection(float dt);
34 | void cameracontroller_death(float dt);
35 |
36 | void cameracontroller_fps_render(void);
37 | void cameracontroller_spectator_render(void);
38 | void cameracontroller_bodyview_render(void);
39 | void cameracontroller_selection_render(void);
40 | void cameracontroller_death_render(void);
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/src/aabb.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef AABB_H
21 | #define AABB_H
22 |
23 | #include
24 |
25 | typedef struct {
26 | union {
27 | struct {
28 | float min_x, min_y, min_z;
29 | };
30 | float min[3];
31 | };
32 | union {
33 | struct {
34 | float max_x, max_y, max_z;
35 | };
36 | float max[3];
37 | };
38 | } AABB;
39 |
40 | typedef struct {
41 | union {
42 | struct {
43 | float x, y, z;
44 | };
45 | float coords[3];
46 | } origin;
47 | union {
48 | struct {
49 | float x, y, z;
50 | };
51 | float coords[3];
52 | } direction;
53 | } Ray;
54 |
55 | bool aabb_intersection(AABB* a, AABB* b);
56 | bool aabb_intersection_ray(AABB* a, Ray* r, float* distance);
57 | bool aabb_intersection_terrain(AABB* a, int miny);
58 | void aabb_set_size(AABB* a, float x, float y, float z);
59 | void aabb_set_center(AABB* a, float x, float y, float z);
60 | void aabb_render(AABB* a);
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/src/log.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017 rxi
3 | *
4 | * This library is free software; you can redistribute it and/or modify it
5 | * under the terms of the MIT license. See `log.c` for details.
6 | */
7 |
8 | #ifndef LOG_H
9 | #define LOG_H
10 |
11 | #define __FILENAME__ \
12 | (__builtin_strrchr(__FILE__, '/') \
13 | ? (__builtin_strrchr(__FILE__, '/') + 1) \
14 | : (__builtin_strrchr(__FILE__, '\\') \
15 | ? __builtin_strrchr(__FILE__, '\\') + 1 \
16 | : __FILE__))
17 |
18 | #include
19 | #include
20 |
21 | #define LOG_VERSION "0.1.0"
22 |
23 | typedef void (*log_LockFn)(void *udata, int lock);
24 |
25 | enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
26 |
27 | #define log_trace(...) log_log(LOG_TRACE, __FILENAME__, __LINE__, __VA_ARGS__)
28 | #define log_debug(...) log_log(LOG_DEBUG, __FILENAME__, __LINE__, __VA_ARGS__)
29 | #define log_info(...) log_log(LOG_INFO, __FILENAME__, __LINE__, __VA_ARGS__)
30 | #define log_warn(...) log_log(LOG_WARN, __FILENAME__, __LINE__, __VA_ARGS__)
31 | #define log_error(...) log_log(LOG_ERROR, __FILENAME__, __LINE__, __VA_ARGS__)
32 | #define log_fatal(...) log_log(LOG_FATAL, __FILENAME__, __LINE__, __VA_ARGS__)
33 |
34 | void log_set_udata(void *udata);
35 | void log_set_lock(log_LockFn fn);
36 | void log_set_fp(FILE *fp);
37 | void log_set_level(int level);
38 | void log_set_quiet(int enable);
39 |
40 | void log_log(int level, const char *file, int line, const char *fmt, ...);
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/src/weapon.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef WEAPON_H
21 | #define WEAPON_H
22 |
23 | #include "player.h"
24 | #include "sound.h"
25 | #include "model.h"
26 |
27 | void weapon_update(void);
28 | void weapon_set(bool restock);
29 | void weapon_reload(void);
30 | int weapon_reloading(void);
31 | int weapon_can_reload(void);
32 | void weapon_reload_abort(void);
33 | void weapon_shoot(void);
34 | int weapon_block_damage(int gun);
35 | float weapon_delay(int gun);
36 | int weapon_ammo(int gun);
37 | int weapon_ammo_reserved(int gun);
38 | struct kv6_t* weapon_casing(int gun);
39 | float weapon_recoil_anim(int gun);
40 | struct Sound_wav* weapon_sound(int gun);
41 | struct Sound_wav* weapon_sound_reload(int gun);
42 | void weapon_spread(struct Player* p, float* d);
43 | void weapon_recoil(int gun, double* horiz_recoil, double* vert_recoil);
44 |
45 | extern float weapon_reload_start, weapon_last_shot;
46 | extern unsigned char weapon_reload_inprogress;
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/src/minheap.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef MINHEAP_H
21 | #define MINHEAP_H
22 |
23 | #define pos_key(x, y, z) (((z) << 20) | ((x) << 8) | (y))
24 | #define pos_keyx(key) (((key) >> 8) & 0xFFF)
25 | #define pos_keyy(key) ((key)&0xFF)
26 | #define pos_keyz(key) (((key) >> 20) & 0xFFF)
27 |
28 | struct path_vec {
29 | short x, y, z;
30 | };
31 |
32 | struct minheap_block {
33 | uint32_t pos;
34 | };
35 |
36 | struct minheap {
37 | int index;
38 | int length;
39 | struct minheap_block* nodes;
40 | };
41 |
42 | int int_cmp(void* first_key, void* second_key, size_t key_size);
43 | size_t int_hash(void* raw_key, size_t key_size);
44 |
45 | void minheap_create(struct minheap* h);
46 | void minheap_clear(struct minheap* h);
47 | void minheap_destroy(struct minheap* h);
48 | int minheap_isempty(struct minheap* h);
49 | struct minheap_block minheap_extract(struct minheap* h);
50 | void minheap_set(struct minheap* h, struct minheap_block* b, int value);
51 | struct minheap_block* minheap_put(struct minheap* h, struct minheap_block* b);
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/glx.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | // for future opengl es abstraction layer
21 |
22 | #ifndef GLX_H
23 | #define GLX_H
24 |
25 | #include
26 | #include
27 |
28 | extern int glx_version;
29 | extern int glx_fog;
30 |
31 | struct glx_displaylist {
32 | uint32_t legacy;
33 | uint32_t modern;
34 | size_t size;
35 | size_t buffer_size;
36 | bool has_normal;
37 | bool has_color;
38 | };
39 |
40 | enum {
41 | GLX_DISPLAYLIST_NORMAL,
42 | GLX_DISPLAYLIST_ENHANCED,
43 | GLX_DISPLAYLIST_POINTS,
44 | };
45 |
46 | void glx_init(void);
47 |
48 | int glx_shader(const char* vertex, const char* fragment);
49 |
50 | void glx_enable_sphericalfog(void);
51 | void glx_disable_sphericalfog(void);
52 |
53 | void glx_displaylist_create(struct glx_displaylist* x, bool has_color, bool has_normal);
54 | void glx_displaylist_destroy(struct glx_displaylist* x);
55 | void glx_displaylist_update(struct glx_displaylist* x, size_t size, int type, void* color, void* vertex, void* normal);
56 | void glx_displaylist_draw(struct glx_displaylist* x, int type);
57 |
58 | #endif
59 |
--------------------------------------------------------------------------------
/src/chunk.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef CHUNK_H
21 | #define CHUNK_H
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include "glx.h"
29 | #include "tesselator.h"
30 | #include "libvxl.h"
31 |
32 | #define CHUNK_SIZE 16
33 | #define CHUNKS_PER_DIM (512 / CHUNK_SIZE)
34 |
35 | extern struct chunk {
36 | struct glx_displaylist display_list;
37 | int max_height;
38 | bool updated;
39 | bool created;
40 | int x, y;
41 | } chunks[CHUNKS_PER_DIM * CHUNKS_PER_DIM];
42 |
43 | #define CHUNK_WORKERS_MAX 16
44 |
45 | void chunk_init(void);
46 |
47 | void chunk_block_update(int x, int y, int z);
48 | void chunk_update_all(void);
49 | void* chunk_generate(void* data);
50 | void chunk_generate_greedy(struct libvxl_chunk_copy* blocks, size_t start_x, size_t start_z, struct tesselator* tess,
51 | int* max_height);
52 | void chunk_generate_naive(struct libvxl_chunk_copy* blocks, struct tesselator* tess, int* max_height, int ao);
53 | void chunk_rebuild_all(void);
54 | void chunk_draw_visible(void);
55 | void chunk_queue_blocks();
56 |
57 | #endif
58 |
--------------------------------------------------------------------------------
/src/matrix.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef MATRIX_H
21 | #define MATRIX_H
22 |
23 | #include
24 |
25 | extern mat4 matrix_view;
26 | extern mat4 matrix_model;
27 | extern mat4 matrix_projection;
28 |
29 | void matrix_multiply(mat4 m, mat4 n);
30 | void matrix_load(mat4 m, mat4 n);
31 | void matrix_rotate(mat4 m, float angle, float x, float y, float z);
32 | void matrix_translate(mat4 m, float x, float y, float z);
33 | void matrix_scale3(mat4 m, float s);
34 | void matrix_scale(mat4 m, float sx, float sy, float sz);
35 | void matrix_identity(mat4 m);
36 | void matrix_push(mat4 m);
37 | void matrix_pop(mat4 m);
38 | void matrix_vector(mat4 m, vec4 v);
39 | void matrix_ortho(mat4 m, float left, float right, float bottom, float top, float nearv, float farv);
40 | void matrix_perspective(mat4 m, float fovy, float aspect, float zNear, float zFar);
41 | void matrix_lookAt(mat4 m, double eyex, double eyey, double eyez, double centerx, double centery, double centerz,
42 | double upx, double upy, double upz);
43 | void matrix_upload(void);
44 | void matrix_upload_p(void);
45 | void matrix_pointAt(mat4 m, float dx, float dy, float dz);
46 |
47 | #endif
48 |
--------------------------------------------------------------------------------
/src/map.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef MAP_H
21 | #define MAP_H
22 |
23 | #include
24 |
25 | #include
26 | #undef pos_key
27 |
28 | extern int map_size_x;
29 | extern int map_size_y;
30 | extern int map_size_z;
31 |
32 | extern float fog_color[4];
33 |
34 | struct Point {
35 | int x, y, z;
36 | };
37 |
38 | void map_init();
39 | int map_object_visible(float x, float y, float z);
40 | int map_damage(int x, int y, int z, int damage);
41 | int map_damage_get(int x, int y, int z);
42 | bool map_damage_action(int x, int y, int z);
43 | void map_damaged_voxels_render();
44 | void map_update_physics(int x, int y, int z);
45 | float map_sunblock(int x, int y, int z);
46 | bool map_isair(int x, int y, int z);
47 | unsigned int map_get(int x, int y, int z);
48 | void map_set(int x, int y, int z, unsigned int color);
49 | int map_cube_line(int x1, int y1, int z1, int x2, int y2, int z2, struct Point* cube_array);
50 | void map_vxl_setgeom(int x, int y, int z, unsigned int t, unsigned int* map);
51 | void map_vxl_setcolor(int x, int y, int z, unsigned int t, unsigned int* map);
52 | int map_dirt_color(int x, int y, int z);
53 | int map_placedblock_color(int color);
54 | void map_vxl_load(void* v, size_t size);
55 | void map_collapsing_render(void);
56 | void map_collapsing_update(float dt);
57 | int map_height_at(int x, int z);
58 | void map_save_file(const char* filename);
59 | void map_copy_blocks(struct libvxl_chunk_copy* copy, size_t x, size_t y);
60 |
61 | #endif
62 |
--------------------------------------------------------------------------------
/src/hud.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef HUD_H
21 | #define HUD_H
22 |
23 | #include
24 |
25 | #include "microui.h"
26 | #include "texture.h"
27 | #include "window.h"
28 |
29 | struct hud {
30 | void (*init)();
31 | void (*render_3D)();
32 | void (*render_2D)(mu_Context* ctx, float scalex, float scaley);
33 | void (*input_keyboard)(int key, int action, int mods, int internal);
34 | void (*input_mouselocation)(double x, double y);
35 | void (*input_mouseclick)(double x, double y, int button, int action, int mods);
36 | void (*input_mousescroll)(double yoffset);
37 | void (*input_touch)(void* finger, int action, float x, float y, float dx, float dy);
38 | struct texture* (*ui_images)(int icon_id, bool* resize);
39 | char render_world;
40 | char render_localplayer;
41 | mu_Context* ctx;
42 | };
43 |
44 | struct serverlist_entry {
45 | int current, max;
46 | char name[32];
47 | char map[21];
48 | char gamemode[8];
49 | int ping;
50 | char identifier[32];
51 | char country[4];
52 | };
53 |
54 | extern int screen_current;
55 | extern int show_exit;
56 |
57 | extern struct hud hud_ingame;
58 | extern struct hud hud_mapload;
59 | extern struct hud hud_serverlist;
60 | extern struct hud hud_settings;
61 | extern struct hud hud_controls;
62 |
63 | extern struct hud* hud_active;
64 | extern struct window_instance* hud_window;
65 |
66 | #define HUD_FLAG_INDEX_START 64
67 |
68 | void hud_change(struct hud* new);
69 | void hud_init();
70 | void hud_mousemode(int mode);
71 | int hud_accent_color();
72 |
73 | #endif
74 |
--------------------------------------------------------------------------------
/src/entitysystem.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "entitysystem.h"
26 |
27 | void entitysys_create(struct entity_system* es, size_t object_size, size_t initial_size) {
28 | assert(es != NULL && object_size > 0 && initial_size > 0);
29 |
30 | es->buffer = malloc(object_size * initial_size);
31 | es->count = 0;
32 | es->object_size = object_size;
33 | es->length = initial_size;
34 |
35 | pthread_mutex_init(&es->lock, NULL);
36 | }
37 |
38 | void entitysys_iterate(struct entity_system* es, void* user, bool (*callback)(void* object, void* user)) {
39 | assert(es != NULL && callback != NULL);
40 |
41 | pthread_mutex_lock(&es->lock);
42 |
43 | uint8_t* obj = es->buffer;
44 | for(size_t k = 0; k < es->count; k++, obj += es->object_size) {
45 | if(callback(obj, user)) {
46 | if(es->count > 1)
47 | memcpy(obj, (uint8_t*)es->buffer + es->object_size * (es->count - 1), es->object_size);
48 |
49 | es->count--;
50 | }
51 | }
52 |
53 | pthread_mutex_unlock(&es->lock);
54 | }
55 |
56 | void entitysys_add(struct entity_system* es, void* object) {
57 | assert(es != NULL && object != NULL);
58 |
59 | pthread_mutex_lock(&es->lock);
60 |
61 | if(es->count >= es->length) {
62 | es->length *= 2;
63 | es->buffer = realloc(es->buffer, es->object_size * es->length);
64 | }
65 |
66 | memcpy((uint8_t*)es->buffer + es->object_size * (es->count++), object, es->object_size);
67 |
68 | pthread_mutex_unlock(&es->lock);
69 | }
70 |
--------------------------------------------------------------------------------
/src/camera.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef CAMERA_H
21 | #define CAMERA_H
22 |
23 | enum camera_mode {
24 | CAMERAMODE_SELECTION,
25 | CAMERAMODE_FPS,
26 | CAMERAMODE_SPECTATOR,
27 | CAMERAMODE_BODYVIEW,
28 | CAMERAMODE_DEATH,
29 | };
30 |
31 | #define CAMERA_DEFAULT_FOV 70.0F
32 | #define CAMERA_MAX_FOV 100.0F
33 |
34 | extern enum camera_mode camera_mode;
35 |
36 | extern float frustum[6][4];
37 | extern float camera_rot_x, camera_rot_y;
38 | extern float camera_x, camera_y, camera_z;
39 | extern float camera_vx, camera_vy, camera_vz;
40 | extern float camera_size;
41 | extern float camera_height;
42 | extern float camera_eye_height;
43 | extern float camera_movement_x, camera_movement_y, camera_movement_z;
44 | extern float camera_speed;
45 |
46 | struct Camera_HitType {
47 | char type;
48 | float x, y, z, distance;
49 | int xb, yb, zb;
50 | unsigned char player_id, player_section;
51 | };
52 |
53 | #define CAMERA_HITTYPE_NONE 0
54 | #define CAMERA_HITTYPE_BLOCK 1
55 | #define CAMERA_HITTYPE_PLAYER 2
56 |
57 | void camera_hit_fromplayer(struct Camera_HitType* hit, int player_id, float range);
58 | void camera_hit(struct Camera_HitType* hit, int exclude_player, float x, float y, float z, float ray_x, float ray_y,
59 | float ray_z, float range);
60 | void camera_hit_mask(struct Camera_HitType* hit, int exclude_player, float x, float y, float z, float ray_x,
61 | float ray_y, float ray_z, float range);
62 |
63 | float camera_fov_scaled();
64 | void camera_ExtractFrustum(void);
65 | unsigned char camera_PointInFrustum(float x, float y, float z);
66 | int camera_CubeInFrustum(float x, float y, float z, float size, float size_y);
67 | int* camera_terrain_pick(unsigned char mode);
68 | int* camera_terrain_pickEx(unsigned char mode, float x, float y, float z, float ray_x, float ray_y, float ray_z);
69 | void camera_overflow_adjust(void);
70 | void camera_apply(void);
71 | void camera_update(float dt);
72 |
73 | #endif
74 |
--------------------------------------------------------------------------------
/resources/config.ini:
--------------------------------------------------------------------------------
1 | [client]
2 | name = Deuce
3 | xres = 1024
4 | yres = 768
5 | vol = 10
6 | inverty = 0
7 | windowed = 1
8 | language = 0
9 | mouse_sensitivity = 5.000000
10 | show_news = 1
11 | multisamples = 0
12 | greedy_meshing = 0
13 | vsync = 1
14 | show_fps = 0
15 | voxlap_models = 0
16 | force_displaylist = 0
17 | smooth_fog = 0
18 | ambient_occlusion = 0
19 | camera_fov = 70.00000
20 | hold_down_sights = 0
21 | chat_shadow = 0.6
22 | chat_flip_on_open = 1
23 | show_player_arms = 0
24 | bg_tile = 1
25 | bg_tile_speed = 0.09
26 | ui_accent_r = 110
27 | ui_accent_g = 90
28 | ui_accent_b = 230
29 | lighten_colors = 120
30 | hud_shadows = 1
31 | show_names_in_spec = 1
32 | chat_spacing = 6
33 | spectator_speed = 1.0
34 | iron_sight = 0
35 | gmi = 0
36 | disable_raw_input = 0
37 | ui_spacing = 8
38 | ui_padding = 5
39 |
40 | [controls]
41 | move_forward = 87
42 | move_backward = 83
43 | move_left = 65
44 | move_right = 68
45 | jump = 32
46 | crouch = 341
47 | sneak = 86
48 | sprint = 340
49 | view_map = 77
50 | reload = 82
51 | cube_color_up = 265
52 | cube_color_down = 264
53 | cube_color_left = 263
54 | cube_color_right = 262
55 | cube_color_sample = 69
56 | quit_game = 256
57 | volume_up = 334
58 | volume_down = 333
59 | view_score = 258
60 | change_team = 44
61 | change_weapon = 46
62 | screenshot = 294
63 | fullscreen = 300
64 | chat_global = 84
65 | chat_command = 47
66 | hide_hud = 295
67 | network_stats = 301
68 | last_tool = 81
69 | tool_block = 50
70 | tool_grenade = 52
71 | tool_gun = 51
72 | tool_spade = 49
73 | save_map = 298
74 |
--------------------------------------------------------------------------------
/src/model.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef MODEL_H
21 | #define MODEL_H
22 |
23 | #include
24 | #include
25 |
26 | #include "aabb.h"
27 | #include "glx.h"
28 | #include "tesselator.h"
29 |
30 | #define KV6_VIS_NEG_X (1 << 0)
31 | #define KV6_VIS_POS_X (1 << 1)
32 | #define KV6_VIS_NEG_Z (1 << 2)
33 | #define KV6_VIS_POS_Z (1 << 3)
34 | #define KV6_VIS_POS_Y (1 << 4)
35 | #define KV6_VIS_NEG_Y (1 << 5)
36 |
37 | struct kv6_voxel {
38 | uint16_t x, y, z;
39 | uint8_t visfaces;
40 | uint32_t color;
41 | };
42 |
43 | struct kv6_t {
44 | uint16_t xsiz, ysiz, zsiz;
45 | float xpiv, ypiv, zpiv;
46 | bool has_display_list, colorize;
47 | struct glx_displaylist display_list[2];
48 | struct kv6_voxel* voxels;
49 | int voxel_count;
50 | float scale;
51 | float red, green, blue;
52 | };
53 |
54 | extern struct kv6_t model_playerdead;
55 | extern struct kv6_t model_playerhead;
56 | extern struct kv6_t model_playertorso;
57 | extern struct kv6_t model_playertorsoc;
58 | extern struct kv6_t model_playerarms;
59 | extern struct kv6_t model_playerleg;
60 | extern struct kv6_t model_playerlegc;
61 | extern struct kv6_t model_intel;
62 | extern struct kv6_t model_tent;
63 |
64 | extern struct kv6_t model_semi;
65 | extern struct kv6_t model_smg;
66 | extern struct kv6_t model_shotgun;
67 | extern struct kv6_t model_spade;
68 | extern struct kv6_t model_block;
69 | extern struct kv6_t model_grenade;
70 |
71 | extern struct kv6_t model_semi_tracer;
72 | extern struct kv6_t model_smg_tracer;
73 | extern struct kv6_t model_shotgun_tracer;
74 |
75 | extern struct kv6_t model_semi_casing;
76 | extern struct kv6_t model_smg_casing;
77 | extern struct kv6_t model_shotgun_casing;
78 |
79 | void kv6_calclight(int x, int y, int z);
80 | void kv6_rebuild_complete(void);
81 | void kv6_rebuild(struct kv6_t* kv6);
82 | void kv6_render(struct kv6_t* kv6, unsigned char team);
83 | void kv6_load(struct kv6_t* kv6, void* bytes, float scale);
84 | void kv6_init(void);
85 |
86 | extern float kv6_normals[256][3];
87 |
88 | #endif
89 |
--------------------------------------------------------------------------------
/src/tesselator.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef TESSELATOR_H
21 | #define TESSELATOR_H
22 |
23 | #include
24 |
25 | #include "glx.h"
26 |
27 | #ifdef OPENGL_ES
28 | #define TESSELATE_TRIANGLES
29 | #else
30 | #define TESSELATE_QUADS
31 | #endif
32 |
33 | enum tesselator_vertex_type {
34 | VERTEX_INT,
35 | VERTEX_FLOAT,
36 | };
37 |
38 | struct tesselator {
39 | void* vertices;
40 | int8_t* normals;
41 | uint32_t* colors;
42 | uint32_t quad_count;
43 | uint32_t quad_space;
44 | int has_normal;
45 | uint32_t color;
46 | int8_t normal[3];
47 | enum tesselator_vertex_type vertex_type;
48 | };
49 |
50 | enum tesselator_cube_face {
51 | CUBE_FACE_X_N,
52 | CUBE_FACE_X_P,
53 | CUBE_FACE_Y_N,
54 | CUBE_FACE_Y_P,
55 | CUBE_FACE_Z_N,
56 | CUBE_FACE_Z_P,
57 | };
58 |
59 | void tesselator_create(struct tesselator* t, enum tesselator_vertex_type type, int has_normal);
60 | void tesselator_clear(struct tesselator* t);
61 | void tesselator_free(struct tesselator* t);
62 | void tesselator_draw(struct tesselator* t, int with_color);
63 | void tesselator_glx(struct tesselator* t, struct glx_displaylist* x);
64 | void tesselator_set_color(struct tesselator* t, uint32_t color);
65 | void tesselator_set_normal(struct tesselator* t, int8_t x, int8_t y, int8_t z);
66 | void tesselator_addi(struct tesselator* t, int16_t* coords, uint32_t* colors, int8_t* normals);
67 | void tesselator_addf(struct tesselator* t, float* coords, uint32_t* colors, int8_t* normals);
68 | void tesselator_addi_simple(struct tesselator* t, int16_t* coords);
69 | void tesselator_addf_simple(struct tesselator* t, float* coords);
70 | void tesselator_addi_cube_face(struct tesselator* t, enum tesselator_cube_face face, int16_t x, int16_t y, int16_t z);
71 | void tesselator_addi_cube_face_adv(struct tesselator* t, enum tesselator_cube_face face, int16_t x, int16_t y,
72 | int16_t z, int16_t sx, int16_t sy, int16_t sz);
73 | void tesselator_addf_cube_face(struct tesselator* t, enum tesselator_cube_face face, float x, float y, float z,
74 | float sz);
75 |
76 | #endif
77 |
--------------------------------------------------------------------------------
/src/config.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef CONFIG_H
21 | #define CONFIG_H
22 |
23 | #include
24 |
25 | #include "list.h"
26 |
27 | struct config_file_entry {
28 | char section[32];
29 | char name[32];
30 | char value[32];
31 | };
32 |
33 | extern struct RENDER_OPTIONS {
34 | char name[16];
35 | char last_address[128];
36 | int opengl14;
37 | int color_correction;
38 | int shadow_entities;
39 | int ambient_occlusion;
40 | float render_distance;
41 | int window_width;
42 | int window_height;
43 | int multisamples;
44 | int player_arms;
45 | int fullscreen;
46 | int bg_tile;
47 | float bg_tile_speed;
48 | int ui_accent_r;
49 | int ui_accent_g;
50 | int ui_accent_b;
51 | int lighten_colors;
52 | int show_names_in_spec;
53 | int hud_shadows;
54 | int greedy_meshing;
55 | int vsync;
56 | float mouse_sensitivity;
57 | int show_news;
58 | int show_fps;
59 | int volume;
60 | int voxlap_models;
61 | int force_displaylist;
62 | int invert_y;
63 | int smooth_fog;
64 | float camera_fov;
65 | int hold_down_sights;
66 | float chat_shadow;
67 | int chat_flip_on_open;
68 | int chat_spacing;
69 | float spectator_speed;
70 | int iron_sight;
71 | int gmi;
72 | int disable_raw_input;
73 | int ui_spacing;
74 | int ui_padding;
75 | } settings, settings_tmp;
76 |
77 | extern struct list config_keys;
78 |
79 | struct config_key_pair {
80 | int internal;
81 | int def;
82 | int original;
83 | int toggle;
84 | char name[24];
85 | char display[24];
86 | char category[24];
87 | };
88 |
89 | enum {
90 | CONFIG_TYPE_STRING,
91 | CONFIG_TYPE_INT,
92 | CONFIG_TYPE_FLOAT,
93 | };
94 |
95 | struct config_setting {
96 | void* value;
97 | int type;
98 | int min;
99 | int max;
100 | char name[32];
101 | char help[64];
102 | int defaults[8];
103 | int defaults_length;
104 | void (*label_callback)(char* buffer, size_t length, int value, size_t index);
105 | };
106 |
107 | extern struct list config_settings;
108 |
109 | void config_register_key(int internal, int def, const char* name, int toggle, const char* display,
110 | const char* category);
111 | int config_key_translate(int key, int dir, int* results);
112 | struct config_key_pair* config_key(int key);
113 | void config_key_reset_togglestates();
114 | void config_reload(void);
115 | void config_save(void);
116 |
117 | #endif
118 |
--------------------------------------------------------------------------------
/src/list.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "common.h"
6 | #include "list.h"
7 |
8 | int list_created(struct list* l) {
9 | assert(l != NULL);
10 |
11 | return l->element_size > 0;
12 | }
13 |
14 | void list_create(struct list* l, size_t element_size) {
15 | assert(l != NULL && element_size > 0);
16 |
17 | l->data = NULL;
18 | l->elements = 0;
19 | l->element_size = element_size;
20 | l->mem_size = 0;
21 | }
22 |
23 | void list_free(struct list* l) {
24 | assert(l != NULL);
25 |
26 | if(l->data) {
27 | free(l->data);
28 | l->data = NULL;
29 | }
30 | }
31 |
32 | void* list_find(struct list* l, const void* ref, enum list_traverse_direction dir, int (*cmp)(const void* obj, const void* ref)) {
33 | assert(l != NULL && cmp != NULL);
34 |
35 | switch(dir) {
36 | case LIST_TRAVERSE_FORWARD:
37 | for(size_t k = 0; k < l->elements; k++) {
38 | void* obj = l->data + l->element_size * k;
39 |
40 | if(cmp(obj, ref))
41 | return obj;
42 | }
43 | break;
44 | case LIST_TRAVERSE_BACKWARD:
45 | if(!l->elements)
46 | break;
47 |
48 | size_t k = l->elements - 1;
49 |
50 | do {
51 | void* obj = l->data + l->element_size * k;
52 |
53 | if(cmp(obj, ref))
54 | return obj;
55 | } while((k--) > 0);
56 |
57 | break;
58 | }
59 |
60 | return NULL;
61 | }
62 |
63 | void list_sort(struct list* l, int (*cmp)(const void* a, const void* b)) {
64 | assert(l != NULL && cmp != NULL);
65 |
66 | qsort(l->data, l->elements, l->element_size, cmp);
67 | }
68 |
69 | void* list_get(struct list* l, size_t i) {
70 | assert(l != NULL && i < l->elements);
71 |
72 | return l->data + i * l->element_size;
73 | }
74 |
75 | void* list_add(struct list* l, void* e) {
76 | assert(l != NULL);
77 |
78 | if((l->elements + 1) * l->element_size > l->mem_size) {
79 | l->mem_size += l->element_size * 64;
80 | l->data = realloc(l->data, l->mem_size);
81 | CHECK_ALLOCATION_ERROR(l->data)
82 | }
83 |
84 | if(e)
85 | memcpy(l->data + l->elements * l->element_size, e, l->element_size);
86 | else
87 | memset(l->data + l->elements * l->element_size, 0, l->element_size);
88 |
89 | return l->data + (l->elements++) * l->element_size;
90 | }
91 |
92 | void list_remove(struct list* l, size_t i) {
93 | assert(l != NULL && i < l->elements);
94 |
95 | if(i < l->elements - 1)
96 | memmove(list_get(l, i), list_get(l, i + 1), (l->elements - (i + 1)) * l->element_size);
97 |
98 | l->elements--;
99 |
100 | if(l->mem_size - 64 * l->element_size > 0
101 | && (l->elements + 1) * l->element_size < l->mem_size - 96 * l->element_size) {
102 | l->mem_size -= l->element_size * 64;
103 | l->data = realloc(l->data, l->mem_size);
104 | CHECK_ALLOCATION_ERROR(l->data)
105 | }
106 | }
107 |
108 | void list_clear(struct list* l) {
109 | assert(l != NULL);
110 |
111 | void* new = realloc(l->data, l->element_size * 64);
112 |
113 | if(new) {
114 | l->data = new;
115 | l->mem_size = l->element_size * 64;
116 | }
117 |
118 | l->elements = 0;
119 | }
120 |
121 | int list_size(struct list* l) {
122 | assert(l != NULL);
123 |
124 | return l->elements;
125 | }
126 |
--------------------------------------------------------------------------------
/src/hashtable.h:
--------------------------------------------------------------------------------
1 | #ifndef HASHTABLE_H
2 | #define HASHTABLE_H
3 |
4 | #include
5 | #include
6 |
7 | /****************** DEFINTIIONS ******************/
8 |
9 | #define HT_MINIMUM_CAPACITY 8
10 | #define HT_LOAD_FACTOR 5
11 | #define HT_MINIMUM_THRESHOLD (HT_MINIMUM_CAPACITY) * (HT_LOAD_FACTOR)
12 |
13 | #define HT_GROWTH_FACTOR 2
14 | #define HT_SHRINK_THRESHOLD (1 / 4)
15 |
16 | #define HT_ERROR -1
17 | #define HT_SUCCESS 0
18 |
19 | #define HT_UPDATED 1
20 | #define HT_INSERTED 0
21 |
22 | #define HT_NOT_FOUND 0
23 | #define HT_FOUND 01
24 |
25 | #define HT_INITIALIZER {0, 0, 0, 0, 0, NULL, NULL, NULL};
26 |
27 | typedef int (*comparison_t)(void*, void*, size_t);
28 | typedef size_t (*hash_t)(void*, size_t);
29 |
30 | /****************** STRUCTURES ******************/
31 |
32 | typedef struct HTNode {
33 | struct HTNode* next;
34 | void* key;
35 | void* value;
36 |
37 | } HTNode;
38 |
39 | typedef struct HashTable {
40 | size_t size;
41 | size_t threshold;
42 | size_t capacity;
43 |
44 | size_t key_size;
45 | size_t value_size;
46 |
47 | comparison_t compare;
48 | hash_t hash;
49 |
50 | HTNode** nodes;
51 |
52 | } HashTable;
53 |
54 | /****************** INTERFACE ******************/
55 |
56 | /* Setup */
57 | int ht_setup(HashTable* table,
58 | size_t key_size,
59 | size_t value_size,
60 | size_t capacity);
61 |
62 | int ht_copy(HashTable* first, HashTable* second);
63 | int ht_move(HashTable* first, HashTable* second);
64 | int ht_swap(HashTable* first, HashTable* second);
65 |
66 | /* Destructor */
67 | int ht_destroy(HashTable* table);
68 |
69 | int ht_insert(HashTable* table, void* key, void* value);
70 |
71 | int ht_contains(HashTable* table, void* key);
72 | void* ht_lookup(HashTable* table, void* key);
73 | const void* ht_const_lookup(const HashTable* table, void* key);
74 |
75 | #define HT_LOOKUP_AS(type, table_pointer, key_pointer) \
76 | (*(type*)ht_lookup((table_pointer), (key_pointer)))
77 |
78 | int ht_erase(HashTable* table, void* key);
79 | int ht_clear(HashTable* table);
80 |
81 | int ht_is_empty(HashTable* table);
82 | bool ht_is_initialized(HashTable* table);
83 |
84 | int ht_reserve(HashTable* table, size_t minimum_capacity);
85 |
86 | /****************** PRIVATE ******************/
87 |
88 | void _ht_int_swap(size_t* first, size_t* second);
89 | void _ht_pointer_swap(void** first, void** second);
90 |
91 | size_t _ht_default_hash(void* key, size_t key_size);
92 | int _ht_default_compare(void* first_key, void* second_key, size_t key_size);
93 |
94 | size_t _ht_hash(const HashTable* table, void* key);
95 | bool _ht_equal(const HashTable* table, void* first_key, void* second_key);
96 |
97 | bool _ht_should_grow(HashTable* table);
98 | bool _ht_should_shrink(HashTable* table);
99 |
100 | HTNode* _ht_create_node(HashTable* table, void* key, void* value, HTNode* next);
101 | int _ht_push_front(HashTable* table, size_t index, void* key, void* value);
102 | void _ht_destroy_node(HTNode* node);
103 |
104 | int _ht_adjust_capacity(HashTable* table);
105 | int _ht_allocate(HashTable* table, size_t capacity);
106 | int _ht_resize(HashTable* table, size_t new_capacity);
107 | void _ht_rehash(HashTable* table, HTNode** old, size_t old_capacity);
108 |
109 | #endif /* HASHTABLE_H */
110 |
--------------------------------------------------------------------------------
/src/utils.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 |
22 | #include "utils.h"
23 |
24 | static int base64_map(char c) {
25 | if(c >= '0' && c <= '9')
26 | return c + 4;
27 | if(c >= 'A' && c <= 'Z')
28 | return c - 'A';
29 | if(c >= 'a' && c <= 'z')
30 | return c - 'a' + 26;
31 | if(c == '+')
32 | return 62;
33 | if(c == '/')
34 | return 63;
35 | return 0;
36 | }
37 |
38 | // works in place
39 | int base64_decode(char* data, int len) {
40 | assert(data && len > 0);
41 |
42 | int buffer = 0;
43 | int buffer_len = 0;
44 | int data_index = 0;
45 | int out_index = 0;
46 | for(int k = 0; k < len; k++) {
47 | if(buffer_len + 6 < sizeof(int) * 8 && data[data_index] != '=') {
48 | buffer <<= 6;
49 | buffer |= base64_map(data[data_index++]);
50 | buffer_len += 6;
51 | }
52 | for(int b = 0; b < buffer_len / 8; b++) {
53 | data[out_index++] = (buffer >> (buffer_len - 8));
54 | buffer_len -= 8;
55 | }
56 | }
57 | return out_index;
58 | }
59 |
60 | int int_cmp(void* first_key, void* second_key, size_t key_size) {
61 | assert(first_key && second_key);
62 |
63 | return (*(uint32_t*)first_key) != (*(uint32_t*)second_key);
64 | }
65 |
66 | size_t int_hash(void* raw_key, size_t key_size) {
67 | assert(raw_key);
68 |
69 | uint32_t x = *(uint32_t*)raw_key;
70 | x = ((x >> 16) ^ x) * 0x45d9f3b;
71 | x = ((x >> 16) ^ x) * 0x45d9f3b;
72 | x = (x >> 16) ^ x;
73 | return x;
74 | }
75 |
76 | void ht_iterate_remove(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user)) {
77 | assert(ht && callback);
78 |
79 | bool removed = false;
80 |
81 | for(size_t chain = 0; chain < ht->capacity; chain++) {
82 | HTNode* node = ht->nodes[chain];
83 | HTNode* prev = NULL;
84 |
85 | while(node) {
86 | if(callback(node->key, node->value, user)) {
87 | if(prev) {
88 | prev->next = node->next;
89 | } else {
90 | ht->nodes[chain] = node->next;
91 | }
92 |
93 | HTNode* del = node;
94 | node = node->next;
95 |
96 | _ht_destroy_node(del);
97 |
98 | ht->size--;
99 | removed = true;
100 | } else {
101 | prev = node;
102 | node = node->next;
103 | }
104 | }
105 | }
106 |
107 | if(removed && _ht_should_shrink(ht))
108 | _ht_adjust_capacity(ht);
109 | }
110 |
111 | bool ht_iterate(HashTable* ht, void* user, bool (*callback)(void* key, void* value, void* user)) {
112 | assert(ht && callback);
113 |
114 | for(size_t chain = 0; chain < ht->capacity; chain++) {
115 | HTNode* node = ht->nodes[chain];
116 |
117 | while(node) {
118 | if(!callback(node->key, node->value, user))
119 | return true;
120 | node = node->next;
121 | }
122 | }
123 |
124 | return false;
125 | }
126 |
--------------------------------------------------------------------------------
/src/sound.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef SOUND_H
21 | #define SOUND_H
22 |
23 | #ifdef USE_SOUND
24 | #if __APPLE__
25 | #include
26 | #include
27 | #else
28 | #include
29 | #include
30 | #endif
31 | #endif
32 |
33 | #include "player.h"
34 |
35 | #define SOUND_SCALE 0.6F
36 |
37 | enum sound_space {
38 | SOUND_WORLD,
39 | SOUND_LOCAL,
40 | };
41 |
42 | extern int sound_enabled;
43 |
44 | struct Sound_wav {
45 | int openal_buffer;
46 | float min, max;
47 | };
48 |
49 | extern struct Sound_wav sound_footstep1;
50 | extern struct Sound_wav sound_footstep2;
51 | extern struct Sound_wav sound_footstep3;
52 | extern struct Sound_wav sound_footstep4;
53 |
54 | extern struct Sound_wav sound_wade1;
55 | extern struct Sound_wav sound_wade2;
56 | extern struct Sound_wav sound_wade3;
57 | extern struct Sound_wav sound_wade4;
58 |
59 | extern struct Sound_wav sound_jump;
60 | extern struct Sound_wav sound_jump_water;
61 |
62 | extern struct Sound_wav sound_land;
63 | extern struct Sound_wav sound_land_water;
64 |
65 | extern struct Sound_wav sound_hurt_fall;
66 |
67 | extern struct Sound_wav sound_explode;
68 | extern struct Sound_wav sound_explode_water;
69 | extern struct Sound_wav sound_grenade_bounce;
70 | extern struct Sound_wav sound_grenade_pin;
71 |
72 | extern struct Sound_wav sound_pickup;
73 | extern struct Sound_wav sound_horn;
74 |
75 | extern struct Sound_wav sound_rifle_shoot;
76 | extern struct Sound_wav sound_rifle_reload;
77 | extern struct Sound_wav sound_smg_shoot;
78 | extern struct Sound_wav sound_smg_reload;
79 | extern struct Sound_wav sound_shotgun_shoot;
80 | extern struct Sound_wav sound_shotgun_reload;
81 | extern struct Sound_wav sound_shotgun_cock;
82 |
83 | extern struct Sound_wav sound_hitground;
84 | extern struct Sound_wav sound_hitplayer;
85 | extern struct Sound_wav sound_build;
86 |
87 | extern struct Sound_wav sound_spade_woosh;
88 | extern struct Sound_wav sound_spade_whack;
89 |
90 | extern struct Sound_wav sound_death;
91 | extern struct Sound_wav sound_beep1;
92 | extern struct Sound_wav sound_beep2;
93 | extern struct Sound_wav sound_chat;
94 | extern struct Sound_wav sound_switch;
95 | extern struct Sound_wav sound_empty;
96 | extern struct Sound_wav sound_intro;
97 |
98 | extern struct Sound_wav sound_debris;
99 | extern struct Sound_wav sound_bounce;
100 | extern struct Sound_wav sound_impact;
101 |
102 | void sound_volume(float vol);
103 | void sound_create_sticky(struct Sound_wav* w, struct Player* player, int player_id);
104 | void sound_create(enum sound_space option, struct Sound_wav* w, float x, float y, float z);
105 | void sound_update(void);
106 | void sound_load(struct Sound_wav* wav, char* name, float min, float max);
107 | void sound_init(void);
108 |
109 | #endif
110 |
--------------------------------------------------------------------------------
/src/window.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef WINDOW_H
21 | #define WINDOW_H
22 |
23 | #include "common.h"
24 | #include
25 |
26 | struct window_instance {
27 | void* impl;
28 | };
29 |
30 | enum {
31 | WINDOW_PRESS,
32 | WINDOW_RELEASE,
33 | WINDOW_REPEAT,
34 | };
35 |
36 | enum {
37 | TOUCH_DOWN,
38 | TOUCH_MOVE,
39 | TOUCH_UP,
40 | };
41 |
42 | enum window_keys {
43 | WINDOW_KEY_UNKNOWN,
44 | WINDOW_KEY_UP,
45 | WINDOW_KEY_DOWN,
46 | WINDOW_KEY_LEFT,
47 | WINDOW_KEY_RIGHT,
48 | WINDOW_KEY_SNEAK,
49 | WINDOW_KEY_CROUCH,
50 | WINDOW_KEY_SPRINT,
51 | WINDOW_KEY_SPACE,
52 | WINDOW_KEY_CURSOR_UP,
53 | WINDOW_KEY_CURSOR_DOWN,
54 | WINDOW_KEY_CURSOR_LEFT,
55 | WINDOW_KEY_CURSOR_RIGHT,
56 | WINDOW_KEY_TAB,
57 | WINDOW_KEY_ESCAPE,
58 | WINDOW_KEY_YES,
59 | WINDOW_KEY_NO,
60 | WINDOW_KEY_RELOAD,
61 | WINDOW_KEY_TOOL1,
62 | WINDOW_KEY_TOOL2,
63 | WINDOW_KEY_TOOL3,
64 | WINDOW_KEY_TOOL4,
65 | WINDOW_KEY_PICKCOLOR,
66 | WINDOW_KEY_CHAT,
67 | WINDOW_KEY_F1,
68 | WINDOW_KEY_F2,
69 | WINDOW_KEY_F3,
70 | WINDOW_KEY_F4,
71 | WINDOW_KEY_CHANGETEAM,
72 | WINDOW_KEY_CHANGEWEAPON,
73 | WINDOW_KEY_ENTER,
74 | WINDOW_KEY_BACKSPACE,
75 | WINDOW_KEY_MAP,
76 | WINDOW_KEY_VOLUME_UP,
77 | WINDOW_KEY_VOLUME_DOWN,
78 | WINDOW_KEY_V,
79 | WINDOW_KEY_FULLSCREEN,
80 | WINDOW_KEY_SCREENSHOT,
81 | WINDOW_KEY_COMMAND,
82 | WINDOW_KEY_HIDEHUD,
83 | WINDOW_KEY_LASTTOOL,
84 | WINDOW_KEY_NETWORKSTATS,
85 | WINDOW_KEY_SHIFT,
86 | WINDOW_KEY_SAVE_MAP,
87 | WINDOW_KEY_SELECT1,
88 | WINDOW_KEY_SELECT2,
89 | WINDOW_KEY_SELECT3,
90 | WINDOW_KEY_HISTORY_PREVIOUS,
91 | WINDOW_KEY_HISTORY_NEXT,
92 | WINDOW_KEY_YCLAMP,
93 | WINDOW_KEY_SWITCH_CAMERA,
94 | WINDOW_KEY_NEXT_PLAYER
95 | };
96 |
97 | enum {
98 | WINDOW_CURSOR_DISABLED,
99 | WINDOW_CURSOR_ENABLED,
100 | };
101 |
102 | enum window_buttons {
103 | WINDOW_MOUSE_LMB,
104 | WINDOW_MOUSE_MMB,
105 | WINDOW_MOUSE_RMB,
106 | };
107 |
108 | struct window_finger {
109 | #ifdef USE_SDL
110 | SDL_FingerID finger;
111 | #else
112 | int finger;
113 | #endif
114 | float down_time;
115 | int full;
116 | struct {
117 | float x, y;
118 | } start;
119 | };
120 |
121 | extern int window_pressed_keys[64];
122 |
123 | #define WINDOW_NOMOUSELOC -1
124 |
125 | void window_textinput(int allow);
126 | float window_time(void);
127 | void window_keyname(int keycode, char* output, size_t length);
128 | const char* window_clipboard(void);
129 | int window_key_down(int key);
130 | void window_mousemode(int mode);
131 | void window_mouseloc(double* x, double* y);
132 | void window_setmouseloc(double x, double y);
133 | void window_swapping(int value);
134 | void window_init(void);
135 | void window_fromsettings(void);
136 | void window_deinit(void);
137 | void window_update(void);
138 | int window_closed(void);
139 | int window_cpucores();
140 | void window_title(char* suffix);
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/src/texture.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef TEXTURE_H
21 | #define TEXTURE_H
22 |
23 | struct texture {
24 | int width, height;
25 | int texture_id;
26 | unsigned char* pixels;
27 | };
28 |
29 | extern struct texture texture_splash;
30 | extern struct texture texture_splash_icon;
31 | extern struct texture texture_minimap;
32 | extern struct texture texture_gradient;
33 | extern struct texture texture_dummy;
34 |
35 | extern struct texture texture_health;
36 | extern struct texture texture_block;
37 | extern struct texture texture_grenade;
38 | extern struct texture texture_ammo_semi;
39 | extern struct texture texture_ammo_smg;
40 | extern struct texture texture_ammo_shotgun;
41 |
42 | extern struct texture texture_color_selection;
43 |
44 | extern struct texture texture_zoom_semi;
45 | extern struct texture texture_zoom_smg;
46 | extern struct texture texture_zoom_shotgun;
47 |
48 | extern struct texture texture_white;
49 | extern struct texture texture_loader;
50 | extern struct texture texture_target;
51 | extern struct texture texture_indicator;
52 |
53 | extern struct texture texture_player;
54 | extern struct texture texture_medical;
55 | extern struct texture texture_intel;
56 | extern struct texture texture_command;
57 | extern struct texture texture_tracer;
58 |
59 | extern struct texture texture_ui_exit;
60 | extern struct texture texture_ui_wait;
61 | extern struct texture texture_ui_join;
62 | extern struct texture texture_ui_reload;
63 | extern struct texture texture_ui_bg;
64 | extern struct texture texture_ui_input;
65 | extern struct texture texture_ui_box_empty;
66 | extern struct texture texture_ui_box_check;
67 | extern struct texture texture_ui_expanded;
68 | extern struct texture texture_ui_collapsed;
69 | extern struct texture texture_ui_flags;
70 | extern struct texture texture_ui_alert;
71 | extern struct texture texture_ui_joystick;
72 | extern struct texture texture_ui_knob;
73 |
74 | #define TEXTURE_FILTER_NEAREST 0
75 | #define TEXTURE_FILTER_LINEAR 1
76 |
77 | int texture_flag_index(const char* country);
78 | void texture_flag_offset(int index, float* u, float* v);
79 | void texture_filter(struct texture* t, int filter);
80 | void texture_init(void);
81 | int texture_create(struct texture* t, char* filename);
82 | int texture_create_buffer(struct texture* t, int width, int height, unsigned char* buff, int new);
83 | void texture_delete(struct texture* t);
84 | void texture_draw(struct texture* t, float x, float y, float w, float h);
85 | void texture_draw_shadow(struct texture* t, float x, float y, float w, float h);
86 | void texture_draw_sector(struct texture* t, float x, float y, float w, float h, float u, float v, float us, float vs);
87 | void texture_draw_empty(float x, float y, float w, float h);
88 | void texture_draw_empty_rotated(float x, float y, float w, float h, float angle);
89 | void texture_draw_rotated(struct texture* t, float x, float y, float w, float h, float angle);
90 | void texture_resize_pow2(struct texture* t, int min_size);
91 | unsigned int texture_block_color(int x, int y);
92 | void texture_gradient_fog(unsigned int* gradient);
93 |
94 | #endif
95 |
--------------------------------------------------------------------------------
/src/matrix.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "common.h"
25 | #include "matrix.h"
26 |
27 | mat4 matrix_view;
28 | mat4 matrix_model;
29 | mat4 matrix_projection;
30 |
31 | #define MATRIX_STACK_DEPTH 8
32 |
33 | mat4 matrix_stack[MATRIX_STACK_DEPTH];
34 | int matrix_stack_index = 0;
35 |
36 | void matrix_multiply(mat4 m, mat4 n) {
37 | glmc_mat4_mul(n, m, m);
38 | }
39 |
40 | void matrix_load(mat4 m, mat4 n) {
41 | glmc_mat4_copy(n, m);
42 | }
43 |
44 | void matrix_rotate(mat4 m, float angle, float x, float y, float z) {
45 | glmc_rotate(m, angle / 180.0F * GLM_PI, (vec3) {x, y, z});
46 | }
47 |
48 | void matrix_translate(mat4 m, float x, float y, float z) {
49 | glmc_translate(m, (vec3) {x, y, z});
50 | }
51 |
52 | void matrix_scale3(mat4 m, float s) {
53 | glmc_scale_uni(m, s);
54 | }
55 |
56 | void matrix_scale(mat4 m, float sx, float sy, float sz) {
57 | glmc_scale(m, (vec3) {sx, sy, sz});
58 | }
59 |
60 | void matrix_identity(mat4 m) {
61 | glmc_mat4_identity(m);
62 | }
63 |
64 | void matrix_push(mat4 m) {
65 | if(matrix_stack_index >= MATRIX_STACK_DEPTH) {
66 | log_fatal("Matrix stack overflow!");
67 | return;
68 | }
69 |
70 | glmc_mat4_copy(m, matrix_stack[matrix_stack_index++]);
71 | }
72 |
73 | void matrix_pop(mat4 m) {
74 | if(matrix_stack_index < 1) {
75 | log_fatal("Matrix stack underflow!");
76 | return;
77 | }
78 |
79 | glmc_mat4_copy(matrix_stack[--matrix_stack_index], m);
80 | }
81 |
82 | void matrix_vector(mat4 m, vec4 v) {
83 | glmc_mat4_mulv(m, v, v);
84 |
85 | v[0] /= v[3];
86 | v[1] /= v[3];
87 | v[2] /= v[3];
88 | }
89 |
90 | void matrix_pointAt(mat4 m, float dx, float dy, float dz) {
91 | float l = sqrt(dx * dx + dy * dy + dz * dz);
92 | if(l) {
93 | dx /= l;
94 | dy /= l;
95 | dz /= l;
96 | }
97 | float rx = -atan2(dz, dx) * GLM_1_PI * 180.0F;
98 | matrix_rotate(m, rx, 0.0F, 1.0F, 0.0F);
99 | if(dy) {
100 | float ry = asin(dy) * GLM_1_PI * 180.0F;
101 | matrix_rotate(m, ry, 0.0F, 0.0F, 1.0F);
102 | }
103 | }
104 |
105 | void matrix_ortho(mat4 m, float left, float right, float bottom, float top, float nearv, float farv) {
106 | glmc_ortho(left, right, bottom, top, nearv, farv, m);
107 | }
108 |
109 | void matrix_perspective(mat4 m, float fovy, float aspect, float zNear, float zFar) {
110 | glmc_perspective(fovy / 180.0F * GLM_PI, aspect, zNear, zFar, m);
111 | }
112 |
113 | void matrix_lookAt(mat4 m, double eyex, double eyey, double eyez, double centerx, double centery, double centerz,
114 | double upx, double upy, double upz) {
115 | glmc_lookat((vec3) {eyex, eyey, eyez}, (vec3) {centerx, centery, centerz}, (vec3) {upx, upy, upz}, m);
116 | // matrix_translate(-eyex, -eyey, -eyez);
117 | }
118 |
119 | void matrix_upload() {
120 | glMatrixMode(GL_MODELVIEW);
121 | glLoadMatrixf((float*)matrix_view);
122 | glMultMatrixf((float*)matrix_model);
123 | }
124 |
125 | void matrix_upload_p() {
126 | glMatrixMode(GL_PROJECTION);
127 | glLoadMatrixf((float*)matrix_projection);
128 | }
129 |
--------------------------------------------------------------------------------
/src/aabb.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "common.h"
25 | #include "map.h"
26 | #include "aabb.h"
27 | #include "tesselator.h"
28 | #include "matrix.h"
29 |
30 | void aabb_render(AABB* a) { }
31 |
32 | // see: https://tavianator.com/2011/ray_box.html
33 | bool aabb_intersection_ray(AABB* a, Ray* r, float* distance) {
34 | double inv_x = 1.0 / r->direction.x;
35 | double tx1 = (a->min_x - r->origin.x) * inv_x;
36 | double tx2 = (a->max_x - r->origin.x) * inv_x;
37 |
38 | double tmin = fmin(tx1, tx2);
39 | double tmax = fmax(tx1, tx2);
40 |
41 | double inv_y = 1.0 / r->direction.y;
42 | double ty1 = (a->min_y - r->origin.y) * inv_y;
43 | double ty2 = (a->max_y - r->origin.y) * inv_y;
44 |
45 | tmin = fmax(tmin, fmin(fmin(ty1, ty2), tmax));
46 | tmax = fmin(tmax, fmax(fmax(ty1, ty2), tmin));
47 |
48 | double inv_z = 1.0 / r->direction.z;
49 | double tz1 = (a->min_z - r->origin.z) * inv_z;
50 | double tz2 = (a->max_z - r->origin.z) * inv_z;
51 |
52 | tmin = fmax(tmin, fmin(fmin(tz1, tz2), tmax));
53 | tmax = fmin(tmax, fmax(fmax(tz1, tz2), tmin));
54 |
55 | if(distance)
56 | *distance = fmax(tmin, 0.0) * len3D(r->direction.x, r->direction.y, r->direction.z);
57 |
58 | return tmax > fmax(tmin, 0.0);
59 | }
60 |
61 | void aabb_set_center(AABB* a, float x, float y, float z) {
62 | float size_x = a->max_x - a->min_x;
63 | float size_y = a->max_y - a->min_y;
64 | float size_z = a->max_z - a->min_z;
65 |
66 | a->min_x = x - size_x / 2;
67 | a->min_y = y - size_y / 2;
68 | a->min_z = z - size_z / 2;
69 | a->max_x = x + size_x / 2;
70 | a->max_y = y + size_y / 2;
71 | a->max_z = z + size_z / 2;
72 | }
73 |
74 | void aabb_set_size(AABB* a, float x, float y, float z) {
75 | a->max_x = a->min_x + x;
76 | a->max_y = a->min_y + y;
77 | a->max_z = a->min_z + z;
78 | }
79 |
80 | bool aabb_intersection(AABB* a, AABB* b) {
81 | return (a->min_x <= b->max_x && b->min_x <= a->max_x) && (a->min_y <= b->max_y && b->min_y <= a->max_y)
82 | && (a->min_z <= b->max_z && b->min_z <= a->max_z);
83 | }
84 |
85 | bool aabb_intersection_terrain(AABB* a, int miny) {
86 | AABB terrain_cube;
87 |
88 | int min_x = min(max(floor(a->min_x) - 1, 0), map_size_x);
89 | int min_y = min(max(floor(a->min_y) - 1, miny), map_size_y);
90 | int min_z = min(max(floor(a->min_z) - 1, 0), map_size_z);
91 |
92 | int max_x = min(max(ceil(a->max_x) + 1, 0), map_size_x);
93 | int max_y = min(max(ceil(a->max_y) + 1, 0), map_size_y);
94 | int max_z = min(max(ceil(a->max_z) + 1, 0), map_size_z);
95 |
96 | for(int x = min_x; x < max_x; x++) {
97 | for(int z = min_z; z < max_z; z++) {
98 | for(int y = min_y; y < max_y; y++) {
99 | if(!map_isair(x, y, z)) {
100 | terrain_cube.min_x = x;
101 | terrain_cube.min_y = y;
102 | terrain_cube.min_z = z;
103 | terrain_cube.max_x = x + 1;
104 | terrain_cube.max_y = y + 1;
105 | terrain_cube.max_z = z + 1;
106 |
107 | if(aabb_intersection(a, &terrain_cube))
108 | return true;
109 | }
110 | }
111 | }
112 | }
113 |
114 | return false;
115 | }
116 |
--------------------------------------------------------------------------------
/src/rpc.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 |
22 | #ifdef USE_RPC
23 | #include
24 | #endif
25 |
26 | #include "common.h"
27 | #include "log.h"
28 | #include "player.h"
29 | #include "rpc.h"
30 |
31 | struct rpc {
32 | int needs_update;
33 | int players;
34 | int slots;
35 | char server_url[64];
36 | char server_name[64];
37 | } rpc_state;
38 |
39 | #ifdef USE_RPC
40 | static void rpc_joingame(const char* joinSecret) {
41 | log_info("discord join %s!", joinSecret);
42 | }
43 |
44 | static void rpc_joinrequest(const DiscordUser* request) {
45 | Discord_Respond(request->userId, DISCORD_REPLY_YES);
46 | }
47 | #endif
48 |
49 | void rpc_init() {
50 | #ifdef USE_RPC
51 | DiscordEventHandlers handlers;
52 | memset(&handlers, 0, sizeof(handlers));
53 | handlers.joinGame = rpc_joingame;
54 | handlers.joinRequest = rpc_joinrequest;
55 | Discord_Initialize("DISCORD TOKEN HERE", &handlers, 1, NULL);
56 | #endif
57 | rpc_state.needs_update = 1;
58 | rpc_state.players = 0;
59 | rpc_state.slots = 0;
60 | *rpc_state.server_url = 0;
61 | *rpc_state.server_name = 0;
62 | }
63 |
64 | void rpc_deinit() {
65 | #ifdef USE_RPC
66 | Discord_Shutdown();
67 | #endif
68 | }
69 |
70 | void rpc_setv(enum RPC_VALUE v, char* x) {
71 | switch(v) {
72 | case RPC_VALUE_SERVERNAME:
73 | if(strcmp(rpc_state.server_name, x) != 0) {
74 | strncpy(rpc_state.server_name, x, sizeof(rpc_state.server_name) - 1);
75 | rpc_state.needs_update = 1;
76 | }
77 | break;
78 | case RPC_VALUE_SERVERURL:
79 | if(strcmp(rpc_state.server_url, x) != 0) {
80 | strncpy(rpc_state.server_url, x, sizeof(rpc_state.server_url) - 1);
81 | rpc_state.needs_update = 1;
82 | }
83 | break;
84 | }
85 | }
86 |
87 | void rpc_seti(enum RPC_VALUE v, int x) {
88 | switch(v) {
89 | case RPC_VALUE_PLAYERS:
90 | if(rpc_state.players != x) {
91 | rpc_state.players = x;
92 | rpc_state.needs_update = 1;
93 | }
94 | break;
95 | case RPC_VALUE_SLOTS:
96 | if(rpc_state.slots != x) {
97 | rpc_state.slots = x;
98 | rpc_state.needs_update = 1;
99 | }
100 | break;
101 | }
102 | }
103 |
104 | void rpc_update() {
105 | #ifdef USE_RPC
106 |
107 | int online = 0;
108 | for(int k = 0; k < PLAYERS_MAX; k++) {
109 | if(players[k].connected)
110 | online++;
111 | }
112 | rpc_seti(RPC_VALUE_PLAYERS, online);
113 |
114 | if(rpc_state.needs_update) {
115 | DiscordRichPresence discordPresence;
116 | memset(&discordPresence, 0, sizeof(discordPresence));
117 | discordPresence.largeImageKey = "pic03";
118 | discordPresence.smallImageKey = "logo";
119 | discordPresence.smallImageText = BETTERSPADES_VERSION;
120 | discordPresence.instance = 1;
121 | if(rpc_state.slots > 0) {
122 | discordPresence.state = "Playing";
123 | discordPresence.partyId = "42";
124 | discordPresence.partySize = max(rpc_state.players, 1);
125 | discordPresence.partyMax = rpc_state.slots;
126 | discordPresence.details = rpc_state.server_name;
127 | discordPresence.joinSecret = rpc_state.server_url;
128 | } else {
129 | discordPresence.state = "Waiting";
130 | }
131 | Discord_UpdatePresence(&discordPresence);
132 | rpc_state.needs_update = 0;
133 | }
134 |
135 | Discord_UpdateConnection();
136 | Discord_RunCallbacks();
137 | #endif
138 | }
139 |
--------------------------------------------------------------------------------
/src/common.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef COMMON_H
21 | #define COMMON_H
22 |
23 | #ifndef OPENGL_ES
24 | #define GLEW_STATIC
25 | #include
26 | #else
27 | #ifdef USE_SDL
28 | #include
29 | #endif
30 | #define glColor3f(r, g, b) glColor4f(r, g, b, 1.0F)
31 | #define glColor3ub(r, g, b) glColor4ub(r, g, b, 255)
32 | #define glDepthRange(a, b) glDepthRangef(a, b)
33 | #define glClearDepth(a) glClearDepthf(a)
34 | #endif
35 |
36 | #ifdef USE_GLFW
37 | #include
38 | #endif
39 |
40 | #ifdef USE_SDL
41 | #define SDL_MAIN_HANDLED
42 | #include
43 | #endif
44 |
45 | #ifdef USE_RPC
46 | #include
47 | #endif
48 |
49 | #ifdef _WIN32
50 | #define OS_WINDOWS
51 | #endif
52 |
53 | #ifdef __linux__
54 | #define OS_LINUX
55 | #include
56 | #endif
57 |
58 | #ifdef __APPLE__
59 | #define OS_APPLE
60 | #endif
61 |
62 | #ifdef __HAIKU__
63 | #define OS_HAIKU
64 | #endif
65 |
66 | #ifndef min
67 | #define min(a, b) ((a) < (b) ? (a) : (b))
68 | #endif
69 | #ifndef max
70 | #define max(a, b) ((a) > (b) ? (a) : (b))
71 | #endif
72 |
73 | #define absf(a) (((a) > 0) ? (a) : -(a))
74 |
75 | #define distance2D(x1, y1, x2, y2) (((x2) - (x1)) * ((x2) - (x1)) + ((y2) - (y1)) * ((y2) - (y1)))
76 | #define distance3D(x1, y1, z1, x2, y2, z2) \
77 | (((x2) - (x1)) * ((x2) - (x1)) + ((y2) - (y1)) * ((y2) - (y1)) + ((z2) - (z1)) * ((z2) - (z1)))
78 | #define angle3D(x1, y1, z1, x2, y2, z2) acos((x1) * (x2) + (y1) * (y2) + (z1) * (z2)) // vectors should be normalized
79 | #define len2D(x, y) sqrt(pow(x, 2) + pow(y, 2))
80 | #define len3D(x, y, z) sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2))
81 |
82 | #define rgba(r, g, b, a) (((int)(a) << 24) | ((int)(b) << 16) | ((int)(g) << 8) | (int)(r))
83 | #define rgb(r, g, b) (((b) << 16) | ((g) << 8) | (r))
84 | #define rgb2bgr(col) rgb(blue(col), green(col), red(col))
85 | #define red(col) ((col)&0xFF)
86 | #define green(col) (((col) >> 8) & 0xFF)
87 | #define blue(col) (((col) >> 16) & 0xFF)
88 | #define alpha(col) (((col) >> 24) & 0xFF)
89 |
90 | #define PI 3.1415F
91 | #define DOUBLEPI (PI * 2.0F)
92 | #define HALFPI (PI * 0.5F)
93 | #define EPSILON 0.005F
94 |
95 | #define MOUSE_SENSITIVITY 0.002F
96 |
97 | #define CHAT_NO_INPUT 0
98 | #define CHAT_ALL_INPUT 1
99 | #define CHAT_TEAM_INPUT 2
100 |
101 | extern int chat_input_mode;
102 | extern float last_cy;
103 |
104 | extern int fps;
105 |
106 | extern char chat[3][128][256];
107 | extern unsigned int chat_color[3][128];
108 | extern float chat_timer[3][128];
109 | extern unsigned int chat_history_pos;
110 | extern char chat_popup[256];
111 | extern float chat_popup_timer;
112 | extern float chat_popup_duration;
113 | extern int chat_popup_color;
114 | void chat_add(int channel, unsigned int color, const char* msg);
115 | void chat_clear(int channel);
116 | void chat_showpopup(const char* msg, float duration, int color);
117 | const char* reason_disconnect(int code);
118 |
119 | #define SCREEN_NONE 0
120 | #define SCREEN_TEAM_SELECT 1
121 | #define SCREEN_GUN_SELECT 2
122 |
123 | extern int ms_seed;
124 | int ms_rand(void);
125 |
126 | #include
127 | #include "log.h"
128 |
129 | #define CHECK_ALLOCATION_ERROR(ret) \
130 | if(!ret) { \
131 | log_fatal("Critical error: memory allocation failed (%s:%d)", __func__, __LINE__); \
132 | exit(1); \
133 | }
134 |
135 | #endif
136 |
--------------------------------------------------------------------------------
/src/minheap.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include "minheap.h"
27 |
28 | static void nodes_swap(struct minheap* h, int a, int b) {
29 | struct minheap_block tmp;
30 | tmp = h->nodes[a];
31 | h->nodes[a] = h->nodes[b];
32 | h->nodes[b] = tmp;
33 | }
34 |
35 | void minheap_create(struct minheap* h) {
36 | h->index = 0;
37 | h->length = 256;
38 | h->nodes = malloc(sizeof(struct minheap_block) * h->length);
39 | }
40 |
41 | void minheap_clear(struct minheap* h) {
42 | h->index = 0;
43 | h->length = 256;
44 | h->nodes = realloc(h->nodes, sizeof(struct minheap_block) * h->length);
45 | }
46 |
47 | void minheap_destroy(struct minheap* h) {
48 | free(h->nodes);
49 | }
50 |
51 | int minheap_isempty(struct minheap* h) {
52 | return h->index <= 0;
53 | }
54 |
55 | struct minheap_block minheap_extract(struct minheap* h) {
56 | struct minheap_block min = h->nodes[0];
57 |
58 | h->nodes[0] = h->nodes[--h->index];
59 |
60 | // now heapify at root node
61 | int k = 0;
62 | while(1) {
63 | int smallest = k;
64 | if(k * 2 + 1 < h->index
65 | && pos_keyy(h->nodes[k * 2 + 1].pos)
66 | < pos_keyy(h->nodes[smallest].pos)) // does left child exist and is less than parent?
67 | smallest = k * 2 + 1;
68 | if(k * 2 + 2 < h->index
69 | && pos_keyy(h->nodes[k * 2 + 2].pos)
70 | < pos_keyy(h->nodes[smallest].pos)) // does right child exist and is less than parent?
71 | smallest = k * 2 + 2;
72 | if(smallest == k) // parent is smallest, finished!
73 | break;
74 | nodes_swap(h, k, smallest);
75 | k = smallest;
76 | }
77 |
78 | return min;
79 | }
80 |
81 | static void minheap_increase(struct minheap* h, struct minheap_block* b, int value) {
82 | b->pos = pos_key(pos_keyx(b->pos), value, pos_keyy(b->pos));
83 |
84 | int k = b - h->nodes;
85 | while(1) {
86 | int smallest = k;
87 | if(k * 2 + 1 < h->index
88 | && pos_keyy(h->nodes[k * 2 + 1].pos)
89 | < pos_keyy(h->nodes[smallest].pos)) // does left child exist and is less than parent?
90 | smallest = k * 2 + 1;
91 | if(k * 2 + 2 < h->index
92 | && pos_keyy(h->nodes[k * 2 + 2].pos)
93 | < pos_keyy(h->nodes[smallest].pos)) // does right child exist and is less than parent?
94 | smallest = k * 2 + 2;
95 | if(smallest == k) // parent is smallest, finished!
96 | break;
97 | nodes_swap(h, k, smallest);
98 | k = smallest;
99 | }
100 | }
101 |
102 | static void minheap_decrease(struct minheap* h, struct minheap_block* b, int value) {
103 | b->pos = pos_key(pos_keyx(b->pos), value, pos_keyy(b->pos));
104 |
105 | int k = b - h->nodes;
106 | while(k > 0) {
107 | if(pos_keyy(h->nodes[k].pos) < pos_keyy(h->nodes[(k - 1) / 2].pos)) { // is child less than parent?
108 | nodes_swap(h, k, (k - 1) / 2);
109 | k = (k - 1) / 2; // continue at parent
110 | } else {
111 | break;
112 | }
113 | }
114 | }
115 |
116 | void minheap_set(struct minheap* h, struct minheap_block* b, int value) {
117 | if(value > pos_keyy(b->pos))
118 | minheap_increase(h, b, value);
119 | else
120 | minheap_decrease(h, b, value);
121 | }
122 |
123 | struct minheap_block* minheap_put(struct minheap* h, struct minheap_block* b) {
124 | if(h->index >= h->length) { // grow buffer
125 | h->length *= 2;
126 | h->nodes = realloc(h->nodes, sizeof(struct minheap_block) * h->length);
127 | }
128 |
129 | h->nodes[h->index++] = *b; // place new node at end of heap
130 |
131 | int k = h->index - 1;
132 | while(k > 0) {
133 | if(pos_keyy(h->nodes[k].pos) < pos_keyy(h->nodes[(k - 1) / 2].pos)) { // is child less than parent?
134 | nodes_swap(h, k, (k - 1) / 2);
135 | k = (k - 1) / 2; // continue at parent
136 | } else {
137 | break;
138 | }
139 | }
140 |
141 | return h->nodes + k;
142 | }
143 |
--------------------------------------------------------------------------------
/src/log.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2017 rxi
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to
6 | * deal in the Software without restriction, including without limitation the
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | * sell copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "log.h"
31 |
32 | #ifdef WIN32
33 | #include
34 | #endif
35 |
36 | pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
37 |
38 | static struct {
39 | FILE* fp;
40 | int level;
41 | int quiet;
42 | } L;
43 |
44 | static const char* level_names[] = {
45 | "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
46 | };
47 |
48 | #ifdef LOG_USE_COLOR
49 | #ifdef WIN32
50 | static const WORD level_colors[] = {
51 | 10, 11, 10, 6, 12, 12
52 | };
53 | #else
54 | static const char* level_colors[] = {
55 | "\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m"
56 | };
57 | #endif
58 | #endif
59 |
60 | static void lock(void) {
61 | pthread_mutex_lock(&m);
62 | }
63 |
64 | static void unlock(void) {
65 | pthread_mutex_unlock(&m);
66 | }
67 |
68 | void log_set_fp(FILE* fp) {
69 | L.fp = fp;
70 | }
71 |
72 | void log_set_level(int level) {
73 | L.level = level;
74 | }
75 |
76 | void log_set_quiet(int enable) {
77 | L.quiet = enable ? 1 : 0;
78 | }
79 |
80 | void log_log(int level, const char* file, int line, const char* fmt, ...) {
81 | if(level < L.level)
82 | return;
83 |
84 | /* Get current time */
85 | time_t t = time(NULL);
86 | struct tm* lt = localtime(&t);
87 |
88 | /* Acquire lock */
89 | lock();
90 |
91 | /* Log to stderr */
92 | if(!L.quiet) {
93 | va_list args;
94 | char buf[16];
95 | buf[strftime(buf, sizeof(buf), "%H:%M:%S", lt)] = '\0';
96 |
97 | #ifdef LOG_USE_COLOR
98 | #ifdef WIN32
99 | HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
100 | CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
101 | WORD saved_attributes;
102 |
103 | GetConsoleScreenBufferInfo(hConsole, &consoleInfo);
104 | saved_attributes = consoleInfo.wAttributes;
105 |
106 | // Force set to grey for this purpose, but keep the previous colour settings and revert
107 | // back to them after the logging has completed, since the user who may have changed colours
108 | // for their own logging prior to log_log called
109 | SetConsoleTextAttribute(hConsole, 7);
110 | fprintf(stderr, "%s ", buf);
111 | SetConsoleTextAttribute(hConsole, level_colors[level]);
112 | fprintf(stderr, "%s", level_names[level]);
113 |
114 | if (strlen(level_names[level]) == 5) {
115 | fprintf(stderr, " ");
116 | } else {
117 | fprintf(stderr, " ");
118 | }
119 | SetConsoleTextAttribute(hConsole, 8 /*GREY*/);
120 | fprintf(stderr, "%s:%d: ", file, line);
121 |
122 | // Revert back colour settings
123 | SetConsoleTextAttribute(hConsole, saved_attributes);
124 | #else
125 | fprintf(
126 | stderr, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ",
127 | buf, level_colors[level], level_names[level], file, line);
128 | #endif
129 | #else
130 | fprintf(stderr, "%s %-5s %s:%d: ", buf, level_names[level], file, line);
131 | #endif
132 | va_start(args, fmt);
133 | vfprintf(stderr, fmt, args);
134 | va_end(args);
135 | fprintf(stderr, "\n");
136 | }
137 |
138 | /* Log to file */
139 | if(L.fp) {
140 | va_list args;
141 | char buf[32];
142 | buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", lt)] = '\0';
143 | fprintf(L.fp, "%s %-5s %s:%d: ", buf, level_names[level], file, line);
144 | va_start(args, fmt);
145 | vfprintf(L.fp, fmt, args);
146 | va_end(args);
147 | fprintf(L.fp, "\n");
148 | }
149 |
150 | /* Release lock */
151 | unlock();
152 | }
153 |
--------------------------------------------------------------------------------
/src/tracer.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "common.h"
25 | #include "matrix.h"
26 | #include "window.h"
27 | #include "tracer.h"
28 | #include "model.h"
29 | #include "camera.h"
30 | #include "texture.h"
31 | #include "config.h"
32 | #include "sound.h"
33 | #include "entitysystem.h"
34 |
35 | struct entity_system tracers;
36 |
37 | void tracer_pvelocity(float* o, struct Player* p) {
38 | o[0] = o[0] * 256.0F / 32.0F + p->physics.velocity.x;
39 | o[1] = o[1] * 256.0F / 32.0F + p->physics.velocity.y;
40 | o[2] = o[2] * 256.0F / 32.0F + p->physics.velocity.z;
41 | }
42 |
43 | struct tracer_minimap_info {
44 | int large;
45 | float scalef;
46 | float minimap_x;
47 | float minimap_y;
48 | };
49 |
50 | static bool tracer_minimap_single(void* obj, void* user) {
51 | struct Tracer* t = (struct Tracer*)obj;
52 | struct tracer_minimap_info* info = (struct tracer_minimap_info*)user;
53 |
54 | if(info->large) {
55 | float ang = -atan2(t->r.direction.z, t->r.direction.x) - HALFPI;
56 | texture_draw_rotated(&texture_tracer, info->minimap_x + t->r.origin.x * info->scalef,
57 | info->minimap_y - t->r.origin.z * info->scalef, 15 * info->scalef, 15 * info->scalef, ang);
58 | } else {
59 | float tracer_x = t->r.origin.x - info->minimap_x;
60 | float tracer_y = t->r.origin.z - info->minimap_y;
61 | if(tracer_x > 0.0F && tracer_x < 128.0F && tracer_y > 0.0F && tracer_y < 128.0F) {
62 | float ang = -atan2(t->r.direction.z, t->r.direction.x) - HALFPI;
63 | texture_draw_rotated(&texture_tracer, settings.window_width - 143 * info->scalef + tracer_x * info->scalef,
64 | (585 - tracer_y) * info->scalef, 15 * info->scalef, 15 * info->scalef, ang);
65 | }
66 | }
67 |
68 | return false;
69 | }
70 |
71 | void tracer_minimap(int large, float scalef, float minimap_x, float minimap_y) {
72 | entitysys_iterate(&tracers,
73 | &(struct tracer_minimap_info) {
74 | .large = large,
75 | .scalef = scalef,
76 | .minimap_x = minimap_x,
77 | .minimap_y = minimap_y,
78 | },
79 | tracer_minimap_single);
80 | }
81 |
82 | void tracer_add(int type, float x, float y, float z, float dx, float dy, float dz) {
83 | struct Tracer t = (struct Tracer) {
84 | .type = type,
85 | .x = t.r.origin.x = x + dx / 4.0F,
86 | .y = t.r.origin.y = y + dy / 4.0F,
87 | .z = t.r.origin.z = z + dz / 4.0F,
88 | .r.direction.x = dx,
89 | .r.direction.y = dy,
90 | .r.direction.z = dz,
91 | .created = window_time(),
92 | };
93 |
94 | float len = len3D(dx, dy, dz);
95 | camera_hit(&t.hit, -1, t.x, t.y, t.z, dx / len, dy / len, dz / len, 128.0F);
96 |
97 | entitysys_add(&tracers, &t);
98 | }
99 |
100 | static bool tracer_render_single(void* obj, void* user) {
101 | struct Tracer* t = (struct Tracer*)obj;
102 |
103 | matrix_push(matrix_model);
104 | matrix_translate(matrix_model, t->r.origin.x, t->r.origin.y, t->r.origin.z);
105 | matrix_pointAt(matrix_model, t->r.direction.x, t->r.direction.y, t->r.direction.z);
106 | matrix_rotate(matrix_model, 90.0F, 0.0F, 1.0F, 0.0F);
107 | matrix_upload();
108 | kv6_render(
109 | (struct kv6_t*[]) {
110 | &model_semi_tracer,
111 | &model_smg_tracer,
112 | &model_shotgun_tracer,
113 | }[t->type],
114 | TEAM_SPECTATOR);
115 | matrix_pop(matrix_model);
116 |
117 | return false;
118 | }
119 |
120 | void tracer_render() {
121 | entitysys_iterate(&tracers, NULL, tracer_render_single);
122 | }
123 |
124 | static bool tracer_update_single(void* obj, void* user) {
125 | struct Tracer* t = (struct Tracer*)obj;
126 | float dt = *(float*)user;
127 |
128 | float len = distance3D(t->x, t->y, t->z, t->r.origin.x, t->r.origin.y, t->r.origin.z);
129 |
130 | // 128.0[m] / 256.0[m/s] = 0.5[s]
131 | if((t->hit.type != CAMERA_HITTYPE_NONE && len > pow(t->hit.distance, 2)) || window_time() - t->created > 0.5F) {
132 | if(t->hit.type != CAMERA_HITTYPE_NONE)
133 | sound_create(SOUND_WORLD, &sound_impact, t->r.origin.x, t->r.origin.y, t->r.origin.z);
134 |
135 | return true;
136 | } else {
137 | t->r.origin.x += t->r.direction.x * 32.0F * dt;
138 | t->r.origin.y += t->r.direction.y * 32.0F * dt;
139 | t->r.origin.z += t->r.direction.z * 32.0F * dt;
140 | }
141 |
142 | return false;
143 | }
144 |
145 | void tracer_update(float dt) {
146 | entitysys_iterate(&tracers, &dt, tracer_update_single);
147 | }
148 |
149 | void tracer_init() {
150 | entitysys_create(&tracers, sizeof(struct Tracer), PLAYERS_MAX);
151 | }
152 |
--------------------------------------------------------------------------------
/src/grenade.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 |
22 | #include "window.h"
23 | #include "particle.h"
24 | #include "matrix.h"
25 | #include "model.h"
26 | #include "sound.h"
27 | #include "grenade.h"
28 | #include "map.h"
29 | #include "entitysystem.h"
30 |
31 | struct entity_system grenades;
32 |
33 | void grenade_init() {
34 | entitysys_create(&grenades, sizeof(struct Grenade), 32);
35 | }
36 |
37 | void grenade_add(struct Grenade* g) {
38 | g->created = window_time();
39 |
40 | entitysys_add(&grenades, g);
41 | }
42 |
43 | static int grenade_clipworld(int x, int y, int z) {
44 | if(x < 0)
45 | x += map_size_x;
46 | if(y < 0)
47 | y += map_size_z;
48 | if(x >= map_size_x)
49 | x -= map_size_x;
50 | if(y >= map_size_z)
51 | y -= map_size_z;
52 |
53 | int sz;
54 |
55 | if(z < 0)
56 | return 0;
57 | sz = (int)z;
58 | if(sz == map_size_y - 1)
59 | sz = map_size_y - 2;
60 | else if(sz >= map_size_y - 1)
61 | return 1;
62 | else if(sz < 0)
63 | return 0;
64 | return !map_isair((int)x, (map_size_y - 1) - sz, (int)y);
65 | }
66 |
67 | static int grenade_move(struct Grenade* g, float dt) {
68 | float tmp;
69 | tmp = g->pos.z;
70 | g->pos.z = 63.0F - g->pos.y;
71 | g->pos.y = tmp;
72 | tmp = g->velocity.z;
73 | g->velocity.z = -g->velocity.y;
74 | g->velocity.y = tmp;
75 |
76 | struct Position fpos = g->pos; // old position
77 |
78 | // do velocity & gravity (friction is negligible)
79 | float f = dt * 32.0F;
80 | g->velocity.z += dt;
81 | g->pos.x += g->velocity.x * f;
82 | g->pos.y += g->velocity.y * f;
83 | g->pos.z += g->velocity.z * f;
84 | // do rotation
85 | // FIX ME: Loses orientation after 45 degree bounce off wall
86 | // if(g->v.x > 0.1f || g->v.x < -0.1f || g->v.y > 0.1f || g->v.y < -0.1f)
87 | // {
88 | // f *= -0.5;
89 | // }
90 | // make it bounce (accurate)
91 | int ret = 0;
92 |
93 | int lpx = floor(g->pos.x);
94 | int lpy = floor(g->pos.y);
95 | int lpz = floor(g->pos.z);
96 |
97 | if(grenade_clipworld(lpx, lpy, lpz)) { // hit a wall
98 |
99 | ret = 1;
100 | if(fabs(g->velocity.x) > 0.1F || fabs(g->velocity.y) > 0.1F || fabs(g->velocity.z) > 0.1F)
101 | ret = 2; // play sound
102 |
103 | int lp2x = floor(fpos.x);
104 | int lp2y = floor(fpos.y);
105 | int lp2z = floor(fpos.z);
106 | if(lpz != lp2z && ((lpx == lp2x && lpy == lp2y) || !grenade_clipworld(lpx, lpy, lp2z)))
107 | g->velocity.z *= -1;
108 | else if(lpx != lp2x && ((lpy == lp2y && lpz == lp2z) || !grenade_clipworld(lp2x, lpy, lpz)))
109 | g->velocity.x *= -1;
110 | else if(lpy != lp2y && ((lpx == lp2x && lpz == lp2z) || !grenade_clipworld(lpx, lp2y, lpz)))
111 | g->velocity.y *= -1;
112 | g->pos = fpos; // set back to old position
113 | g->velocity.x *= 0.36F;
114 | g->velocity.y *= 0.36F;
115 | g->velocity.z *= 0.36F;
116 | }
117 |
118 | tmp = g->pos.y;
119 | g->pos.y = 63.0F - g->pos.z;
120 | g->pos.z = tmp;
121 | tmp = g->velocity.y;
122 | g->velocity.y = -g->velocity.z;
123 | g->velocity.z = tmp;
124 |
125 | return ret;
126 | }
127 |
128 | static int grenade_inwater(struct Grenade* g) {
129 | return g->pos.y < 1.0F;
130 | }
131 |
132 | bool grenade_render_single(void* obj, void* user) {
133 | struct Grenade* g = (struct Grenade*)obj;
134 |
135 | // TODO: position grenade on ground properly
136 | matrix_push(matrix_model);
137 | matrix_translate(matrix_model, g->pos.x,
138 | g->pos.y + (model_grenade.zpiv + model_grenade.zsiz * 2) * model_grenade.scale, g->pos.z);
139 | if(fabs(g->velocity.x) > 0.05F || fabs(g->velocity.y) > 0.05F || fabs(g->velocity.z) > 0.05F)
140 | matrix_rotate(matrix_model, -window_time() * 720.0F, -g->velocity.z, 0.0F, g->velocity.x);
141 | matrix_upload();
142 |
143 | kv6_calclight(g->pos.x, g->pos.y, g->pos.z);
144 |
145 | kv6_render(&model_grenade, g->team);
146 | matrix_pop(matrix_model);
147 | return false;
148 | }
149 |
150 | void grenade_render() {
151 | entitysys_iterate(&grenades, NULL, grenade_render_single);
152 | }
153 |
154 | bool grenade_update_single(void* obj, void* user) {
155 | struct Grenade* g = (struct Grenade*)obj;
156 | float dt = *(float*)user;
157 |
158 | if(window_time() - g->created > g->fuse_length) {
159 | sound_create(SOUND_WORLD, grenade_inwater(g) ? &sound_explode_water : &sound_explode, g->pos.x, g->pos.y,
160 | g->pos.z);
161 | particle_create(grenade_inwater(g) ? map_get(g->pos.x, 0, g->pos.z) : 0x505050, g->pos.x, g->pos.y + 1.5F,
162 | g->pos.z, 20.0F, 1.5F, 64, 0.1F, 0.5F);
163 |
164 | return true;
165 | } else {
166 | if(grenade_move(g, dt) == 2)
167 | sound_create(SOUND_WORLD, &sound_grenade_bounce, g->pos.x, g->pos.y, g->pos.z);
168 |
169 | return false;
170 | }
171 | }
172 |
173 | void grenade_update(float dt) {
174 | entitysys_iterate(&grenades, &dt, grenade_update_single);
175 | }
176 |
--------------------------------------------------------------------------------
/src/player.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef PLAYER_H
21 | #define PLAYER_H
22 |
23 | #include
24 |
25 | #include "aabb.h"
26 | #include "network.h"
27 |
28 | #define PLAYERS_MAX 256 // just because 32 players are not enough
29 | #define TEAM_1 0
30 | #define TEAM_2 1
31 | #define TEAM_SPECTATOR 255
32 |
33 | extern struct GameState {
34 | struct Team {
35 | char name[11];
36 | unsigned char red, green, blue;
37 | } team_1;
38 | struct Team team_2;
39 | unsigned char gamemode_type;
40 | union Gamemodes gamemode;
41 | struct {
42 | unsigned char team_capturing, tent;
43 | float progress, rate, update;
44 | } progressbar;
45 | } gamestate;
46 |
47 | #define GAMEMODE_CTF 0
48 | #define GAMEMODE_TC 1
49 |
50 | extern int button_map[3];
51 |
52 | extern unsigned char local_player_id;
53 | extern unsigned char local_player_health;
54 | extern unsigned char local_player_blocks;
55 | extern unsigned char local_player_grenades;
56 | extern unsigned char local_player_ammo, local_player_ammo_reserved;
57 | extern unsigned char local_player_respawn_time;
58 | extern float local_player_death_time;
59 | extern unsigned char local_player_respawn_cnt_last;
60 | extern unsigned char local_player_newteam;
61 | extern unsigned char local_player_lasttool;
62 |
63 | extern float local_player_last_damage_timer;
64 | extern float local_player_last_damage_x;
65 | extern float local_player_last_damage_y;
66 | extern float local_player_last_damage_z;
67 |
68 | extern char local_player_drag_active;
69 | extern int local_player_drag_x;
70 | extern int local_player_drag_y;
71 | extern int local_player_drag_z;
72 |
73 | extern int player_intersection_type;
74 | extern int player_intersection_player;
75 | extern float player_intersection_dist;
76 |
77 | struct player_intersection {
78 | bool head;
79 | bool torso;
80 | bool leg_left;
81 | bool leg_right;
82 | bool arms;
83 | union {
84 | struct {
85 | float head;
86 | float torso;
87 | float leg_left;
88 | float leg_right;
89 | float arms;
90 | };
91 | float values[5];
92 | } distance;
93 | };
94 |
95 | bool player_intersection_exists(struct player_intersection* s);
96 | int player_intersection_choose(struct player_intersection* s, float* distance);
97 |
98 | extern struct Player {
99 | char name[17];
100 | struct Position {
101 | float x, y, z;
102 | } pos;
103 | struct Orientation {
104 | float x, y, z;
105 | } orientation;
106 | AABB bb_2d;
107 | struct Orientation orientation_smooth;
108 | struct Position gun_pos;
109 | struct Position casing_dir;
110 | float gun_shoot_timer;
111 | int ammo, ammo_reserved;
112 | float spade_use_timer;
113 | unsigned char spade_used, spade_use_type;
114 | unsigned int score;
115 | unsigned char team, weapon, held_item;
116 | unsigned char alive, connected;
117 | float item_showup, item_disabled, items_show_start;
118 | unsigned char items_show;
119 | union {
120 | unsigned int packed;
121 | struct {
122 | unsigned char red, green, blue;
123 | };
124 | } block;
125 | struct {
126 | union {
127 | unsigned char packed; // useful to load PacketInput quickly
128 | struct {
129 | unsigned char up : 1;
130 | unsigned char down : 1;
131 | unsigned char left : 1;
132 | unsigned char right : 1;
133 | unsigned char jump : 1;
134 | unsigned char crouch : 1;
135 | unsigned char sneak : 1;
136 | unsigned char sprint : 1;
137 | };
138 | } keys;
139 | union {
140 | unsigned char packed;
141 | struct {
142 | unsigned char lmb : 1;
143 | unsigned char rmb : 1;
144 | float lmb_start, rmb_start;
145 | };
146 | } buttons;
147 | } input;
148 |
149 | struct {
150 | unsigned char jump, airborne, wade;
151 | float lastclimb;
152 | struct Velocity {
153 | float x, y, z;
154 | } velocity;
155 | struct Position eye;
156 | } physics;
157 |
158 | struct {
159 | float feet_started, feet_started_cycle;
160 | char feet_cylce;
161 | float tool_started;
162 | } sound;
163 | } players[PLAYERS_MAX];
164 | // pyspades/pysnip/piqueserver sometimes uses ids that are out of range
165 |
166 | void player_on_held_item_change(struct Player* p);
167 | int player_can_spectate(struct Player* p);
168 | float player_section_height(int section);
169 | void player_init(void);
170 | float player_height(const struct Player* p);
171 | float player_height2(const struct Player* p);
172 | void player_reposition(struct Player* p);
173 | void player_update(float dt, int locked);
174 | void player_render_all(void);
175 | void player_render(struct Player* p, int id);
176 | void player_collision(const struct Player* p, Ray* ray, struct player_intersection* intersects);
177 | void player_reset(struct Player* p);
178 | int player_move(struct Player* p, float fsynctics, int id);
179 | int player_uncrouch(struct Player* p);
180 |
181 | #endif
182 |
--------------------------------------------------------------------------------
/src/ping.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include "window.h"
27 | #include "ping.h"
28 | #include "common.h"
29 | #include "parson.h"
30 | #include "list.h"
31 | #include "hud.h"
32 | #include "channel.h"
33 | #include "hashtable.h"
34 | #include "utils.h"
35 |
36 | struct channel ping_queue;
37 | ENetSocket sock, lan;
38 | pthread_t ping_thread;
39 | void (*ping_result)(void*, float time_delta, char* aos);
40 |
41 | void ping_init() {
42 | channel_create(&ping_queue, sizeof(struct ping_entry), 64);
43 |
44 | sock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
45 | enet_socket_set_option(sock, ENET_SOCKOPT_NONBLOCK, 1);
46 |
47 | lan = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
48 | enet_socket_set_option(lan, ENET_SOCKOPT_NONBLOCK, 1);
49 | enet_socket_set_option(lan, ENET_SOCKOPT_BROADCAST, 1);
50 |
51 | pthread_create(&ping_thread, NULL, ping_update, NULL);
52 | }
53 |
54 | void ping_deinit() {
55 | enet_socket_destroy(sock);
56 | enet_socket_destroy(lan);
57 | }
58 |
59 | static void ping_lan() {
60 | ENetAddress addr = {.host = 0xFFFFFFFF}; // 255.255.255.255
61 |
62 | ENetBuffer buffer = {
63 | .data = "HELLOLAN",
64 | .dataLength = 8,
65 | };
66 |
67 | for(addr.port = 32882; addr.port < 32892; addr.port++)
68 | enet_socket_send(lan, &addr, &buffer, 1);
69 | }
70 |
71 | static bool pings_retry(void* key, void* value, void* user) {
72 | struct ping_entry* entry = (struct ping_entry*)value;
73 |
74 | if(window_time() - entry->time_start > 2.0F) { // timeout
75 | // try up to 3 times after first failed attempt
76 | if(entry->trycount >= 3) {
77 | return true;
78 | } else {
79 | enet_socket_send(sock, &entry->addr, &(ENetBuffer) {.data = "HELLO", .dataLength = 5}, 1);
80 | entry->time_start = window_time();
81 | entry->trycount++;
82 | log_warn("Ping timeout on %s, retrying", entry->aos);
83 | }
84 | }
85 |
86 | return false;
87 | }
88 |
89 | #define IP_KEY(addr) (((uint64_t)addr.host << 16) | (addr.port));
90 |
91 | void* ping_update(void* data) {
92 | pthread_detach(pthread_self());
93 |
94 | float ping_start = window_time();
95 |
96 | HashTable pings;
97 | ht_setup(&pings, sizeof(uint64_t), sizeof(struct ping_entry), 64);
98 |
99 | while(1) {
100 | size_t drain = channel_size(&ping_queue);
101 | for(size_t k = 0; (k < drain) || (!pings.size && window_time() - ping_start >= 8.0F); k++) {
102 | struct ping_entry entry;
103 | channel_await(&ping_queue, &entry);
104 |
105 | uint64_t ID = IP_KEY(entry.addr);
106 | ht_insert(&pings, &ID, &entry);
107 | }
108 |
109 | char tmp[512];
110 | ENetAddress from;
111 |
112 | ENetBuffer buf = {
113 | .data = tmp,
114 | .dataLength = sizeof(tmp),
115 | };
116 |
117 | while(1) {
118 | int recvLength = enet_socket_receive(sock, &from, &buf, 1);
119 | uint64_t ID = IP_KEY(from);
120 |
121 | if(recvLength != 0) {
122 | struct ping_entry* entry = ht_lookup(&pings, &ID);
123 |
124 | if(entry) {
125 | if(recvLength > 0) { // received something!
126 | if(!strncmp(buf.data, "HI", recvLength)) {
127 | ping_result(NULL, window_time() - entry->time_start, entry->aos);
128 | ht_erase(&pings, &ID);
129 | } else {
130 | entry->trycount++;
131 | }
132 | } else { // connection was closed
133 | ht_erase(&pings, &ID);
134 | }
135 | }
136 | } else { // would block
137 | break;
138 | }
139 | }
140 |
141 | ht_iterate_remove(&pings, NULL, pings_retry);
142 |
143 | int length = enet_socket_receive(lan, &from, &buf, 1);
144 | if(length) {
145 | JSON_Value* js = json_parse_string(buf.data);
146 | if(js) {
147 | JSON_Object* root = json_value_get_object(js);
148 |
149 | struct serverlist_entry e;
150 |
151 | strcpy(e.country, "LAN");
152 | e.ping = ceil((window_time() - ping_start) * 1000.0F);
153 | snprintf(e.identifier, sizeof(e.identifier) - 1, "aos://%u:%u", from.host, from.port);
154 |
155 | strncpy(e.name, json_object_get_string(root, "name"), sizeof(e.name) - 1);
156 | e.name[sizeof(e.name) - 1] = 0;
157 | strncpy(e.gamemode, json_object_get_string(root, "game_mode"), sizeof(e.gamemode) - 1);
158 | e.gamemode[sizeof(e.gamemode) - 1] = 0;
159 | strncpy(e.map, json_object_get_string(root, "map"), sizeof(e.map) - 1);
160 | e.map[sizeof(e.map) - 1] = 0;
161 | e.current = json_object_get_number(root, "players_current");
162 | e.max = json_object_get_number(root, "players_max");
163 | ping_result(&e, window_time() - ping_start, NULL);
164 |
165 | json_value_free(js);
166 | }
167 | }
168 |
169 | usleep(1000);
170 | }
171 | }
172 |
173 | void ping_check(char* addr, int port, char* aos) {
174 | struct ping_entry entry = {
175 | .trycount = 0,
176 | .addr.port = port,
177 | .time_start = window_time(),
178 | };
179 |
180 | strncpy(entry.aos, aos, sizeof(entry.aos) - 1);
181 | entry.aos[sizeof(entry.aos) - 1] = 0;
182 |
183 | enet_address_set_host(&entry.addr, addr);
184 |
185 | channel_put(&ping_queue, &entry);
186 |
187 | enet_socket_send(sock, &entry.addr, &(ENetBuffer) {.data = "HELLO", .dataLength = 5}, 1);
188 | }
189 |
190 | void ping_start(void (*result)(void*, float, char*)) {
191 | ping_stop();
192 |
193 | ping_result = result;
194 | }
195 |
196 | void ping_stop() {
197 | channel_clear(&ping_queue);
198 | }
199 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
ButterSpades
4 | ---------------
5 | **Windows**: [64bit](https://butter.penguins.win/download/) - [32bit](https://butter.penguins.win/download32/)
6 |
7 |
8 | ButterSpades is a fork which aims to improve the overall UI and feel of [BetterSpades](https://github.com/xtreme8000/BetterSpades).
9 |
10 | ## What's different
11 | - In-game settings/controls menu
12 | - Better UI scaling (HUD/Main UI)
13 | - Configurable UI background and color accents
14 | - Chat colors and killfeed (OpenSpades compatible)
15 | - Adaptive chat size
16 | - HUD shadows
17 | - Spectator Y-Clamp
18 |
19 | ## Previews
20 |
21 | | 
*Apocalypse on Babel* | 
*Babel* | 
*Chat* |
22 | | :-: | :-: | :-: |
23 | | 
***Player list*** | 
***Customizable UI*** | 
***Background and color scheme*** |
24 |
25 | ## System requirements
26 |
27 | | Type | min. requirement |
28 | | ------- | ---------------------------------------------------- |
29 | | OS | Windows 98 or Linux |
30 | | CPU | 1 GHz single core processor |
31 | | GPU | 64MB VRAM, Mobile Intel 945GM or equivalent |
32 | | RAM | 256MB |
33 | | Display | 800x600px |
34 | | Others | Keyboard and mouse
Dial up network connection |
35 |
36 |
37 | ## Build requirements
38 |
39 | This project uses the following libraries and files:
40 |
41 | | Name | License | Usage | GitHub |
42 | | ------------ | --------------- | ---------------------- | :------------------------------------------------: |
43 | | GLFW3 | *ZLib* | OpenGL context | [Link](https://github.com/glfw/glfw) |
44 | | OpenAL soft | *LGPL-2.1* | 3D sound environment | [Link](https://github.com/kcat/openal-soft) |
45 | | inih | *BSD-3.Clause* | .INI file parser | [Link](https://github.com/benhoyt/inih) |
46 | | stb_truetype | *Public domain* | TrueType font renderer | [Link](https://github.com/nothings/stb) |
47 | | dr_wav | *Public domain* | wav support | [Link](https://github.com/mackron/dr_libs/) |
48 | | http | *Public domain* | http client library | [Link](https://github.com/mattiasgustavsson/libs) |
49 | | LodePNG | *MIT* | png support | [Link](https://github.com/lvandeve/lodepng) |
50 | | libdeflate | *MIT* | decompression of maps | [Link](https://github.com/ebiggers/libdeflate) |
51 | | enet | *MIT* | networking library | [Link](https://github.com/lsalzman/enet) |
52 | | parson | *MIT* | JSON parser | [Link](https://github.com/kgabis/parson) |
53 | | log.c | *MIT* | logger | [Link](https://github.com/xtreme8000/log.c) |
54 | | GLEW | *MIT* | OpenGL extensions | [Link](https://github.com/nigels-com/glew) |
55 | | hashtable | *MIT* | hashtable | [Link](https://github.com/goldsborough/hashtable/) |
56 | | libvxl | *MIT* | access VXL format | [Link](https://github.com/xtreme8000/libvxl/) |
57 | | microui | *MIT* | user interface | [Link](https://github.com/rxi/microui) |
58 |
59 | You will need to compile the following by yourself, or get hold of precompiled binaries:
60 |
61 | * GLFW3
62 | * GLEW
63 | * OpenAL soft *(only needed on Windows)*
64 | * libdeflate
65 | * enet
66 |
67 | Follow the instructions on their project page, then place produced static libraries in `deps/`.
68 |
69 | All other requirements of the above list (like single file libs) will be downloaded by CMake automatically and **don't** need to be taken care of. Because state of copyright of 0.75 assets is unknown, CMake will also download additional assets from [*here*](http://aos.party/bsresources.zip) which are not part of this repository.
70 |
71 | #### Windows
72 |
73 | This project uses CMake to generate all Makefiles automatically. It's best to use MinGW-w64 for GCC on Windows. You can generate the required files by opening `cmd.exe` in the `build/` directory and typing:
74 | ```
75 | cmake -G "MinGW Makefiles" ..
76 | mingw32-make
77 | ```
78 |
79 | If everything went well, the client should be in the `build/BetterSpades/` subfolder.
80 |
81 | When starting `client.exe`, you will be greeted by a server list. Select a server on it to start playing!
82 | You can also start the client the same way as you did with the voxlap version by opening cmd and putting an `aos://` link in as the first argument:
83 |
84 | ```
85 | client.exe -aos://16777343:32887 //Connects to a local server
86 | ```
87 |
88 | #### Linux
89 |
90 | Compilation now works the same on Linux. Just change the build system to `Unix Makefiles` or leaving it as default will work too (`cmake ..`).
91 |
92 | You can build each library yourself, or install them with your distro's package manager:
93 | ```
94 | sudo apt install libgl1-mesa libgl1-mesa-dev libopenal1 libopenal-dev libglfw-dev libenet-dev libglew-dev
95 | ```
96 | (this does not include [libdeflate](https://github.com/ebiggers/libdeflate) which is a requirement too, see [_Wiki/Building_](https://github.com/xtreme8000/BetterSpades/wiki/Building) for more details)
97 |
98 | Start the client e.g. with the following inside the `build/bin/` directory:
99 | ```
100 | ./client
101 | ```
102 | Or connect directly to localhost:
103 | ```
104 | ./client -aos://16777343:32887
105 | ```
106 |
107 |
108 | #### macOS
109 |
110 | The same instructions for Linux work on macOS aside from some minor differences. First, use Homebrew or MacPorts to grab dependencies:
111 | ```
112 | brew install glfw enet
113 | ```
114 | The development headers for OpenAL and OpenGL don't have to be installed since they come with macOS by default. [libdeflate](https://github.com/ebiggers/libdeflate) should be installed and placed manually in a way similar to Linux. See [_Wiki/Building_](https://github.com/xtreme8000/BetterSpades/wiki/Building) for more details.
115 |
--------------------------------------------------------------------------------
/src/channel.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "channel.h"
26 |
27 | static void channel_sanity_checks(struct channel* ch) {
28 | assert(ch != NULL);
29 |
30 | assert(ch->queue != NULL);
31 | assert(ch->object_size > 0);
32 | assert(ch->loc_remove < ch->length);
33 | assert(ch->loc_insert < ch->length);
34 | assert(ch->count <= ch->length);
35 | assert(ch->length >= ch->initial_length);
36 |
37 | if(ch->loc_remove < ch->loc_insert) {
38 | assert(ch->loc_insert - ch->loc_remove == ch->count);
39 | } else if(ch->loc_insert < ch->loc_remove) {
40 | assert(ch->loc_insert + (ch->length - ch->loc_remove) == ch->count);
41 | } else {
42 | assert(ch->count == ch->length || ch->count == 0);
43 | }
44 | }
45 |
46 | bool channel_create(struct channel* ch, size_t object_size, size_t length) {
47 | assert(ch != NULL && object_size > 0 && length > 0);
48 |
49 | ch->object_size = object_size;
50 | ch->initial_length = length;
51 | ch->length = ch->initial_length;
52 | ch->count = 0;
53 | ch->queue = malloc(object_size * length);
54 | ch->loc_insert = 0;
55 | ch->loc_remove = 0;
56 |
57 | if(!ch->queue)
58 | return false;
59 |
60 | if(pthread_mutex_init(&ch->lock, NULL)) {
61 | free(ch->queue);
62 | return false;
63 | }
64 |
65 | if(pthread_cond_init(&ch->signal, NULL)) {
66 | free(ch->queue);
67 | pthread_mutex_destroy(&ch->lock);
68 | return false;
69 | }
70 |
71 | return true;
72 | }
73 |
74 | size_t channel_size(struct channel* ch) {
75 | assert(ch != NULL);
76 |
77 | pthread_mutex_lock(&ch->lock);
78 | size_t res = ch->count;
79 | pthread_mutex_unlock(&ch->lock);
80 | return res;
81 | }
82 |
83 | void channel_destroy(struct channel* ch) {
84 | assert(ch != NULL);
85 |
86 | free(ch->queue);
87 | pthread_cond_destroy(&ch->signal);
88 | pthread_mutex_destroy(&ch->lock);
89 | }
90 |
91 | // call once buffer is full
92 | static void channel_grow(struct channel* ch) {
93 | assert(ch != NULL);
94 |
95 | size_t length = ch->length * 2;
96 |
97 | ch->queue = realloc(ch->queue, ch->object_size * length);
98 |
99 | if(ch->loc_insert <= ch->loc_remove) {
100 | size_t object_count = ch->length - ch->loc_remove;
101 | size_t new_remove_loc = length - object_count;
102 |
103 | memcpy((uint8_t*)ch->queue + new_remove_loc * ch->object_size,
104 | (uint8_t*)ch->queue + ch->loc_remove * ch->object_size, object_count * ch->object_size);
105 |
106 | ch->loc_remove = new_remove_loc;
107 | }
108 |
109 | ch->length = length;
110 |
111 | channel_sanity_checks(ch);
112 | }
113 |
114 | // call once only 25% of elements left, we will halve the buffer, so its filled exactly by 50%
115 | static void channel_shrink(struct channel* ch) {
116 | assert(ch != NULL);
117 |
118 | size_t length = ch->length / 2;
119 |
120 | /* Is the run of elements ending in the to be removed section? Note, that there are only 25% of elements left, so
121 | * the run can't wrap around to the left. If yes, move all elements to the start. */
122 | if(ch->loc_insert > length && ch->loc_remove < ch->loc_insert) {
123 | memmove(ch->queue, (uint8_t*)ch->queue + ch->loc_remove * ch->object_size, ch->count * ch->object_size);
124 | ch->loc_remove = 0;
125 | ch->loc_insert = ch->count;
126 |
127 | /* Is the run of elements wrapping at the buffer's borders? If yes, copy the right part to the new ending
128 | * (middle). We won't override existing data, since all elements will only occupy 50% once shrinked. */
129 | } else if(ch->loc_insert < ch->loc_remove) {
130 | size_t object_count = ch->length - ch->loc_remove;
131 | size_t new_remove_loc = length - object_count;
132 |
133 | memcpy((uint8_t*)ch->queue + new_remove_loc * ch->object_size,
134 | (uint8_t*)ch->queue + ch->loc_remove * ch->object_size, object_count * ch->object_size);
135 |
136 | ch->loc_remove = new_remove_loc;
137 | }
138 |
139 | ch->length = length;
140 | ch->queue = realloc(ch->queue, ch->object_size * ch->length);
141 | ch->loc_remove %= ch->length;
142 | ch->loc_insert %= ch->length;
143 |
144 | channel_sanity_checks(ch);
145 | }
146 |
147 | void channel_put(struct channel* ch, void* object) {
148 | assert(ch != NULL && object != NULL);
149 |
150 | pthread_mutex_lock(&ch->lock);
151 | channel_sanity_checks(ch);
152 |
153 | if(ch->count >= ch->length)
154 | channel_grow(ch);
155 |
156 | memcpy((uint8_t*)ch->queue + ch->loc_insert * ch->object_size, object, ch->object_size);
157 | ch->loc_insert = (ch->loc_insert + 1) % ch->length;
158 | ch->count++;
159 |
160 | channel_sanity_checks(ch);
161 |
162 | pthread_cond_signal(&ch->signal);
163 | pthread_mutex_unlock(&ch->lock);
164 | }
165 |
166 | void channel_await(struct channel* ch, void* object) {
167 | assert(ch != NULL && object != NULL);
168 |
169 | pthread_mutex_lock(&ch->lock);
170 | channel_sanity_checks(ch);
171 |
172 | while(!ch->count)
173 | pthread_cond_wait(&ch->signal, &ch->lock);
174 |
175 | memcpy(object, (uint8_t*)ch->queue + ch->loc_remove * ch->object_size, ch->object_size);
176 | ch->loc_remove = (ch->loc_remove + 1) % ch->length;
177 | ch->count--;
178 |
179 | if(ch->length / 2 >= ch->initial_length && ch->count <= ch->length / 4)
180 | channel_shrink(ch);
181 |
182 | channel_sanity_checks(ch);
183 |
184 | pthread_cond_signal(&ch->signal);
185 | pthread_mutex_unlock(&ch->lock);
186 | }
187 |
188 | void channel_clear(struct channel* ch) {
189 | assert(ch != NULL);
190 |
191 | pthread_mutex_lock(&ch->lock);
192 | ch->count = 0;
193 | ch->loc_remove = 0;
194 | ch->loc_insert = 0;
195 |
196 | pthread_cond_signal(&ch->signal);
197 | pthread_mutex_unlock(&ch->lock);
198 | }
199 |
--------------------------------------------------------------------------------
/src/ini.h:
--------------------------------------------------------------------------------
1 | /* inih -- simple .INI file parser
2 |
3 | SPDX-License-Identifier: BSD-3-Clause
4 |
5 | Copyright (C) 2009-2020, Ben Hoyt
6 |
7 | inih is released under the New BSD license (see LICENSE.txt). Go to the project
8 | home page for more info:
9 |
10 | https://github.com/benhoyt/inih
11 |
12 | */
13 |
14 | #ifndef INI_H
15 | #define INI_H
16 |
17 | /* Make this header file easier to include in C++ code */
18 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 |
22 | #include
23 |
24 | /* Nonzero if ini_handler callback should accept lineno parameter. */
25 | #ifndef INI_HANDLER_LINENO
26 | #define INI_HANDLER_LINENO 0
27 | #endif
28 |
29 | /* Visibility symbols, required for Windows DLLs */
30 | #ifndef INI_API
31 | #if defined _WIN32 || defined __CYGWIN__
32 | # ifdef INI_SHARED_LIB
33 | # ifdef INI_SHARED_LIB_BUILDING
34 | # define INI_API __declspec(dllexport)
35 | # else
36 | # define INI_API __declspec(dllimport)
37 | # endif
38 | # else
39 | # define INI_API
40 | # endif
41 | #else
42 | # if defined(__GNUC__) && __GNUC__ >= 4
43 | # define INI_API __attribute__ ((visibility ("default")))
44 | # else
45 | # define INI_API
46 | # endif
47 | #endif
48 | #endif
49 |
50 | /* Typedef for prototype of handler function. */
51 | #if INI_HANDLER_LINENO
52 | typedef int (*ini_handler)(void* user, const char* section,
53 | const char* name, const char* value,
54 | int lineno);
55 | #else
56 | typedef int (*ini_handler)(void* user, const char* section,
57 | const char* name, const char* value);
58 | #endif
59 |
60 | /* Typedef for prototype of fgets-style reader function. */
61 | typedef char* (*ini_reader)(char* str, int num, void* stream);
62 |
63 | /* Parse given INI-style file. May have [section]s, name=value pairs
64 | (whitespace stripped), and comments starting with ';' (semicolon). Section
65 | is "" if name=value pair parsed before any section heading. name:value
66 | pairs are also supported as a concession to Python's configparser.
67 |
68 | For each name=value pair parsed, call handler function with given user
69 | pointer as well as section, name, and value (data only valid for duration
70 | of handler call). Handler should return nonzero on success, zero on error.
71 |
72 | Returns 0 on success, line number of first error on parse error (doesn't
73 | stop on first error), -1 on file open error, or -2 on memory allocation
74 | error (only when INI_USE_STACK is zero).
75 | */
76 | INI_API int ini_parse(const char* filename, ini_handler handler, void* user);
77 |
78 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
79 | close the file when it's finished -- the caller must do that. */
80 | INI_API int ini_parse_file(FILE* file, ini_handler handler, void* user);
81 |
82 | /* Same as ini_parse(), but takes an ini_reader function pointer instead of
83 | filename. Used for implementing custom or string-based I/O (see also
84 | ini_parse_string). */
85 | INI_API int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
86 | void* user);
87 |
88 | /* Same as ini_parse(), but takes a zero-terminated string with the INI data
89 | instead of a file. Useful for parsing INI data from a network socket or
90 | already in memory. */
91 | INI_API int ini_parse_string(const char* string, ini_handler handler, void* user);
92 |
93 | /* Nonzero to allow multi-line value parsing, in the style of Python's
94 | configparser. If allowed, ini_parse() will call the handler with the same
95 | name for each subsequent line parsed. */
96 | #ifndef INI_ALLOW_MULTILINE
97 | #define INI_ALLOW_MULTILINE 1
98 | #endif
99 |
100 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
101 | the file. See https://github.com/benhoyt/inih/issues/21 */
102 | #ifndef INI_ALLOW_BOM
103 | #define INI_ALLOW_BOM 1
104 | #endif
105 |
106 | /* Chars that begin a start-of-line comment. Per Python configparser, allow
107 | both ; and # comments at the start of a line by default. */
108 | #ifndef INI_START_COMMENT_PREFIXES
109 | #define INI_START_COMMENT_PREFIXES ";#"
110 | #endif
111 |
112 | /* Nonzero to allow inline comments (with valid inline comment characters
113 | specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
114 | Python 3.2+ configparser behaviour. */
115 | #ifndef INI_ALLOW_INLINE_COMMENTS
116 | #define INI_ALLOW_INLINE_COMMENTS 1
117 | #endif
118 | #ifndef INI_INLINE_COMMENT_PREFIXES
119 | #define INI_INLINE_COMMENT_PREFIXES ";"
120 | #endif
121 |
122 | /* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */
123 | #ifndef INI_USE_STACK
124 | #define INI_USE_STACK 1
125 | #endif
126 |
127 | /* Maximum line length for any line in INI file (stack or heap). Note that
128 | this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */
129 | #ifndef INI_MAX_LINE
130 | #define INI_MAX_LINE 200
131 | #endif
132 |
133 | /* Nonzero to allow heap line buffer to grow via realloc(), zero for a
134 | fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is
135 | zero. */
136 | #ifndef INI_ALLOW_REALLOC
137 | #define INI_ALLOW_REALLOC 0
138 | #endif
139 |
140 | /* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK
141 | is zero. */
142 | #ifndef INI_INITIAL_ALLOC
143 | #define INI_INITIAL_ALLOC 200
144 | #endif
145 |
146 | /* Stop parsing on first error (default is to keep parsing). */
147 | #ifndef INI_STOP_ON_FIRST_ERROR
148 | #define INI_STOP_ON_FIRST_ERROR 0
149 | #endif
150 |
151 | /* Nonzero to call the handler at the start of each new section (with
152 | name and value NULL). Default is to only call the handler on
153 | each name=value pair. */
154 | #ifndef INI_CALL_HANDLER_ON_NEW_SECTION
155 | #define INI_CALL_HANDLER_ON_NEW_SECTION 0
156 | #endif
157 |
158 | /* Nonzero to allow a name without a value (no '=' or ':' on the line) and
159 | call the handler with value NULL in this case. Default is to treat
160 | no-value lines as an error. */
161 | #ifndef INI_ALLOW_NO_VALUE
162 | #define INI_ALLOW_NO_VALUE 0
163 | #endif
164 |
165 | /* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory
166 | allocation functions (INI_USE_STACK must also be 0). These functions must
167 | have the same signatures as malloc/free/realloc and behave in a similar
168 | way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */
169 | #ifndef INI_CUSTOM_ALLOCATOR
170 | #define INI_CUSTOM_ALLOCATOR 0
171 | #endif
172 |
173 |
174 | #ifdef __cplusplus
175 | }
176 | #endif
177 |
178 | #endif /* INI_H */
179 |
--------------------------------------------------------------------------------
/src/file.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include "common.h"
29 | #include "log.h"
30 | #include "file.h"
31 |
32 | struct file_handle {
33 | void* internal;
34 | int type;
35 | };
36 |
37 | enum {
38 | FILE_STD,
39 | FILE_SDL,
40 | };
41 |
42 | void file_url(char* url) {
43 | char cmd[strlen(url) + 16];
44 | #ifdef OS_WINDOWS
45 | sprintf(cmd, "start %s", url);
46 | system(cmd);
47 | #endif
48 | #if defined(OS_LINUX) || defined(OS_APPLE)
49 | sprintf(cmd, "xdg-open %s", url);
50 | system(cmd);
51 | #endif
52 | #ifdef OS_HAIKU
53 | sprintf(cmd, "open %s", url);
54 | system(cmd);
55 | #endif
56 | }
57 |
58 | int file_dir_exists(const char* path) {
59 | #ifndef USE_ANDROID_FILE
60 | DIR* d = opendir(path);
61 | #else
62 | char str[256];
63 | sprintf(str, "/sdcard/BetterSpades/%s", path);
64 | DIR* d = opendir(str);
65 | #endif
66 | if(d) {
67 | closedir(d);
68 | return 1;
69 | } else {
70 | return 0;
71 | }
72 | }
73 |
74 | int file_dir_create(const char* path) {
75 | #ifndef USE_ANDROID_FILE
76 | #ifdef OS_WINDOWS
77 | mkdir(path);
78 | #else
79 | mkdir(path, 0755);
80 | #endif
81 | #else
82 | char str[256];
83 | sprintf(str, "/sdcard/BetterSpades/%s", path);
84 | mkdir(str);
85 | #endif
86 | return 1;
87 | }
88 |
89 | int file_exists(const char* name) {
90 | #ifdef USE_ANDROID_FILE
91 | void* f = file_open(name, "rb");
92 | if(f == NULL)
93 | return 0;
94 | file_close(f);
95 | return 1;
96 | #else
97 | return !access(name, F_OK);
98 | #endif
99 | }
100 |
101 | int file_size(const char* name) {
102 | #ifdef USE_ANDROID_FILE
103 | struct file_handle* f = (struct file_handle*)file_open(name, "rb");
104 | if(!f)
105 | return 0;
106 | if(f->type == FILE_SDL) {
107 | int size = SDL_RWsize((struct SDL_RWops*)f->internal);
108 | file_close(f);
109 | return size;
110 | }
111 | if(f->type == FILE_STD) {
112 | fseek(f->internal, 0, SEEK_END);
113 | int size = ftell(f->internal);
114 | file_close(f);
115 | return size;
116 | }
117 | return 0;
118 | #else
119 | FILE* f = fopen(name, "rb");
120 | if(!f)
121 | return 0;
122 | fseek(f, 0, SEEK_END);
123 | int size = ftell(f);
124 | fclose(f);
125 | return size;
126 | #endif
127 | }
128 |
129 | unsigned char* file_load(const char* name) {
130 | #ifdef USE_ANDROID_FILE
131 | int size = file_size(name);
132 | struct file_handle* f = (struct file_handle*)file_open(name, "rb");
133 | if(!f)
134 | return NULL;
135 | unsigned char* data = malloc(size + 1);
136 | CHECK_ALLOCATION_ERROR(data)
137 | data[size] = 0;
138 | if(f->type == FILE_SDL) {
139 | int offset = 0;
140 | while(1) {
141 | int read = SDL_RWread((struct SDL_RWops*)f->internal, data + offset, 1, size - offset);
142 | if(!read)
143 | break;
144 | offset += read;
145 | }
146 | SDL_RWclose((struct SDL_RWops*)f->internal);
147 | if(!offset) {
148 | free(data);
149 | return NULL;
150 | }
151 | }
152 | if(f->type == FILE_STD) {
153 | fread(data, size, 1, f->internal);
154 | fclose(f->internal);
155 | }
156 | return data;
157 | #else
158 | FILE* f;
159 | f = fopen(name, "rb");
160 | if(!f) {
161 | log_fatal("ERROR: failed to open '%s', exiting", name);
162 | exit(1);
163 | }
164 | fseek(f, 0, SEEK_END);
165 | int size = ftell(f);
166 | unsigned char* data = malloc(size + 1);
167 | CHECK_ALLOCATION_ERROR(data)
168 | data[size] = 0;
169 | fseek(f, 0, SEEK_SET);
170 | fread(data, size, 1, f);
171 | fclose(f);
172 | return data;
173 | #endif
174 | }
175 |
176 | void* file_open(const char* name, const char* mode) {
177 | #ifdef USE_ANDROID_FILE
178 | struct file_handle* handle = malloc(sizeof(struct file_handle));
179 | handle->internal = (strchr(mode, 'r') != NULL) ? SDL_RWFromFile(name, mode) : NULL;
180 | handle->type = FILE_SDL;
181 | if(!handle->internal) {
182 | char str[256];
183 | sprintf(str, "/sdcard/BetterSpades/%s", name);
184 | handle->internal = fopen(str, mode);
185 | handle->type = FILE_STD;
186 | // log_warn("open %s %i",str,handle->internal);
187 | }
188 | if(!handle->internal) {
189 | free(handle);
190 | return NULL;
191 | }
192 | return handle;
193 | #else
194 | return fopen(name, mode);
195 | #endif
196 | }
197 |
198 | void file_printf(void* file, const char* fmt, ...) {
199 | va_list args;
200 | va_start(args, fmt);
201 | #ifdef USE_ANDROID_FILE
202 | struct file_handle* f = (struct file_handle*)file;
203 | if(f->type == FILE_SDL) {
204 | char str[256];
205 | vsprintf(str, fmt, args);
206 | int written = 0;
207 | int total = strlen(str);
208 | while(written < total)
209 | written += SDL_RWwrite((struct SDL_RWops*)f->internal, str + written, 1, total - written);
210 | }
211 | if(f->type == FILE_STD) {
212 | log_warn("%i %i", f->internal, f);
213 | vfprintf((FILE*)f->internal, fmt, args);
214 | }
215 | #else
216 | vfprintf((FILE*)file, fmt, args);
217 | #endif
218 | va_end(args);
219 | }
220 |
221 | void file_close(void* file) {
222 | #ifdef USE_ANDROID_FILE
223 | struct file_handle* f = (struct file_handle*)file;
224 | if(f->type == FILE_SDL) {
225 | SDL_RWclose((struct SDL_RWops*)f->internal);
226 | }
227 | if(f->type == FILE_STD) {
228 | fclose((FILE*)f->internal);
229 | }
230 | free(f);
231 | #else
232 | fclose((FILE*)file);
233 | #endif
234 | }
235 |
236 | float buffer_readf(unsigned char* buffer, int index) {
237 | return ((float*)(buffer + index))[0];
238 | }
239 |
240 | unsigned int buffer_read32(unsigned char* buffer, int index) {
241 | return (buffer[index + 3] << 24) | (buffer[index + 2] << 16) | (buffer[index + 1] << 8) | buffer[index];
242 | }
243 |
244 | unsigned short buffer_read16(unsigned char* buffer, int index) {
245 | return (buffer[index + 1] << 8) | buffer[index];
246 | }
247 |
248 | unsigned char buffer_read8(unsigned char* buffer, int index) {
249 | return buffer[index];
250 | }
251 |
--------------------------------------------------------------------------------
/src/particle.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "common.h"
25 | #include "window.h"
26 | #include "camera.h"
27 | #include "map.h"
28 | #include "matrix.h"
29 | #include "particle.h"
30 | #include "model.h"
31 | #include "weapon.h"
32 | #include "config.h"
33 | #include "tesselator.h"
34 | #include "entitysystem.h"
35 |
36 | struct entity_system particles;
37 | struct tesselator particle_tesselator;
38 |
39 | void particle_init() {
40 | entitysys_create(&particles, sizeof(struct Particle), 256);
41 | tesselator_create(&particle_tesselator, VERTEX_FLOAT, 0);
42 | }
43 |
44 | static bool particle_update_single(void* obj, void* user) {
45 | struct Particle* p = (struct Particle*)obj;
46 | float dt = *(float*)user;
47 | float size = p->size * (1.0F - ((float)(window_time() - p->fade) / 2.0F));
48 |
49 | if(size < 0.01F) {
50 | return true;
51 | } else {
52 | float acc_y = -32.0F * dt;
53 |
54 | if(map_isair(p->x, p->y + acc_y * dt - p->size / 2.0F, p->z) && !p->y + acc_y * dt < 0.0F) {
55 | p->vy += acc_y;
56 | }
57 |
58 | float movement_x = p->vx * dt;
59 | float movement_y = p->vy * dt;
60 | float movement_z = p->vz * dt;
61 | bool on_ground = false;
62 |
63 | if(!map_isair(p->x + movement_x, p->y, p->z)) {
64 | movement_x = 0.0F;
65 | p->vx = -p->vx * 0.6F;
66 | on_ground = true;
67 | }
68 | if(!map_isair(p->x + movement_x, p->y + movement_y, p->z)) {
69 | movement_y = 0.0F;
70 | p->vy = -p->vy * 0.6F;
71 | on_ground = true;
72 | }
73 | if(!map_isair(p->x + movement_x, p->y + movement_y, p->z + movement_z)) {
74 | movement_z = 0.0F;
75 | p->vz = -p->vz * 0.6F;
76 | on_ground = true;
77 | }
78 |
79 | float pow1_tys = 0.999991F + (2.55114F * dt - 2.30093F) * dt;
80 | float pow4_tys = 1.0F + (0.413432 * dt - 0.916185F) * dt;
81 |
82 | // air and ground friction
83 | if(on_ground) {
84 | p->vx *= pow1_tys; // pow(0.1F, dt);
85 | p->vy *= pow1_tys; // pow(0.1F, dt);
86 | p->vz *= pow1_tys; // pow(0.1F, dt);
87 |
88 | if(abs(p->vx) < 0.1F)
89 | p->vx = 0.0F;
90 | if(abs(p->vy) < 0.1F)
91 | p->vy = 0.0F;
92 | if(abs(p->vz) < 0.1F)
93 | p->vz = 0.0F;
94 | } else {
95 | p->vx *= pow4_tys; // pow(0.4F, dt);
96 | p->vy *= pow4_tys; // pow(0.4F, dt);
97 | p->vz *= pow4_tys; // pow(0.4F, dt);
98 | }
99 |
100 | p->x += movement_x;
101 | p->y += movement_y;
102 | p->z += movement_z;
103 |
104 | return false;
105 | }
106 | }
107 |
108 | void particle_update(float dt) {
109 | entitysys_iterate(&particles, &dt, particle_update_single);
110 | }
111 |
112 | static bool particle_render_single(void* obj, void* user) {
113 | struct Particle* p = (struct Particle*)obj;
114 | struct tesselator* tess = (struct tesselator*)user;
115 |
116 | if(distance2D(camera_x, camera_z, p->x, p->z) > settings.render_distance * settings.render_distance)
117 | return false;
118 |
119 | float size = p->size / 2.0F * (1.0F - ((float)(window_time() - p->fade) / 2.0F));
120 |
121 | if(p->type == 255) {
122 | tesselator_set_color(tess, p->color);
123 |
124 | tesselator_addf_cube_face(tess, CUBE_FACE_X_N, p->x - size, p->y - size, p->z - size, size * 2.0F);
125 | tesselator_addf_cube_face(tess, CUBE_FACE_X_P, p->x - size, p->y - size, p->z - size, size * 2.0F);
126 | tesselator_addf_cube_face(tess, CUBE_FACE_Y_N, p->x - size, p->y - size, p->z - size, size * 2.0F);
127 | tesselator_addf_cube_face(tess, CUBE_FACE_Y_P, p->x - size, p->y - size, p->z - size, size * 2.0F);
128 | tesselator_addf_cube_face(tess, CUBE_FACE_Z_N, p->x - size, p->y - size, p->z - size, size * 2.0F);
129 | tesselator_addf_cube_face(tess, CUBE_FACE_Z_P, p->x - size, p->y - size, p->z - size, size * 2.0F);
130 | } else {
131 | struct kv6_t* casing = weapon_casing(p->type);
132 |
133 | if(casing) {
134 | matrix_push(matrix_model);
135 | matrix_identity(matrix_model);
136 | matrix_translate(matrix_model, p->x, p->y, p->z);
137 | matrix_pointAt(matrix_model, p->ox, p->oy * max(1.0F - (window_time() - p->fade) / 0.5F, 0.0F), p->oz);
138 | matrix_rotate(matrix_model, 90.0F, 0.0F, 1.0F, 0.0F);
139 | matrix_upload();
140 | kv6_render(casing, TEAM_SPECTATOR);
141 | matrix_pop(matrix_model);
142 | }
143 | }
144 |
145 | return false;
146 | }
147 |
148 | void particle_render() {
149 | tesselator_clear(&particle_tesselator);
150 |
151 | entitysys_iterate(&particles, &particle_tesselator, particle_render_single);
152 |
153 | matrix_upload();
154 | tesselator_draw(&particle_tesselator, 1);
155 | }
156 |
157 | void particle_create_casing(struct Player* p) {
158 | entitysys_add(&particles,
159 | &(struct Particle) {
160 | .size = 0.1F,
161 | .x = p->gun_pos.x,
162 | .y = p->gun_pos.y,
163 | .z = p->gun_pos.z,
164 | .ox = p->orientation.x,
165 | .oy = p->orientation.y,
166 | .oz = p->orientation.z,
167 | .vx = p->casing_dir.x * 3.5F,
168 | .vy = p->casing_dir.y * 3.5F,
169 | .vz = p->casing_dir.z * 3.5F,
170 | .fade = window_time(),
171 | .type = p->weapon,
172 | .color = 0x00FFFF,
173 | });
174 | }
175 |
176 | void particle_create(unsigned int color, float x, float y, float z, float velocity, float velocity_y, int amount,
177 | float min_size, float max_size) {
178 | for(int k = 0; k < amount; k++) {
179 | float vx = (((float)rand() / (float)RAND_MAX) * 2.0F - 1.0F);
180 | float vy = (((float)rand() / (float)RAND_MAX) * 2.0F - 1.0F);
181 | float vz = (((float)rand() / (float)RAND_MAX) * 2.0F - 1.0F);
182 | float len = len3D(vx, vy, vz);
183 |
184 | vx = (vx / len) * velocity;
185 | vy = (vy / len) * velocity * velocity_y;
186 | vz = (vz / len) * velocity;
187 |
188 | entitysys_add(&particles,
189 | &(struct Particle) {
190 | .size = ((float)rand() / (float)RAND_MAX) * (max_size - min_size) + min_size,
191 | .x = x,
192 | .y = y,
193 | .z = z,
194 | .vx = vx,
195 | .vy = vy,
196 | .vz = vz,
197 | .fade = window_time(),
198 | .color = color,
199 | .type = 255,
200 | });
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/src/font.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "common.h"
25 | #include "file.h"
26 | #include "hashtable.h"
27 | #include "font.h"
28 | #include "stb_truetype.h"
29 | #include "utils.h"
30 |
31 | #define FONT_BAKE_START 31
32 |
33 | static short* font_vertex_buffer;
34 | static short* font_coords_buffer;
35 | static enum font_type font_current_type = FONT_FIXEDSYS;
36 |
37 | static void* font_data_fixedsys;
38 | static void* font_data_smallfnt;
39 | static void* font_data_fantasy;
40 |
41 | static HashTable fonts_backed;
42 |
43 | struct __attribute__((packed)) font_backed_id {
44 | enum font_type type;
45 | float size;
46 | };
47 |
48 | struct font_backed_data {
49 | stbtt_bakedchar* cdata;
50 | GLuint texture_id;
51 | int w, h;
52 | };
53 |
54 | void font_init() {
55 | font_vertex_buffer = malloc(512 * 8 * sizeof(short));
56 | CHECK_ALLOCATION_ERROR(font_vertex_buffer)
57 | font_coords_buffer = malloc(512 * 8 * sizeof(short));
58 | CHECK_ALLOCATION_ERROR(font_coords_buffer)
59 |
60 | font_data_fixedsys = file_load("fonts/Fixedsys.ttf");
61 | CHECK_ALLOCATION_ERROR(font_data_fixedsys)
62 | font_data_smallfnt = file_load("fonts/Terminal.ttf");
63 | CHECK_ALLOCATION_ERROR(font_data_smallfnt)
64 | font_data_fantasy = file_load("fonts/ft88.ttf");
65 | CHECK_ALLOCATION_ERROR(font_data_fantasy)
66 |
67 | ht_setup(&fonts_backed, sizeof(struct font_backed_id), sizeof(struct font_backed_data), 8);
68 | }
69 |
70 | void font_select(enum font_type type) {
71 | font_current_type = type;
72 | }
73 |
74 | static struct font_backed_data* font_find(float h) {
75 | if(font_current_type == FONT_SMALLFNT) {
76 | h *= 1.5F;
77 | }
78 |
79 | struct font_backed_id id = (struct font_backed_id) {
80 | .type = font_current_type,
81 | .size = h,
82 | };
83 |
84 | struct font_backed_data* f_cached = ht_lookup(&fonts_backed, &id);
85 |
86 | if(f_cached)
87 | return f_cached;
88 |
89 | void* file;
90 | switch(font_current_type) {
91 | case FONT_FIXEDSYS: file = font_data_fixedsys; break;
92 | case FONT_SMALLFNT: file = font_data_smallfnt; break;
93 | case FONT_FANTASY: file = font_data_fantasy; break;
94 | default: return NULL;
95 | }
96 |
97 | struct font_backed_data f;
98 | f.w = 64;
99 | f.h = 64;
100 | f.cdata = malloc((0xFF - FONT_BAKE_START) * sizeof(stbtt_bakedchar));
101 | CHECK_ALLOCATION_ERROR(f.cdata)
102 |
103 | void* temp_bitmap = NULL;
104 |
105 | int max_size = 0;
106 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size);
107 |
108 | while(1) {
109 | temp_bitmap = realloc(temp_bitmap, f.w * f.h);
110 | CHECK_ALLOCATION_ERROR(temp_bitmap)
111 | int res = 0;
112 | res = stbtt_BakeFontBitmap(file, 0, h, temp_bitmap, f.w, f.h, FONT_BAKE_START, 0xFF - FONT_BAKE_START, f.cdata);
113 | if(res > 0 || (f.w == max_size && f.h == max_size))
114 | break;
115 | if(f.h > f.w)
116 | f.w *= 2;
117 | else
118 | f.h *= 2;
119 | }
120 |
121 | log_info("font texsize: %i:%ipx [size %f] type: %i", f.w, f.h, h, font_current_type);
122 |
123 | glGenTextures(1, &f.texture_id);
124 | glBindTexture(GL_TEXTURE_2D, f.texture_id);
125 | glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, f.w, f.h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap);
126 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
127 | glBindTexture(GL_TEXTURE_2D, 0);
128 |
129 | free(temp_bitmap);
130 |
131 | ht_insert(&fonts_backed, &id, &f);
132 |
133 | return ht_lookup(&fonts_backed, &id);
134 | }
135 |
136 | float font_length(float h, char* text) {
137 | struct font_backed_data* font = font_find(h);
138 |
139 | if(!font)
140 | return 0.0F;
141 |
142 | stbtt_aligned_quad q;
143 | float y = h * 0.75F;
144 | float x = 0.0F;
145 | float length = 0.0F;
146 | for(size_t k = 0; k < strlen(text); k++) {
147 | if(text[k] == '\n') {
148 | length = fmax(length, x);
149 | x = 0.0F;
150 | }
151 |
152 | if(text[k] >= FONT_BAKE_START)
153 | stbtt_GetBakedQuad(font->cdata, font->w, font->h, text[k] - FONT_BAKE_START, &x, &y, &q, 1);
154 | }
155 |
156 | return fmax(length, x) + h * 0.125F;
157 | }
158 |
159 | bool font_remove_callback(void* key, void* value, void* user) {
160 | struct font_backed_data* f = (struct font_backed_data*)value;
161 |
162 | glDeleteTextures(1, &f->texture_id);
163 | free(f->cdata);
164 |
165 | return true;
166 | }
167 |
168 | void font_reset() {
169 | ht_iterate_remove(&fonts_backed, NULL, font_remove_callback);
170 | }
171 |
172 | void font_render(float x, float y, float h, char* text) {
173 | struct font_backed_data* font = font_find(h);
174 |
175 | if(!font)
176 | return;
177 |
178 | size_t k = 0;
179 | float x2 = x;
180 | float y2 = h * 0.75F;
181 | while(*text) {
182 | if(*text == '\n') {
183 | x2 = x;
184 | y2 += h;
185 | }
186 |
187 | if(*text >= FONT_BAKE_START) {
188 | stbtt_aligned_quad q;
189 | stbtt_GetBakedQuad(font->cdata, font->w, font->h, *text - FONT_BAKE_START, &x2, &y2, &q, 1);
190 | font_coords_buffer[k + 0] = q.s0 * 8192.0F;
191 | font_coords_buffer[k + 1] = q.t1 * 8192.0F;
192 | font_coords_buffer[k + 2] = q.s1 * 8192.0F;
193 | font_coords_buffer[k + 3] = q.t1 * 8192.0F;
194 | font_coords_buffer[k + 4] = q.s1 * 8192.0F;
195 | font_coords_buffer[k + 5] = q.t0 * 8192.0F;
196 |
197 | font_coords_buffer[k + 6] = q.s0 * 8192.0F;
198 | font_coords_buffer[k + 7] = q.t1 * 8192.0F;
199 | font_coords_buffer[k + 8] = q.s1 * 8192.0F;
200 | font_coords_buffer[k + 9] = q.t0 * 8192.0F;
201 | font_coords_buffer[k + 10] = q.s0 * 8192.0F;
202 | font_coords_buffer[k + 11] = q.t0 * 8192.0F;
203 |
204 | font_vertex_buffer[k + 0] = q.x0;
205 | font_vertex_buffer[k + 1] = -q.y1 + y;
206 | font_vertex_buffer[k + 2] = q.x1;
207 | font_vertex_buffer[k + 3] = -q.y1 + y;
208 | font_vertex_buffer[k + 4] = q.x1;
209 | font_vertex_buffer[k + 5] = -q.y0 + y;
210 |
211 | font_vertex_buffer[k + 6] = q.x0;
212 | font_vertex_buffer[k + 7] = -q.y1 + y;
213 | font_vertex_buffer[k + 8] = q.x1;
214 | font_vertex_buffer[k + 9] = -q.y0 + y;
215 | font_vertex_buffer[k + 10] = q.x0;
216 | font_vertex_buffer[k + 11] = -q.y0 + y;
217 | k += 12;
218 | }
219 |
220 | text++;
221 | }
222 |
223 | glMatrixMode(GL_TEXTURE);
224 | glLoadIdentity();
225 | glScalef(1.0F / 8192.0F, 1.0F / 8192.0F, 1.0F);
226 | glMatrixMode(GL_MODELVIEW);
227 |
228 | glEnable(GL_TEXTURE_2D);
229 | glBindTexture(GL_TEXTURE_2D, font->texture_id);
230 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
231 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
232 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
233 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
234 | glEnable(GL_BLEND);
235 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
236 |
237 | glEnableClientState(GL_VERTEX_ARRAY);
238 | glEnableClientState(GL_TEXTURE_COORD_ARRAY);
239 | glVertexPointer(2, GL_SHORT, 0, font_vertex_buffer);
240 | glTexCoordPointer(2, GL_SHORT, 0, font_coords_buffer);
241 | glDrawArrays(GL_TRIANGLES, 0, k / 2);
242 | glDisableClientState(GL_TEXTURE_COORD_ARRAY);
243 | glDisableClientState(GL_VERTEX_ARRAY);
244 |
245 | glDisable(GL_BLEND);
246 | glBindTexture(GL_TEXTURE_2D, 0);
247 | glDisable(GL_TEXTURE_2D);
248 |
249 | glMatrixMode(GL_TEXTURE);
250 | glLoadIdentity();
251 | glMatrixMode(GL_MODELVIEW);
252 | }
253 |
254 | void font_render_shadow(float x, float y, float h, char* text, float a) {
255 | float color[4];
256 | glGetFloatv(GL_CURRENT_COLOR, color);
257 |
258 | glColor4f(0.F, 0.F, 0.F, a);
259 | font_render(x, y - 1.F, h, text);
260 | font_render(x, y - 2.F, h, text);
261 |
262 | glColor4f(color[0], color[1], color[2], color[3]);
263 | font_render(x, y, h, text);
264 | }
265 |
266 | void font_centered(float x, float y, float h, char* text) {
267 | font_render(x - font_length(h, text) / 2.0F, y, h, text);
268 | }
269 |
270 | void font_centered_shadow(float x, float y, float h, char* text, float a) {
271 | font_render_shadow(x - font_length(h, text) / 2.0F, y, h, text, a);
272 | }
273 |
--------------------------------------------------------------------------------
/src/model_normals.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2017-2020 ByteBit
3 |
4 | This file is part of BetterSpades.
5 |
6 | BetterSpades is free software: you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation, either version 3 of the License, or
9 | (at your option) any later version.
10 |
11 | BetterSpades is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License
17 | along with BetterSpades. If not, see .
18 | */
19 |
20 | #ifndef MODEL_NORMALS_H
21 | #define MODEL_NORMALS_H
22 |
23 | float kv6_normals[256][3]
24 | = {{0.08847, 0.00000, -0.99608}, {-0.11277, 0.10331, -0.98824}, {0.01723, -0.19630, -0.98039},
25 | {0.14158, 0.18467, -0.97255}, {-0.25930, -0.04587, -0.96471}, {0.24514, -0.15594, -0.95686},
26 | {-0.08183, 0.30441, -0.94902}, {-0.15575, -0.29988, -0.94118}, {0.33723, 0.12315, -0.93333},
27 | {-0.35012, 0.14452, -0.92549}, {0.16843, -0.35994, -0.91765}, {0.12421, 0.39601, -0.90980},
28 | {-0.37361, -0.21652, -0.90196}, {0.43739, -0.09616, -0.89412}, {-0.26638, 0.37889, -0.88627},
29 | {-0.06141, -0.47391, -0.87843}, {0.37622, 0.31708, -0.87059}, {-0.50521, 0.02089, -0.86275},
30 | {0.36773, -0.36594, -0.85490}, {-0.02455, 0.53093, -0.84706}, {-0.34842, -0.41752, -0.83922},
31 | {0.55075, 0.07410, -0.83137}, {-0.46565, 0.32399, -0.82353}, {0.12697, -0.56439, -0.81569},
32 | {0.29304, 0.51139, -0.80784}, {-0.57162, -0.18236, -0.80000}, {0.55404, -0.25598, -0.79216},
33 | {-0.23950, 0.57227, -0.78431}, {-0.21328, -0.59296, -0.77647}, {0.56625, 0.29760, -0.76863},
34 | {-0.62757, 0.16543, -0.76078}, {0.35592, -0.55354, -0.75294}, {0.11297, 0.65732, -0.74510},
35 | {-0.53416, -0.41368, -0.73725}, {0.68174, -0.05648, -0.72941}, {-0.47015, 0.50823, -0.72157},
36 | {0.00342, -0.70042, -0.71373}, {0.47592, 0.52463, -0.70588}, {-0.71300, -0.06608, -0.69804},
37 | {0.57641, -0.43747, -0.69020}, {-0.13084, 0.71922, -0.68235}, {-0.39321, -0.62484, -0.67451},
38 | {0.71885, 0.19701, -0.66667}, {-0.66931, 0.34348, -0.65882}, {0.26387, -0.71176, -0.65098},
39 | {0.28872, 0.70924, -0.64314}, {-0.69787, -0.33073, -0.63529}, {0.74409, -0.22941, -0.62745},
40 | {-0.39687, 0.67719, -0.61961}, {-0.16608, -0.77341, -0.61176}, {0.64979, 0.46158, -0.60392},
41 | {-0.79676, 0.09930, -0.59608}, {0.52417, -0.61581, -0.58824}, {0.02968, 0.81380, -0.58039},
42 | {-0.57548, -0.58396, -0.57255}, {0.82422, 0.04214, -0.56471}, {-0.64031, 0.52906, -0.55686},
43 | {0.11549, -0.82779, -0.54902}, {0.47690, 0.69260, -0.54118}, {-0.82436, -0.18968, -0.53333},
44 | {0.74025, -0.41940, -0.52549}, {-0.26401, 0.81384, -0.51765}, {-0.35702, -0.78271, -0.50980},
45 | {0.79620, 0.33778, -0.50196}, {-0.81951, 0.29026, -0.49412}, {0.41029, -0.77149, -0.48627},
46 | {0.21969, 0.85020, -0.47843}, {-0.73984, -0.48082, -0.47059}, {0.87440, -0.14589, -0.46275},
47 | {-0.54871, 0.70142, -0.45490}, {-0.06951, -0.89180, -0.44706}, {0.65649, 0.61328, -0.43922},
48 | {-0.90213, -0.00880, -0.43137}, {0.67391, -0.60537, -0.42353}, {-0.08835, 0.90521, -0.41569},
49 | {-0.54844, -0.72998, -0.40784}, {0.90091, 0.16843, -0.40000}, {-0.78095, 0.48614, -0.39216},
50 | {0.24835, -0.88917, -0.38431}, {0.41896, 0.82628, -0.37647}, {-0.87002, -0.32738, -0.36863},
51 | {0.86552, -0.34743, -0.36078}, {-0.40482, 0.84354, -0.35294}, {-0.27215, -0.89824, -0.34510},
52 | {0.80988, 0.47995, -0.33725}, {-0.92410, 0.19373, -0.32941}, {0.55211, -0.76926, -0.32157},
53 | {0.11283, 0.94279, -0.31373}, {-0.72198, -0.62063, -0.30588}, {0.95408, -0.03014, -0.29804},
54 | {-0.68488, 0.66838, -0.29020}, {0.05366, -0.95781, -0.28235}, {0.60886, 0.74426, -0.27451},
55 | {-0.95388, -0.13783, -0.26667}, {0.79823, -0.54391, -0.25882}, {-0.22166, 0.94227, -0.25098},
56 | {-0.47403, -0.84628, -0.24314}, {0.92302, 0.30442, -0.23529}, {-0.88794, 0.39979, -0.22745},
57 | {0.38540, -0.89624, -0.21961}, {0.32179, 0.92283, -0.21176}, {-0.86210, -0.46389, -0.20392},
58 | {0.95059, -0.24068, -0.19608}, {-0.53920, 0.82087, -0.18824}, {-0.15713, -0.97096, -0.18039},
59 | {0.77284, 0.61069, -0.17255}, {-0.98372, 0.07184, -0.16471}, {0.67770, -0.71841, -0.15686},
60 | {-0.01446, 0.98873, -0.14902}, {-0.65798, -0.73968, -0.14118}, {0.98590, 0.10107, -0.13333},
61 | {-0.79607, 0.59205, -0.12549}, {0.18725, -0.97524, -0.11765}, {0.52116, 0.84636, -0.10980},
62 | {-0.95680, -0.27227, -0.10196}, {0.89012, -0.44589, -0.09412}, {-0.35541, 0.93072, -0.08627},
63 | {-0.36687, -0.92696, -0.07843}, {0.89720, 0.43595, -0.07059}, {-0.95655, 0.28474, -0.06275},
64 | {0.51323, -0.85649, -0.05490}, {0.20019, 0.97863, -0.04706}, {-0.80894, -0.58658, -0.03922},
65 | {0.99299, -0.11394, -0.03137}, {-0.65538, 0.75493, -0.02353}, {-0.02670, -0.99952, -0.01569},
66 | {0.69492, 0.71905, -0.00784}, {-0.99815, -0.06079, 0.00000}, {0.77705, -0.62939, 0.00784},
67 | {-0.14781, 0.98889, 0.01569}, {-0.55891, -0.82889, 0.02353}, {0.97182, 0.23361, 0.03137},
68 | {-0.87415, 0.48407, 0.03922}, {0.31748, -0.94710, 0.04706}, {0.40549, 0.91245, 0.05490},
69 | {-0.91492, -0.39872, 0.06275}, {0.94347, -0.32385, 0.07059}, {-0.47665, 0.87559, 0.07843},
70 | {-0.23982, -0.96698, 0.08627}, {0.82943, 0.55063, 0.09412}, {-0.98277, 0.15414, 0.10196},
71 | {0.62003, -0.77686, 0.10980}, {0.06751, 0.99076, 0.11765}, {-0.71833, -0.68429, 0.12549},
72 | {0.99088, 0.01933, 0.13333}, {-0.74289, 0.65436, 0.14118}, {0.10564, -0.98317, 0.14902},
73 | {0.58551, 0.79535, 0.15686}, {-0.96773, -0.19071, 0.16471}, {0.84125, -0.51237, 0.17255},
74 | {-0.27382, 0.94471, 0.18039}, {-0.43558, -0.88025, 0.18824}, {0.91435, 0.35428, 0.19608},
75 | {-0.91204, 0.35582, 0.20392}, {0.43142, -0.87695, 0.21176}, {0.27377, 0.93639, 0.21961},
76 | {-0.83285, -0.50461, 0.22745}, {0.95314, -0.19014, 0.23529}, {-0.57324, 0.78248, 0.24314},
77 | {-0.10565, -0.96221, 0.25098}, {0.72631, 0.63678, 0.25882}, {-0.96356, 0.02103, 0.26667},
78 | {0.69470, -0.66486, 0.27451}, {-0.06300, 0.95724, 0.28235}, {-0.59869, -0.74656, 0.29020},
79 | {0.94337, 0.14572, 0.29804}, {-0.79197, 0.52841, 0.30588}, {0.22643, -0.92212, 0.31373},
80 | {0.45466, 0.83059, 0.32157}, {-0.89375, -0.30446, 0.32941}, {0.86215, -0.37810, 0.33725},
81 | {-0.37916, 0.85857, 0.34510}, {-0.29944, -0.88644, 0.35294}, {0.81695, 0.44992, 0.36078},
82 | {-0.90332, 0.21936, 0.36863}, {0.51615, -0.76932, 0.37647}, {0.13859, 0.91274, 0.38431},
83 | {-0.71617, -0.57734, 0.39216}, {0.91469, -0.05784, 0.40000}, {-0.63299, 0.65802, 0.40784},
84 | {0.02218, -0.90924, 0.41569}, {0.59544, 0.68269, 0.42353}, {-0.89653, -0.10077, 0.43137},
85 | {0.72607, -0.52906, 0.43922}, {-0.17724, 0.87677, 0.44706}, {-0.45951, -0.76283, 0.45490},
86 | {0.85023, 0.25095, 0.46275}, {-0.79273, 0.38747, 0.47059}, {0.32126, -0.81725, 0.47843},
87 | {0.31361, 0.81559, 0.48627}, {-0.77822, -0.38758, 0.49412}, {0.83131, -0.23865, 0.50196},
88 | {-0.44938, 0.73359, 0.50980}, {-0.16328, -0.83987, 0.51765}, {0.68387, 0.50615, 0.52549},
89 | {-0.84129, 0.08822, 0.53333}, {0.55744, -0.62959, 0.54118}, {0.01416, 0.83569, 0.54902},
90 | {-0.57136, -0.60287, 0.55686}, {0.82324, 0.05822, 0.56471}, {-0.64211, 0.50979, 0.57255},
91 | {0.12824, -0.80418, 0.58039}, {0.44554, 0.67489, 0.58824}, {-0.77882, -0.19528, 0.59608},
92 | {0.70101, -0.37929, 0.60392}, {-0.25873, 0.74753, 0.61176}, {-0.31173, -0.72035, 0.61961},
93 | {0.71074, 0.31804, 0.62745}, {-0.73285, 0.24358, 0.63529}, {0.37268, -0.66894, 0.64314},
94 | {0.17553, 0.73852, 0.65098}, {-0.62267, -0.42218, 0.65882}, {0.73745, -0.10829, 0.66667},
95 | {-0.46614, 0.57249, 0.67451}, {-0.04259, -0.72978, 0.68235}, {0.51906, 0.50419, 0.69020},
96 | {-0.71575, -0.02094, 0.69804}, {0.53607, -0.46299, 0.70588}, {-0.08161, 0.69565, 0.71373},
97 | {-0.40500, -0.56152, 0.72157}, {0.66985, 0.13880, 0.72941}, {-0.58041, 0.34580, 0.73726},
98 | {0.19190, -0.63875, 0.74510}, {0.28611, 0.59264, 0.75294}, {-0.60285, -0.24036, 0.76078},
99 | {0.59818, -0.22669, 0.76863}, {-0.28366, 0.56270, 0.77647}, {-0.16828, -0.59710, 0.78431},
100 | {0.51888, 0.32133, 0.79216}, {-0.58952, 0.11164, 0.80000}, {0.35293, -0.47205, 0.80784},
101 | {0.05754, 0.57563, 0.81569}, {-0.42289, -0.37810, 0.82353}, {0.55567, -0.00672, 0.83137},
102 | {-0.39651, 0.37215, 0.83922}, {0.04006, -0.52999, 0.84706}, {0.32060, 0.40787, 0.85490},
103 | {-0.49894, -0.08205, 0.86275}, {0.41192, -0.26907, 0.87059}, {-0.11847, 0.46295, 0.87843},
104 | {-0.21843, -0.40842, 0.88627}, {0.42248, 0.14853, 0.89412}, {-0.39713, 0.16957, 0.90196},
105 | {0.17136, -0.37801, 0.90980}, {0.12351, 0.37772, 0.91765}, {-0.32999, -0.18594, 0.92549},
106 | {0.34968, -0.08132, 0.93333}, {-0.19099, 0.27876, 0.94118}, {-0.04428, -0.31209, 0.94902},
107 | {0.22441, 0.18454, 0.95686}, {-0.26295, 0.01406, 0.96471}, {0.16295, -0.16612, 0.97255},
108 | {-0.00672, 0.19694, 0.98039}, {-0.09940, -0.11623, 0.98824}, {0.08782, 0.01074, 0.99608},
109 | {0.00000, 0.00000, 1.00000}};
110 |
111 | #endif
112 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | include(FetchContent)
2 |
3 | FetchContent_Declare(
4 | cglm
5 | GIT_REPOSITORY https://github.com/recp/cglm
6 | GIT_TAG v0.8.5
7 | )
8 |
9 | set(CGLM_STATIC ON CACHE INTERNAL "")
10 | set(CGLM_USE_C99 ON CACHE INTERNAL "")
11 | set(MIRRORS https://butter.penguins.win/mirror)
12 | FetchContent_MakeAvailable(cglm)
13 |
14 | FetchContent_Declare(
15 | vxl
16 | GIT_REPOSITORY https://github.com/xtreme8000/libvxl
17 | GIT_TAG origin/master
18 | )
19 |
20 | FetchContent_MakeAvailable(vxl)
21 |
22 | macro(download_file_if_it_doesnt_exist filename url)
23 | set(argn ${ARGN})
24 | list(LENGTH argn no_fallback)
25 | if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${filename})
26 | message(STATUS "Downloading ${filename}")
27 | file(DOWNLOAD ${url} ${CMAKE_CURRENT_SOURCE_DIR}/${filename} STATUS stat)
28 | list(GET stat 0 success)
29 | list(GET stat 1 error)
30 | if (NOT ${success})
31 | message(STATUS "Downloaded ${filename} successfully")
32 | else()
33 | file(REMOVE ${CMAKE_CURRENT_SOURCE_DIR}/${filename})
34 | message(WARNING "Failed to download ${filename} (${error})")
35 |
36 | if(${no_fallback} EQUAL 0)
37 | foreach(mirror ${MIRRORS})
38 | string(SHA256 mirror_url_hash ${url})
39 | set(mirror_url ${mirror}/${mirror_url_hash})
40 | message(STATUS "Trying alternate URL ${mirror_url}")
41 | download_file_if_it_doesnt_exist(${filename} ${mirror_url} 1)
42 | if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${filename})
43 | # Success
44 | break()
45 | endif()
46 | endforeach()
47 |
48 | if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${filename})
49 | # Everything failed, exit
50 | message(FATAL_ERROR "Failed to download ${filename} from all sources.")
51 | endif()
52 | endif()
53 | endif()
54 | endif()
55 | endmacro(download_file_if_it_doesnt_exist)
56 |
57 | download_file_if_it_doesnt_exist(../bsresources.zip http://aos.party/bsresources.zip)
58 |
59 | list(APPEND CLIENT_SOURCES aabb.c)
60 | list(APPEND CLIENT_SOURCES camera.c)
61 | list(APPEND CLIENT_SOURCES cameracontroller.c)
62 | list(APPEND CLIENT_SOURCES chunk.c)
63 | list(APPEND CLIENT_SOURCES config.c)
64 | list(APPEND CLIENT_SOURCES dr_wav.c)
65 | list(APPEND CLIENT_SOURCES file.c)
66 | list(APPEND CLIENT_SOURCES font.c)
67 | list(APPEND CLIENT_SOURCES glx.c)
68 | list(APPEND CLIENT_SOURCES grenade.c)
69 | list(APPEND CLIENT_SOURCES http.c)
70 | list(APPEND CLIENT_SOURCES gmi.c)
71 | list(APPEND CLIENT_SOURCES hud.c)
72 | list(APPEND CLIENT_SOURCES ini.c)
73 | list(APPEND CLIENT_SOURCES list.c)
74 | list(APPEND CLIENT_SOURCES main.c)
75 | list(APPEND CLIENT_SOURCES map.c)
76 | list(APPEND CLIENT_SOURCES matrix.c)
77 | list(APPEND CLIENT_SOURCES model.c)
78 | list(APPEND CLIENT_SOURCES network.c)
79 | list(APPEND CLIENT_SOURCES parson.c)
80 | list(APPEND CLIENT_SOURCES particle.c)
81 | list(APPEND CLIENT_SOURCES player.c)
82 | list(APPEND CLIENT_SOURCES sound.c)
83 | list(APPEND CLIENT_SOURCES stb_truetype.c)
84 | list(APPEND CLIENT_SOURCES texture.c)
85 | list(APPEND CLIENT_SOURCES tracer.c)
86 | list(APPEND CLIENT_SOURCES weapon.c)
87 | list(APPEND CLIENT_SOURCES window.c)
88 | list(APPEND CLIENT_SOURCES utils.c)
89 | list(APPEND CLIENT_SOURCES ping.c)
90 | list(APPEND CLIENT_SOURCES log.c)
91 | list(APPEND CLIENT_SOURCES minheap.c)
92 | list(APPEND CLIENT_SOURCES hashtable.c)
93 | list(APPEND CLIENT_SOURCES rpc.c)
94 | list(APPEND CLIENT_SOURCES tesselator.c)
95 | list(APPEND CLIENT_SOURCES microui.c)
96 | list(APPEND CLIENT_SOURCES channel.c)
97 | list(APPEND CLIENT_SOURCES entitysystem.c)
98 | list(APPEND CLIENT_SOURCES ${BetterSpades_SOURCE_DIR}/resources/icon.rc)
99 |
100 | add_executable(client ${CLIENT_SOURCES})
101 |
102 | if(CMAKE_BUILD_TYPE STREQUAL "Release")
103 | set_property(TARGET client PROPERTY WIN32_EXECUTABLE true)
104 | target_compile_definitions(client PRIVATE NDEBUG)
105 | endif()
106 |
107 | set(GIT_COMMIT_HASH "?")
108 |
109 | execute_process(
110 | COMMAND git describe --always --dirty
111 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
112 | OUTPUT_VARIABLE GIT_COMMIT_HASH
113 | OUTPUT_STRIP_TRAILING_WHITESPACE
114 | )
115 |
116 | include(CheckIPOSupported)
117 | check_ipo_supported(RESULT lto_supported OUTPUT error)
118 |
119 | if(lto_supported)
120 | message(STATUS "IPO / LTO enabled")
121 | set_property(TARGET client PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
122 | else()
123 | message(STATUS "IPO / LTO not supported: <${error}>")
124 | endif()
125 |
126 | target_compile_definitions(client PRIVATE GIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
127 | target_compile_definitions(client PRIVATE DR_WAV_IMPLEMENTATION)
128 | target_compile_definitions(client PRIVATE LOG_USE_COLOR)
129 |
130 | if(ENABLE_TOUCH)
131 | target_compile_definitions(client PRIVATE USE_TOUCH)
132 | endif()
133 | if(ENABLE_ANDROID_FILE)
134 | target_compile_definitions(client PRIVATE USE_ANDROID_FILE)
135 | endif()
136 |
137 | target_compile_definitions(client PRIVATE BETTERSPADES_MAJOR=${BETTERSPADES_MAJOR})
138 | target_compile_definitions(client PRIVATE BETTERSPADES_MINOR=${BETTERSPADES_MINOR})
139 | target_compile_definitions(client PRIVATE BETTERSPADES_PATCH=${BETTERSPADES_PATCH})
140 | target_compile_definitions(client PRIVATE BETTERSPADES_VERSION="v${BETTERSPADES_MAJOR}.${BETTERSPADES_MINOR}.${BETTERSPADES_PATCH}")
141 |
142 |
143 | set_target_properties(
144 | client PROPERTIES
145 | RUNTIME_OUTPUT_DIRECTORY ${BetterSpades_SOURCE_DIR}/build/BetterSpades
146 | C_STANDARD 99
147 | )
148 |
149 | set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${BetterSpades_SOURCE_DIR}/deps)
150 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${BetterSpades_SOURCE_DIR}/cmake/Modules)
151 | set(OpenGL_GL_PREFERENCE LEGACY)
152 | if(ENABLE_GLFW)
153 | find_package(glfw3 REQUIRED)
154 | target_link_libraries(client glfw3::glfw3)
155 | target_compile_definitions(client PRIVATE USE_GLFW)
156 | endif()
157 | if(ENABLE_SDL)
158 | find_package(SDL2 REQUIRED)
159 | target_link_libraries(client ${SDL2_LIBRARY})
160 | target_compile_definitions(client PRIVATE USE_SDL)
161 | endif()
162 | if(ENABLE_SOUND)
163 | find_package(OpenAL REQUIRED)
164 | target_link_libraries(client ${OPENAL_LIBRARY})
165 | target_compile_definitions(client PRIVATE USE_SOUND)
166 | endif()
167 | find_package(enet REQUIRED)
168 | find_package(deflate REQUIRED)
169 | find_package(Threads REQUIRED)
170 | if(NOT ENABLE_OPENGLES)
171 | find_package(OpenGL REQUIRED)
172 | find_package(GLEW REQUIRED)
173 | target_link_libraries(client GLEW::GLEW)
174 | else()
175 | find_package(OpenGL REQUIRED COMPONENTS EGL)
176 | target_link_libraries(client OpenGL::EGL)
177 | target_compile_definitions(client PRIVATE OPENGL_ES)
178 | endif()
179 | if(ENABLE_RPC)
180 | target_link_libraries(client discord-rpc stdc++)
181 | target_compile_definitions(client PRIVATE USE_RPC DISCORD_DISABLE_IO_THREAD)
182 | endif()
183 | if(DEFINED ENV{BUILD_NUMBER})
184 | target_compile_definitions(client PRIVATE JENKINS_BUILD="$ENV{BUILD_NUMBER}")
185 | endif()
186 |
187 |
188 | if(WIN32)
189 | target_compile_definitions(client PRIVATE LIBDEFLATE_STATIC)
190 | endif()
191 |
192 | target_link_libraries(client ${CMAKE_THREAD_LIBS_INIT} ${OPENGL_LIBRARIES} enet::enet deflate::deflate m cglm vxl)
193 | target_include_directories(client PRIVATE ${OPENAL_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR} ${OPENGL_EGL_INCLUDE_DIRS})
194 |
195 | add_custom_command(
196 | TARGET client
197 | POST_BUILD
198 | COMMENT "Copying resources..."
199 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${BetterSpades_SOURCE_DIR}/resources ${BetterSpades_SOURCE_DIR}/build/BetterSpades
200 | )
201 |
202 | add_custom_command(
203 | TARGET client
204 | POST_BUILD
205 | COMMENT "Extracting additional third-party assets..."
206 | DEPENDS ${BetterSpades_SOURCE_DIR}/bsresources.zip
207 | WORKING_DIRECTORY ${BetterSpades_SOURCE_DIR}/build/BetterSpades
208 | COMMAND ${CMAKE_COMMAND} -E tar xzf ${BetterSpades_SOURCE_DIR}/bsresources.zip
209 | )
210 |
211 | add_custom_command(
212 | TARGET client
213 | POST_BUILD
214 | COMMENT "Copying overrides..."
215 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${BetterSpades_SOURCE_DIR}/resources.override ${BetterSpades_SOURCE_DIR}/build/BetterSpades
216 | )
217 |
218 | install(
219 | TARGETS client
220 | RUNTIME
221 | DESTINATION .
222 | )
223 |
224 | install(
225 | FILES "${CMAKE_BINARY_DIR}/BetterSpades/config.ini" "${CMAKE_BINARY_DIR}/BetterSpades/OpenAL32.dll"
226 | DESTINATION .
227 | PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
228 | GROUP_EXECUTE GROUP_READ
229 | )
230 |
231 | install(
232 | DIRECTORY "${CMAKE_BINARY_DIR}/BetterSpades/fonts"
233 | DESTINATION .
234 | FILES_MATCHING PATTERN "*.ttf"
235 | )
236 |
237 | install(
238 | DIRECTORY "${CMAKE_BINARY_DIR}/BetterSpades/kv6"
239 | DESTINATION .
240 | FILES_MATCHING PATTERN "*.kv6"
241 | )
242 |
243 | install(
244 | DIRECTORY "${CMAKE_BINARY_DIR}/BetterSpades/png"
245 | DESTINATION .
246 | FILES_MATCHING PATTERN "*.png"
247 | )
248 |
249 | install(
250 | DIRECTORY "${CMAKE_BINARY_DIR}/BetterSpades/wav"
251 | DESTINATION .
252 | FILES_MATCHING PATTERN "*.wav"
253 | )
254 |
255 | install(
256 | DIRECTORY
257 | DESTINATION "cache"
258 | )
259 |
260 | install(
261 | DIRECTORY
262 | DESTINATION "logs"
263 | )
264 |
265 | install(
266 | DIRECTORY
267 | DESTINATION "screenshots"
268 | )
269 |
270 | set(CPACK_GENERATOR NSIS)
271 | set(CPACK_PACKAGE_NAME "BetterSpades")
272 | set(CPACK_PACKAGE_VENDOR "github.com")
273 | set(CPACK_PACKAGE_VERSION "v${BETTERSPADES_MAJOR}.${BETTERSPADES_MINOR}.${BETTERSPADES_PATCH}")
274 | set(CPACK_PACKAGE_VERSION_MAJOR "${BETTERSPADES_MAJOR}")
275 | set(CPACK_PACKAGE_VERSION_MINOR "${BETTERSPADES_MINOR}")
276 | set(CPACK_PACKAGE_VERSION_PATCH "${BETTERSPADES_PATCH}")
277 | set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}")
278 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
279 | set(CPACK_STRIP_FILES TRUE)
280 | set(CPACK_NSIS_MENU_LINKS "client" "BetterSpades")
281 | set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
282 | set(CPACK_PACKAGE_CHECKSUM SHA256)
283 |
284 | INCLUDE(CPack)
285 |
--------------------------------------------------------------------------------
/src/ini.c:
--------------------------------------------------------------------------------
1 | /* inih -- simple .INI file parser
2 |
3 | SPDX-License-Identifier: BSD-3-Clause
4 |
5 | Copyright (C) 2009-2020, Ben Hoyt
6 |
7 | inih is released under the New BSD license (see LICENSE.txt). Go to the project
8 | home page for more info:
9 |
10 | https://github.com/benhoyt/inih
11 |
12 | */
13 |
14 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
15 | #define _CRT_SECURE_NO_WARNINGS
16 | #endif
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | #include "ini.h"
23 |
24 | #if !INI_USE_STACK
25 | #if INI_CUSTOM_ALLOCATOR
26 | #include
27 | void* ini_malloc(size_t size);
28 | void ini_free(void* ptr);
29 | void* ini_realloc(void* ptr, size_t size);
30 | #else
31 | #include
32 | #define ini_malloc malloc
33 | #define ini_free free
34 | #define ini_realloc realloc
35 | #endif
36 | #endif
37 |
38 | #define MAX_SECTION 50
39 | #define MAX_NAME 50
40 |
41 | /* Used by ini_parse_string() to keep track of string parsing state. */
42 | typedef struct {
43 | const char* ptr;
44 | size_t num_left;
45 | } ini_parse_string_ctx;
46 |
47 | /* Strip whitespace chars off end of given string, in place. Return s. */
48 | static char* rstrip(char* s)
49 | {
50 | char* p = s + strlen(s);
51 | while (p > s && isspace((unsigned char)(*--p)))
52 | *p = '\0';
53 | return s;
54 | }
55 |
56 | /* Return pointer to first non-whitespace char in given string. */
57 | static char* lskip(const char* s)
58 | {
59 | while (*s && isspace((unsigned char)(*s)))
60 | s++;
61 | return (char*)s;
62 | }
63 |
64 | /* Return pointer to first char (of chars) or inline comment in given string,
65 | or pointer to NUL at end of string if neither found. Inline comment must
66 | be prefixed by a whitespace character to register as a comment. */
67 | static char* find_chars_or_comment(const char* s, const char* chars)
68 | {
69 | #if INI_ALLOW_INLINE_COMMENTS
70 | int was_space = 0;
71 | while (*s && (!chars || !strchr(chars, *s)) &&
72 | !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
73 | was_space = isspace((unsigned char)(*s));
74 | s++;
75 | }
76 | #else
77 | while (*s && (!chars || !strchr(chars, *s))) {
78 | s++;
79 | }
80 | #endif
81 | return (char*)s;
82 | }
83 |
84 | /* Similar to strncpy, but ensures dest (size bytes) is
85 | NUL-terminated, and doesn't pad with NULs. */
86 | static char* strncpy0(char* dest, const char* src, size_t size)
87 | {
88 | /* Could use strncpy internally, but it causes gcc warnings (see issue #91) */
89 | size_t i;
90 | for (i = 0; i < size - 1 && src[i]; i++)
91 | dest[i] = src[i];
92 | dest[i] = '\0';
93 | return dest;
94 | }
95 |
96 | /* See documentation in header file. */
97 | int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
98 | void* user)
99 | {
100 | /* Uses a fair bit of stack (use heap instead if you need to) */
101 | #if INI_USE_STACK
102 | char line[INI_MAX_LINE];
103 | size_t max_line = INI_MAX_LINE;
104 | #else
105 | char* line;
106 | size_t max_line = INI_INITIAL_ALLOC;
107 | #endif
108 | #if INI_ALLOW_REALLOC && !INI_USE_STACK
109 | char* new_line;
110 | size_t offset;
111 | #endif
112 | char section[MAX_SECTION] = "";
113 | char prev_name[MAX_NAME] = "";
114 |
115 | char* start;
116 | char* end;
117 | char* name;
118 | char* value;
119 | int lineno = 0;
120 | int error = 0;
121 |
122 | #if !INI_USE_STACK
123 | line = (char*)ini_malloc(INI_INITIAL_ALLOC);
124 | if (!line) {
125 | return -2;
126 | }
127 | #endif
128 |
129 | #if INI_HANDLER_LINENO
130 | #define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
131 | #else
132 | #define HANDLER(u, s, n, v) handler(u, s, n, v)
133 | #endif
134 |
135 | /* Scan through stream line by line */
136 | while (reader(line, (int)max_line, stream) != NULL) {
137 | #if INI_ALLOW_REALLOC && !INI_USE_STACK
138 | offset = strlen(line);
139 | while (offset == max_line - 1 && line[offset - 1] != '\n') {
140 | max_line *= 2;
141 | if (max_line > INI_MAX_LINE)
142 | max_line = INI_MAX_LINE;
143 | new_line = ini_realloc(line, max_line);
144 | if (!new_line) {
145 | ini_free(line);
146 | return -2;
147 | }
148 | line = new_line;
149 | if (reader(line + offset, (int)(max_line - offset), stream) == NULL)
150 | break;
151 | if (max_line >= INI_MAX_LINE)
152 | break;
153 | offset += strlen(line + offset);
154 | }
155 | #endif
156 |
157 | lineno++;
158 |
159 | start = line;
160 | #if INI_ALLOW_BOM
161 | if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
162 | (unsigned char)start[1] == 0xBB &&
163 | (unsigned char)start[2] == 0xBF) {
164 | start += 3;
165 | }
166 | #endif
167 | start = lskip(rstrip(start));
168 |
169 | if (strchr(INI_START_COMMENT_PREFIXES, *start)) {
170 | /* Start-of-line comment */
171 | }
172 | #if INI_ALLOW_MULTILINE
173 | else if (*prev_name && *start && start > line) {
174 | #if INI_ALLOW_INLINE_COMMENTS
175 | end = find_chars_or_comment(start, NULL);
176 | if (*end)
177 | *end = '\0';
178 | rstrip(start);
179 | #endif
180 | /* Non-blank line with leading whitespace, treat as continuation
181 | of previous name's value (as per Python configparser). */
182 | if (!HANDLER(user, section, prev_name, start) && !error)
183 | error = lineno;
184 | }
185 | #endif
186 | else if (*start == '[') {
187 | /* A "[section]" line */
188 | end = find_chars_or_comment(start + 1, "]");
189 | if (*end == ']') {
190 | *end = '\0';
191 | strncpy0(section, start + 1, sizeof(section));
192 | *prev_name = '\0';
193 | #if INI_CALL_HANDLER_ON_NEW_SECTION
194 | if (!HANDLER(user, section, NULL, NULL) && !error)
195 | error = lineno;
196 | #endif
197 | }
198 | else if (!error) {
199 | /* No ']' found on section line */
200 | error = lineno;
201 | }
202 | }
203 | else if (*start) {
204 | /* Not a comment, must be a name[=:]value pair */
205 | end = find_chars_or_comment(start, "=:");
206 | if (*end == '=' || *end == ':') {
207 | *end = '\0';
208 | name = rstrip(start);
209 | value = end + 1;
210 | #if INI_ALLOW_INLINE_COMMENTS
211 | end = find_chars_or_comment(value, NULL);
212 | if (*end)
213 | *end = '\0';
214 | #endif
215 | value = lskip(value);
216 | rstrip(value);
217 |
218 | /* Valid name[=:]value pair found, call handler */
219 | strncpy0(prev_name, name, sizeof(prev_name));
220 | if (!HANDLER(user, section, name, value) && !error)
221 | error = lineno;
222 | }
223 | else if (!error) {
224 | /* No '=' or ':' found on name[=:]value line */
225 | #if INI_ALLOW_NO_VALUE
226 | *end = '\0';
227 | name = rstrip(start);
228 | if (!HANDLER(user, section, name, NULL) && !error)
229 | error = lineno;
230 | #else
231 | error = lineno;
232 | #endif
233 | }
234 | }
235 |
236 | #if INI_STOP_ON_FIRST_ERROR
237 | if (error)
238 | break;
239 | #endif
240 | }
241 |
242 | #if !INI_USE_STACK
243 | ini_free(line);
244 | #endif
245 |
246 | return error;
247 | }
248 |
249 | /* See documentation in header file. */
250 | int ini_parse_file(FILE* file, ini_handler handler, void* user)
251 | {
252 | return ini_parse_stream((ini_reader)fgets, file, handler, user);
253 | }
254 |
255 | /* See documentation in header file. */
256 | int ini_parse(const char* filename, ini_handler handler, void* user)
257 | {
258 | FILE* file;
259 | int error;
260 |
261 | file = fopen(filename, "r");
262 | if (!file)
263 | return -1;
264 | error = ini_parse_file(file, handler, user);
265 | fclose(file);
266 | return error;
267 | }
268 |
269 | /* An ini_reader function to read the next line from a string buffer. This
270 | is the fgets() equivalent used by ini_parse_string(). */
271 | static char* ini_reader_string(char* str, int num, void* stream) {
272 | ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream;
273 | const char* ctx_ptr = ctx->ptr;
274 | size_t ctx_num_left = ctx->num_left;
275 | char* strp = str;
276 | char c;
277 |
278 | if (ctx_num_left == 0 || num < 2)
279 | return NULL;
280 |
281 | while (num > 1 && ctx_num_left != 0) {
282 | c = *ctx_ptr++;
283 | ctx_num_left--;
284 | *strp++ = c;
285 | if (c == '\n')
286 | break;
287 | num--;
288 | }
289 |
290 | *strp = '\0';
291 | ctx->ptr = ctx_ptr;
292 | ctx->num_left = ctx_num_left;
293 | return str;
294 | }
295 |
296 | /* See documentation in header file. */
297 | int ini_parse_string(const char* string, ini_handler handler, void* user) {
298 | ini_parse_string_ctx ctx;
299 |
300 | ctx.ptr = string;
301 | ctx.num_left = strlen(string);
302 | return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
303 | user);
304 | }
305 |
--------------------------------------------------------------------------------