655 lines
21 KiB
C++
655 lines
21 KiB
C++
#ifdef WIN32 // FUCK WINDOWS
|
|
#include "external/fix_win32_compatibility.h"
|
|
#undef PlaySound
|
|
#endif
|
|
|
|
#include <enet/enet.h>
|
|
|
|
#ifdef WIN32 // FUCK WINDOWS 2
|
|
#undef PlaySound
|
|
#undef Sound
|
|
#endif
|
|
#include <functional>
|
|
#include "glfw_keycodes_to_string.h"
|
|
#include "raylib.h"
|
|
#include "raymath.h"
|
|
#include <stdint.h>
|
|
#include <bitset>
|
|
#include <cstdint>
|
|
#include <list>
|
|
#define FOV 90
|
|
#define WIDTH 1024.0
|
|
#define HEIGHT 600.0
|
|
#define ASPECT WIDTH / HEIGHT
|
|
#define CHUNK_SIZE 16 // W & H
|
|
#define WORLD_HEIGHT 128
|
|
#define CHUNK_DATA_SIZE CHUNK_SIZE*CHUNK_SIZE*WORLD_HEIGHT
|
|
#define CHUNK_SIZE_SQR CHUNK_SIZE*CHUNK_SIZE
|
|
#define MAX_WORLD_SIZE 16
|
|
#define MAX_WORLD_AREA MAX_WORLD_SIZE*MAX_WORLD_SIZE
|
|
#define WORLD_SIZE_BLOCKS MAX_WORLD_SIZE * CHUNK_SIZE
|
|
#define ATLAS_SIZE_W 16
|
|
#define ATLAS_SIZE_H 16
|
|
#define ITEM_ATLAS_SIZE 16
|
|
#define ITEM_SIZE 16
|
|
#define PLAYER_HEIGHT 1.75f
|
|
#define PLAYER_RADIUS 0.25f
|
|
#define GRAVITY 20.0f
|
|
#define MOVE_SPEED 6.0f
|
|
#define JUMP_SPEED 8.0f
|
|
#define DELTA_SMOOTH 0.016f
|
|
#define MOUSE_SENS 0.0025f
|
|
#define PITCH_MIN -1.47f // ~-83 degrees
|
|
#define PITCH_MAX 1.47f // ~ 83 degrees
|
|
#define SMOOTH_FACTOR 12.0f // larger = snappier
|
|
#define BLOCK_AIR 0
|
|
#define BLOCK_STONE 1
|
|
#define BLOCK_GRASS 2
|
|
#define BLOCK_DIRT 3
|
|
#define BLOCK_SAND 4
|
|
#define BLOCK_WATERS 5
|
|
#define MAX_BLOCK_ID 28
|
|
#define CLOUD_FADE_BLOCKS CHUNK_SIZE*8
|
|
#define PORT 25565
|
|
#define MAX_MESSAGE_LENGTH 64
|
|
#define NET_ARG_NONE 0x00 // Invalid
|
|
#define NET_ARG_CHUNKF 0x01 // Byte 1 - chunk ID, uint8_t blocks[16*64*16], uint8_t highestBlock[16*16]
|
|
#define NET_ARG_BLOCK 0x02 // Player ID, block X, block Y, block Z, block type
|
|
#define NET_ARG_PLRCON 0x03 // Byte 1 - ID
|
|
#define NET_ARG_PLRDCN 0x04 // Byte 1 - ID
|
|
#define NET_ARG_PLRID 0x05 // Byte 1 - Server-assigned ID to the player
|
|
#define NET_ARG_ECHOMOVE 0x06 // Byte 1 - player ID, bytes 2-3 - echoed player X, bytes 4-5 - echoed player Y, bytes 6-7 - echoed player Z, byte 8 - player yaw
|
|
#define NET_ARG_PLRREG 0x07 // Same as ECHOMOVE, used as an answer to REQPLAYERS
|
|
#define NET_ARG_ECHOYAW 0x08 // Byte 1 - ID, byte 2 - yaw
|
|
#define NET_ARG_MESSAGEE 0x09 // Byte 1 - sender ID, byte 2 - length, rest is message (128b max)
|
|
#define NET_ARG_PLAYERMOVE 0x80 // Byte 1-2 - player X, byte 3-4 - player Y, byte 5-6 - player Z, byte 7 - player yaw
|
|
#define NET_ARG_BLOCKDELTA 0x81 // Block X, block Y, block Z, block type
|
|
#define NET_ARG_REQWORLD 0x82 // No additional data
|
|
#define NET_ARG_REQPLAYERS 0x83 // No additional data
|
|
#define NET_ARG_PLAYERYAW 0x84 // Byte 1 - yaw
|
|
#define NET_ARG_MESSAGEC 0x85 // All is message (64b max)
|
|
#define NET_ERROR_DSCN 0x00
|
|
#define NET_ERROR_NOTFOUND 0x01
|
|
#define NET_ERROR_FAILED 0x02
|
|
#define NET_ERROR_INTERNAL 0x03
|
|
#define GAME_NAME "CubeGame"
|
|
#define GAME_VERSION_INT 0
|
|
#define DEFAULT_FONT_SIZE 16
|
|
#define TPS 30
|
|
#define TPS_DIV 1.0 / TPS
|
|
#define RENDER_DISTANCE 16
|
|
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
|
|
#define MAX_HP 100
|
|
#define PATH_APPEND "resources/"
|
|
#define PATH_APPEND_USER "user/"
|
|
#define ITEMS 9
|
|
#define INVENTORY_WIDTH 8
|
|
#define INVENTORY_HEIGHT 6
|
|
#define INVENTORY_SIZE INVENTORY_WIDTH*INVENTORY_HEIGHT
|
|
#define WORLD_TIME_SECONDS (24*60)
|
|
#define WORLD_TIME_TICKS WORLD_TIME_SECONDS*TPS
|
|
enum BlockType {
|
|
B_Wood,
|
|
B_Stone,
|
|
B_Grass,
|
|
B_Dirt
|
|
};
|
|
typedef enum BlockType BlockType;
|
|
typedef struct BlockDef BlockDef;
|
|
enum BlockRendering {
|
|
R_None,
|
|
R_Normal,
|
|
R_TriSide,
|
|
R_Translucent,
|
|
R_TranslucentTriSide,
|
|
R_TranslucentAllSides
|
|
};
|
|
typedef enum BlockRendering BlockRendering;
|
|
struct BlockDef {
|
|
const std::string name;
|
|
BlockRendering render;
|
|
uint8_t textureTop;
|
|
uint8_t textureSide;
|
|
uint8_t textureBottom;
|
|
int hardness;
|
|
int min_tier;
|
|
BlockType type;
|
|
// Constructor with initializer list; textureSide/textureBottom default to textureTop if not provided.
|
|
BlockDef(
|
|
std::string _name,
|
|
BlockRendering render_ = R_None,
|
|
BlockType btype = B_Stone,
|
|
int _hardness = 1,
|
|
int _min_tier = 0,
|
|
uint8_t textureTop_ = 255,
|
|
uint8_t textureSide_ = 255,
|
|
uint8_t textureBottom_ = 255)
|
|
: name(_name),
|
|
render(render_),
|
|
hardness(_hardness),
|
|
min_tier(_min_tier),
|
|
textureTop(textureTop_),
|
|
textureSide(textureSide_ == 255 ? textureTop_ : textureSide_),
|
|
textureBottom(textureBottom_ == 255 ? textureTop_ : textureBottom_),
|
|
type(btype)
|
|
{}
|
|
};
|
|
enum GameState {
|
|
GAME_STATE_LOADING,
|
|
GAME_STATE_GAME,
|
|
GAME_STATE_MAINMENU,
|
|
GAME_STATE_WORLDSELECT,
|
|
GAME_STATE_MULTIPLAYERSELECT,
|
|
GAME_STATE_TRANSITION,
|
|
GAME_STATE_WORLD_CREATE,
|
|
GAME_STATE_OPTIONS
|
|
};
|
|
typedef enum GameState GameState;
|
|
typedef struct Chunk Chunk;
|
|
struct Chunk {
|
|
uint8_t x;
|
|
uint8_t z;
|
|
bool isDirty;
|
|
uint8_t blocks[CHUNK_DATA_SIZE];
|
|
uint16_t opaqueMask[CHUNK_DATA_SIZE/16];
|
|
uint16_t airMask[CHUNK_DATA_SIZE/16];
|
|
uint8_t highestBlock[CHUNK_SIZE*CHUNK_SIZE];
|
|
uint16_t light[CHUNK_DATA_SIZE];
|
|
};
|
|
#if !defined(SERVER)
|
|
typedef struct ChunkRenderData ChunkRenderData;
|
|
struct ChunkRenderData {
|
|
uint8_t sides[CHUNK_DATA_SIZE];
|
|
};
|
|
typedef struct MeshData MeshData;
|
|
struct MeshData {
|
|
float *positions; // xyz xyz ...
|
|
float *normals; // xyz ...
|
|
float *uvs; // uv uv ...
|
|
unsigned char *colors; // rgba rgba ...
|
|
unsigned short *indices; // triangles
|
|
unsigned short vertexCount;
|
|
unsigned short indexCount;
|
|
};
|
|
typedef struct ChunkMeshData ChunkMeshData;
|
|
struct ChunkMeshData {
|
|
uint8_t *positions; // xyz xyz ...
|
|
uint8_t *luminosity; // l l ...
|
|
float *uvs; // uv uv ...
|
|
unsigned short *indices; // triangles
|
|
unsigned short vertexCount;
|
|
unsigned short indexCount;
|
|
};
|
|
typedef struct UVCorners UVCorners;
|
|
struct UVCorners {
|
|
Vector2 corner0;
|
|
Vector2 corner1;
|
|
Vector2 corner2;
|
|
Vector2 corner3;
|
|
};
|
|
typedef struct Quad2D Quad2D;
|
|
struct Quad2D {
|
|
int x;
|
|
int y;
|
|
int w;
|
|
int h;
|
|
};
|
|
#endif
|
|
typedef struct Vector3I Vector3I;
|
|
struct Vector3I {
|
|
int x, y, z;
|
|
bool operator==(const Vector3I& other) const {
|
|
return (x == other.x && y == other.y && z == other.z);
|
|
};
|
|
};
|
|
typedef struct Vector3IHash Vector3IHash;
|
|
struct Vector3IHash {
|
|
size_t operator()(const Vector3I& p) const noexcept {
|
|
size_t h1 = std::hash<int>{}(p.x);
|
|
size_t h2 = std::hash<int>{}(p.y);
|
|
size_t h3 = std::hash<int>{}(p.z);
|
|
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
|
}
|
|
};
|
|
typedef struct Entity Entity;
|
|
struct Entity {
|
|
uint8_t type;
|
|
uint8_t id;
|
|
uint8_t damage_flash;
|
|
uint8_t data[16];
|
|
float smoothing;
|
|
float health;
|
|
float lifetime;
|
|
Vector3 position;
|
|
Vector3 velocity;
|
|
unsigned short yaw;
|
|
bool free;
|
|
};
|
|
typedef struct NetPlayer NetPlayer;
|
|
struct NetPlayer {
|
|
ENetPeer* peer;
|
|
int addr;
|
|
int port;
|
|
int id;
|
|
int yaw;
|
|
float x;
|
|
float y;
|
|
float z;
|
|
};
|
|
typedef struct MemInfo MemInfo;
|
|
struct MemInfo {
|
|
uint64_t resident;
|
|
uint64_t virtualSize;
|
|
uint64_t privateBytes;
|
|
};
|
|
enum ItemType {
|
|
IType_Generic,
|
|
IType_Block,
|
|
IType_Edible,
|
|
IType_Mining,
|
|
IType_Weapon,
|
|
IType_Special_Tag
|
|
};
|
|
typedef enum ItemType ItemType;
|
|
enum EntityPhysics {
|
|
Phys_Falling,
|
|
Phys_Floating
|
|
};
|
|
typedef enum EntityPhysics EntityPhysics;
|
|
typedef struct Item Item;
|
|
struct Item {
|
|
std::string id;
|
|
ItemType type;
|
|
int texture;
|
|
int tier;
|
|
Item(
|
|
std::string _id,
|
|
ItemType _type,
|
|
int _texture,
|
|
int _tier = 0)
|
|
: id(_id),
|
|
type(_type),
|
|
texture(_texture),
|
|
tier(_tier)
|
|
{}
|
|
};
|
|
typedef struct InventoryItem InventoryItem;
|
|
struct InventoryItem {
|
|
Item* item = nullptr;
|
|
int damage = -1;
|
|
int amount = 0;
|
|
};
|
|
typedef struct RecipeItem RecipeItem;
|
|
struct RecipeItem {
|
|
ItemType type;
|
|
std::string id;
|
|
int quantity = 1;
|
|
};
|
|
typedef struct Recipe Recipe;
|
|
struct Recipe {
|
|
std::string requiredStation;
|
|
std::list<RecipeItem> inputs;
|
|
std::list<RecipeItem> outputs;
|
|
};
|
|
typedef struct Particle Particle;
|
|
struct Particle {
|
|
Vector3 position;
|
|
Vector3 velocity;
|
|
EntityPhysics physicsType;
|
|
Texture2D texture;
|
|
int lifetime;
|
|
int data[8];
|
|
};
|
|
typedef struct World World;
|
|
struct World {
|
|
Chunk chunks[MAX_WORLD_AREA];
|
|
};
|
|
BlockDef&GetBlockDefinition(int id);
|
|
void LoadBlocks();
|
|
int GetBlock(World&world,int x,int y,int z);
|
|
int GetHighestBlock(World&world,int x,int z);
|
|
int GetSkyLight(World&world,int x,int y,int z);
|
|
int GetRLight(World&world,int x,int y,int z);
|
|
int GetGLight(World&world,int x,int y,int z);
|
|
int GetBLight(World&world,int x,int y,int z);
|
|
Color GetSunlightColor();
|
|
Color GetLight(World&world,int x,int y,int z);
|
|
Color GetLightMesher(World&world,int x,int y,int z);
|
|
bool CanTick(int blockType);
|
|
bool GetCloud(int x,int z);
|
|
bool IsTranslucent(int blockType);
|
|
void SetBlockChunk(Chunk *c,int x,int y,int z,int t);
|
|
void RebuildHeightmap(Chunk&c);
|
|
int GetBiome(int sx,int sy);
|
|
void SetBlockChunkFast(Chunk *c,int i,int t);
|
|
void SetBlock(World&world,int x,int y,int z,int t);
|
|
void SetLightChunk(Chunk *c,int x,int y,int z,uint8_t sky,uint8_t r,uint8_t g,uint8_t b);
|
|
void SetLight(World&world,int x,int y,int z,uint8_t sky,uint8_t r,uint8_t g,uint8_t b);
|
|
void InitWorldgen(int worldType);
|
|
Vector3 WorldPosition(int cx,int cz,int localX,int y,int localZ);
|
|
Chunk GenerateChunk(int _x,int _y);
|
|
void GenerateWorldAdditional(World&world);
|
|
void TickBlock(World&world,int wx,int wy,int wz);
|
|
void TickChunk(Chunk *chunk,World&world,int wx,int wz);
|
|
void RebuildOpaqueMask(Chunk&chunk);
|
|
void RebuildLighting(World&world,int startX,int startZ);
|
|
#if !defined(SERVER)
|
|
ChunkRenderData GenerateCRDOpaque(Chunk&chunk,World&world);
|
|
ChunkRenderData GenerateCRDTranslucent(Chunk chunk,World&world);
|
|
ChunkRenderData GenerateCRDWater(Chunk chunk,World&world);
|
|
#endif
|
|
void SaveWorld(World&world,const char *path);
|
|
bool LoadWorld(World&world,const char *path);
|
|
extern long nsTotal;
|
|
void Debug_StartMeasure();
|
|
#if defined(WIN32)
|
|
bool Debug_GetProcessMemory(MemInfo&out);
|
|
#endif
|
|
#if defined(PLAYSTATION2)
|
|
bool Debug_GetProcessMemory(MemInfo&out);
|
|
#endif
|
|
#if !defined(WIN32)
|
|
bool Debug_GetProcessMemory(MemInfo&out);
|
|
#endif
|
|
#if !defined(SERVER)
|
|
extern Camera camera;
|
|
#endif
|
|
extern Camera3D camera;
|
|
#if !defined(SERVER)
|
|
extern Camera camera;
|
|
extern Font fnt;
|
|
extern Font fnt;
|
|
extern Texture2D terrain;
|
|
#endif
|
|
extern Texture2D terrain;
|
|
#if !defined(SERVER)
|
|
extern Texture2D terrain;
|
|
extern Texture2D terrain;
|
|
extern Texture2D playerTex;
|
|
extern Texture2D playerTex;
|
|
extern Texture2D bomb;
|
|
extern Sound nekit_idle;
|
|
void EntitiesInit();
|
|
extern bool online;
|
|
extern bool online;
|
|
#endif
|
|
#if !(!defined(SERVER))
|
|
extern bool online;
|
|
#endif
|
|
#if !defined(SERVER)
|
|
extern Vector3 player_position;
|
|
#endif
|
|
extern Vector3 player_position;
|
|
#if !defined(SERVER)
|
|
extern Vector3 player_velocity;
|
|
#endif
|
|
extern Vector3 player_velocity;
|
|
#if !defined(SERVER)
|
|
void TakeDamage(float amount);
|
|
void SetBlockNetwork(World&world,int bx,int by,int bz,int t);
|
|
#endif
|
|
Entity NewEntity();
|
|
void AddEntity(Entity ent);
|
|
void UpdateEntities(World&world,float dt);
|
|
extern float globalCounter;
|
|
#if !defined(SERVER)
|
|
void DrawEntities(float dt);
|
|
extern bool swap_mouse;
|
|
bool InputGetLMB();
|
|
bool InputGetLMBDown();
|
|
bool InputGetRMB();
|
|
Vector2 InputGetWalkAxis();
|
|
Vector2 InputGetLookAxis();
|
|
Vector2 InputGetDPAD();
|
|
void InputWriteControls();
|
|
void InputInit();
|
|
void InputUpdate();
|
|
extern int currentlySelected;
|
|
extern GameState state;
|
|
extern Texture2D cubemap;
|
|
int TryConnect(const char *hostname);
|
|
void GameModeCleanup();
|
|
void DrawBackground();
|
|
void InitMenu();
|
|
void DrawTextB(const char *text,int posX,int posY,int fontSize,Color color);
|
|
bool Button(const char *text,int x,int y,int width,int id);
|
|
bool ButtonInventory(int x,int y,int width,int height);
|
|
extern char buffer[64];
|
|
bool TextField(int id,char *buffer,int bufferSize,int x,int y,int width);
|
|
extern const char *error;
|
|
void UIBegin();
|
|
void UIResetMousePos();
|
|
void UIHandleControls();
|
|
void DrawControls();
|
|
void DrawMainMenu();
|
|
void _LoadWorld(const char *path);
|
|
void DrawWorldSelect();
|
|
void DrawMultiplayer();
|
|
void DrawPauseMenu();
|
|
extern char bufferChat[MAX_MESSAGE_LENGTH];
|
|
char *DrawChat();
|
|
void DrawLogoCenter();
|
|
#endif
|
|
#if !defined(LEGACY_GL) && !defined(SERVER)
|
|
MeshData GenerateChunkMesh(World&world,ChunkRenderData chunkRenderData,Chunk chunk,int chunkWorldX,int chunkWorldY,uint8_t sideMask);
|
|
MeshData MergeMeshData(const MeshData&a,const MeshData&b);
|
|
MeshData CreateCubeMeshData(const BlockDef&def,float cx,float cy,float cz);
|
|
Mesh GenChunkMesh(MeshData meshData);
|
|
#endif
|
|
int NetworkingStart();
|
|
ENetHost *StartServer();
|
|
ENetHost *StartClient();
|
|
void SendPacket(ENetPeer *peer,void *data,int len);
|
|
void SendPacketR(ENetPeer *peer,void *data,int len);
|
|
void BroadcastPacketR(ENetHost *server,void *data,int len);
|
|
void SerializeFloat2Data(float v,void *target,int offset);
|
|
float DeserializeFloat(int b0,int b1);
|
|
const char *Pathify(const char *src);
|
|
const char *PathifyUser(const char *src);
|
|
#if !defined(SERVER)
|
|
void DrawCubeTexture(Texture2D texture,Vector3 position,float width,float height,float length,Color color,int offsetX,int offsetY,int sizeX,int sizeY);
|
|
void DrawCubeBlock(Texture2D texture,Vector3 position,float width,float height,float length,BlockDef def,Color tint);
|
|
void DrawTextCodepoint3D(Font font,int codepoint,Vector3 position,float fontSize,bool backface,Color tint);
|
|
void DrawText3D(Font font,const char *text,Vector3 position,float fontSize,float fontSpacing,float lineSpacing,bool backface,Color tint);
|
|
#endif
|
|
RenderTexture2D LoadRenderTextureDepthTex(int width,int height);
|
|
void UnloadRenderTextureDepthTex(RenderTexture2D target);
|
|
inline uint8_t pack6(bool b0,bool b1,bool b2,bool b3,bool b4,bool b5){
|
|
return (uint8_t)(
|
|
((uint8_t)(b0 ? 1 : 0) << 0) |
|
|
((uint8_t)(b1 ? 1 : 0) << 1) |
|
|
((uint8_t)(b2 ? 1 : 0) << 2) |
|
|
((uint8_t)(b3 ? 1 : 0) << 3) |
|
|
((uint8_t)(b4 ? 1 : 0) << 4) |
|
|
((uint8_t)(b5 ? 1 : 0) << 5)
|
|
);
|
|
};
|
|
inline void unpack6(uint8_t v,bool *b0,bool *b1,bool *b2,bool *b3,bool *b4,bool *b5){
|
|
*b0 = (v >> 0) & 1;
|
|
*b1 = (v >> 1) & 1;
|
|
*b2 = (v >> 2) & 1;
|
|
*b3 = (v >> 3) & 1;
|
|
*b4 = (v >> 4) & 1;
|
|
*b5 = (v >> 5) & 1;
|
|
};
|
|
inline void GetXYZFromIndex(int index,int *x,int *y,int *z){
|
|
*y = index / (CHUNK_SIZE * CHUNK_SIZE);
|
|
int rem = index % (CHUNK_SIZE * CHUNK_SIZE);
|
|
*z = rem / CHUNK_SIZE;
|
|
*x = rem % CHUNK_SIZE;
|
|
};
|
|
inline int GetIndexChunk(int x,int y,int z){
|
|
if(x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE) return 0;
|
|
return x + CHUNK_SIZE * (z + CHUNK_SIZE * y);
|
|
};
|
|
inline int GetIndexChunk2D(int x,int z){
|
|
if(x < 0 || z < 0 || x >= CHUNK_SIZE || z >= CHUNK_SIZE) return 0;
|
|
return x + CHUNK_SIZE * z;
|
|
};
|
|
inline bool CheckOOBWorld(int x,int y,int z){
|
|
return (x < 0 || y < 0 || z < 0 || x >= WORLD_SIZE_BLOCKS || y >= WORLD_HEIGHT || z >= WORLD_SIZE_BLOCKS);
|
|
};
|
|
inline bool CheckOOBWorldChunk(int x,int z){
|
|
return (x < 0 || z < 0 || x >= MAX_WORLD_SIZE || z >= MAX_WORLD_SIZE);
|
|
};
|
|
inline int GetIndexWorld(int x,int z){
|
|
if(CheckOOBWorld(x << 4, 0, z << 4)) return 0;
|
|
return x + MAX_WORLD_SIZE * z;
|
|
};
|
|
inline void GetXZFromIndex(int index,int *x,int *z){
|
|
*z = index / MAX_WORLD_SIZE;
|
|
*x = index % MAX_WORLD_SIZE;
|
|
};
|
|
inline bool TestMask(const uint16_t *maskArray,int position){
|
|
if (position < 0 || position >= CHUNK_DATA_SIZE) return false;
|
|
int index = position >> 4;
|
|
int bit = position & 15;
|
|
return (maskArray[index] & (1u << bit)) != 0;
|
|
};
|
|
inline bool CheckOOBChunk(int x,int y,int z){
|
|
return (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_HEIGHT || z >= CHUNK_SIZE);
|
|
};
|
|
inline bool TestOpaqueMaskWorld(const World&world,int x,int y,int z){
|
|
if(CheckOOBWorld(x, y, z)) return true;
|
|
const Chunk c = world.chunks[GetIndexWorld(x >> 4, z >> 4)];
|
|
const int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
|
return TestMask(c.opaqueMask, localIndex);
|
|
};
|
|
inline bool TestAirMaskWorld(const World&world,int x,int y,int z){
|
|
if(CheckOOBWorld(x, y, z)) return true;
|
|
const Chunk c = world.chunks[GetIndexWorld(x >> 4, z >> 4)];
|
|
const int localIndex = GetIndexChunk((uint8_t)x & 15, y, (uint8_t)z & 15);
|
|
return TestMask(c.airMask, localIndex);
|
|
};
|
|
inline int fetch_block(Chunk chunk,int x,int y,int z){
|
|
if(x<0||x>=CHUNK_SIZE||y<0||y>=WORLD_HEIGHT||z<0||z>=CHUNK_SIZE) return 0;
|
|
return chunk.blocks[GetIndexChunk(x, y, z)];
|
|
};
|
|
inline int fetch_block_ptr(Chunk *chunk,int x,int y,int z){
|
|
if(x<0||x>=CHUNK_SIZE||y<0||y>=WORLD_HEIGHT||z<0||z>=CHUNK_SIZE) return 0;
|
|
return chunk->blocks[GetIndexChunk(x, y, z)];
|
|
};
|
|
inline void *grow(void *ptr,size_t oldBytes,size_t newBytes){
|
|
if (!ptr) return malloc(newBytes);
|
|
return realloc(ptr, newBytes);
|
|
};
|
|
inline void pushFloats(float *&buf,int&count,const float *vals,int n){
|
|
for (int i=0;i<n;i++) buf[count+i] = vals[i];
|
|
count += n;
|
|
};
|
|
inline void pushU8(unsigned char *&buf,int&count,const unsigned char *vals,int n){
|
|
for (int i=0;i<n;i++) buf[count+i] = vals[i];
|
|
count += n;
|
|
};
|
|
inline void pushU32(uint32_t *&buf,int&count,const uint32_t *vals,int n){
|
|
for (int i=0;i<n;i++) buf[count+i] = vals[i];
|
|
count += n;
|
|
};
|
|
inline void pushU16(unsigned short *&buf,int&count,const unsigned short *vals,int n){
|
|
for (int i=0;i<n;i++) buf[count+i] = vals[i];
|
|
count += n;
|
|
};
|
|
#if !defined(SERVER)
|
|
inline UVCorners GetUVTex(int texture){
|
|
const float uv_mod_x = 1.0f / static_cast<float>(ATLAS_SIZE_W);
|
|
const float uv_mod_y = 1.0f / static_cast<float>(ATLAS_SIZE_H);
|
|
const float uv_x = (texture % ATLAS_SIZE_W) * uv_mod_x;
|
|
const float uv_y = (texture / ATLAS_SIZE_W) * uv_mod_y;
|
|
UVCorners corners = { 0 };
|
|
corners.corner2 = Vector2{uv_x,uv_y};
|
|
corners.corner3 = Vector2{uv_x+uv_mod_x,uv_y};
|
|
corners.corner0 = Vector2{uv_x+uv_mod_x,uv_y+uv_mod_y};
|
|
corners.corner1 = Vector2{uv_x,uv_y+uv_mod_y};
|
|
return corners;
|
|
};
|
|
inline UVCorners GetUVTex(int w,int h,int offsetX,int offsetY,int sizeX,int sizeY){
|
|
const float uv_mod_x = 1.0f / static_cast<float>(w);
|
|
const float uv_mod_y = 1.0f / static_cast<float>(h);
|
|
const float uv_x = offsetX * uv_mod_x;
|
|
const float uv_y = offsetY * uv_mod_y;
|
|
const float uvsx = sizeX * uv_mod_x;
|
|
const float uvsy = sizeY * uv_mod_y;
|
|
UVCorners corners = { 0 };
|
|
corners.corner2 = Vector2{uv_x,uv_y};
|
|
corners.corner3 = Vector2{uv_x+uvsx,uv_y};
|
|
corners.corner0 = Vector2{uv_x+uvsx,uv_y+uvsy};
|
|
corners.corner1 = Vector2{uv_x,uv_y+uvsy};
|
|
return corners;
|
|
};
|
|
inline UVCorners GetUVTex(int texture,float offsetX,float offsetY,float sizeModX,float sizeModY){
|
|
const float uv_mod_x = 1.0f / static_cast<float>(ATLAS_SIZE_W);
|
|
const float uv_mod_y = 1.0f / static_cast<float>(ATLAS_SIZE_H);
|
|
const float uv_mod1_x = sizeModX / static_cast<float>(ATLAS_SIZE_W);
|
|
const float uv_mod1_y = sizeModY / static_cast<float>(ATLAS_SIZE_H);
|
|
const float uv_off_x = offsetX / static_cast<float>(ATLAS_SIZE_W);
|
|
const float uv_off_y = offsetY / static_cast<float>(ATLAS_SIZE_H);
|
|
const float uv_x = (texture % ATLAS_SIZE_W) * uv_mod_x;
|
|
const float uv_y = (texture / ATLAS_SIZE_W) * uv_mod_y;
|
|
UVCorners corners = { 0 };
|
|
corners.corner2 = Vector2{uv_x+uv_off_x,uv_y+uv_off_y};
|
|
corners.corner3 = Vector2{uv_x+uv_off_x+uv_mod1_x,uv_y+uv_off_y};
|
|
corners.corner0 = Vector2{uv_x+uv_off_x+uv_mod1_x,uv_y+uv_off_y+uv_mod1_y};
|
|
corners.corner1 = Vector2{uv_x+uv_off_x,uv_y+uv_off_y+uv_mod1_y};
|
|
return corners;
|
|
};
|
|
inline UVCorners GetUVTexFlipX(int w,int h,int offsetX,int offsetY,int sizeX,int sizeY){
|
|
const float uv_mod_x = 1.0f / static_cast<float>(w);
|
|
const float uv_mod_y = 1.0f / static_cast<float>(h);
|
|
const float uv_x = offsetX * uv_mod_x;
|
|
const float uv_y = offsetY * uv_mod_y;
|
|
const float uvsx = sizeX * uv_mod_x;
|
|
const float uvsy = sizeY * uv_mod_y;
|
|
UVCorners corners = { 0 };
|
|
corners.corner2 = Vector2{uv_x+uvsx,uv_y};
|
|
corners.corner3 = Vector2{uv_x,uv_y};
|
|
corners.corner0 = Vector2{uv_x,uv_y+uvsy};
|
|
corners.corner1 = Vector2{uv_x+uvsx,uv_y+uvsy};
|
|
return corners;
|
|
};
|
|
extern InventoryItem hotbar[ITEMS];
|
|
#endif
|
|
extern InventoryItem hotbar[ITEMS];
|
|
#if !defined(SERVER)
|
|
extern InventoryItem inventory[INVENTORY_SIZE];
|
|
#endif
|
|
extern InventoryItem inventory[INVENTORY_SIZE];
|
|
#if !defined(SERVER)
|
|
extern bool inventoryOpen;
|
|
extern InventoryItem *movingItem;
|
|
void DrawItem(InventoryItem item,int x,int y);
|
|
void InventoryRemoveItem(int slot);
|
|
void HotbarRemoveItem(int slot);
|
|
void HotbarRemoveSelected();
|
|
void HotbarAddItem(Item *registry,int damage);
|
|
void HotbarAddItemLots(Item *registry,int damage,int amount);
|
|
void InitHotbar();
|
|
void DrawHotbar();
|
|
InventoryItem HotbarGetSelected();
|
|
void DrawSelectedItem(Color tint);
|
|
void CloseInventory();
|
|
void UpdateHotbar();
|
|
void LocaleUpdate();
|
|
void LoadRecipes();
|
|
#endif
|
|
void ParticlesUpdate(float dt,World&world);
|
|
void ParticlesDraw();
|
|
void AddParticle(Particle part);
|
|
Particle NewParticle(Vector3 position);
|
|
extern bool creative_mode;
|
|
extern float player_health;
|
|
extern float player_attack_time;
|
|
extern float player_place_time;
|
|
extern float player_break_parts_time;
|
|
void SavePlayerData();
|
|
bool LoadPlayerData();
|
|
void MS_PlaySound(Sound src,float pitch,float volume,Vector3 position);
|
|
void MS_Update(float dt,Camera camera);
|
|
#define INTERFACE 0
|
|
#define EXPORT_INTERFACE 0
|
|
#define LOCAL_INTERFACE 0
|
|
#define EXPORT
|
|
#define LOCAL static
|
|
#define PUBLIC
|
|
#define PRIVATE
|
|
#define PROTECTED
|