#ifdef WIN32 // FUCK WINDOWS #include "external/fix_win32_compatibility.h" #undef PlaySound #endif #include #ifdef WIN32 // FUCK WINDOWS 2 #undef PlaySound #undef Sound #endif #include #include "glfw_keycodes_to_string.h" #include "raylib.h" #include "raymath.h" #include #include #include #include #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{}(p.x); size_t h2 = std::hash{}(p.y); size_t h3 = std::hash{}(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 inputs; std::list 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(ATLAS_SIZE_W); const float uv_mod_y = 1.0f / static_cast(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(w); const float uv_mod_y = 1.0f / static_cast(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(ATLAS_SIZE_W); const float uv_mod_y = 1.0f / static_cast(ATLAS_SIZE_H); const float uv_mod1_x = sizeModX / static_cast(ATLAS_SIZE_W); const float uv_mod1_y = sizeModY / static_cast(ATLAS_SIZE_H); const float uv_off_x = offsetX / static_cast(ATLAS_SIZE_W); const float uv_off_y = offsetY / static_cast(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(w); const float uv_mod_y = 1.0f / static_cast(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