mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 09:35:23 -04:00
Fix game being stuffed after getting disconnected
This commit is contained in:
parent
0ace7afa1e
commit
04c3683ba1
@ -144,16 +144,16 @@ static bool Physics_IsEdgeWater(int x, int y, int z) {
|
||||
}
|
||||
|
||||
|
||||
static void Physics_BlockChanged(void* obj, Vector3I p, BlockID old, BlockID now) {
|
||||
void Physics_OnBlockChanged(int x, int y, int z, BlockID old, BlockID now) {
|
||||
PhysicsHandler handler;
|
||||
int index;
|
||||
if (!Physics_Enabled) return;
|
||||
|
||||
if (now == BLOCK_AIR && Physics_IsEdgeWater(p.X, p.Y, p.Z)) {
|
||||
if (now == BLOCK_AIR && Physics_IsEdgeWater(x, y, z)) {
|
||||
now = BLOCK_STILL_WATER;
|
||||
Game_UpdateBlock(p.X, p.Y, p.Z, BLOCK_STILL_WATER);
|
||||
Game_UpdateBlock(x, y, z, BLOCK_STILL_WATER);
|
||||
}
|
||||
index = World_Pack(p.X, p.Y, p.Z);
|
||||
index = World_Pack(x, y, z);
|
||||
|
||||
if (now == BLOCK_AIR) {
|
||||
handler = Physics_OnDelete[old];
|
||||
@ -162,7 +162,7 @@ static void Physics_BlockChanged(void* obj, Vector3I p, BlockID old, BlockID now
|
||||
handler = Physics_OnPlace[now];
|
||||
if (handler) handler(index, now);
|
||||
}
|
||||
Physics_ActivateNeighbours(p.X, p.Y, p.Z, index);
|
||||
Physics_ActivateNeighbours(x, y, z, index);
|
||||
}
|
||||
|
||||
static void Physics_TickRandomBlocks(void) {
|
||||
@ -515,7 +515,6 @@ static void Physics_HandleTnt(int index, BlockID block) {
|
||||
|
||||
void Physics_Init(void) {
|
||||
Event_RegisterVoid(&WorldEvents_MapLoaded, NULL, Physics_OnNewMapLoaded);
|
||||
Event_RegisterBlock(&UserEvents_BlockChanged, NULL, Physics_BlockChanged);
|
||||
Physics_Enabled = Options_GetBool(OPT_BLOCK_PHYSICS, true);
|
||||
TickQueue_Init(&physics_lavaQ);
|
||||
TickQueue_Init(&physics_waterQ);
|
||||
@ -559,7 +558,6 @@ void Physics_Init(void) {
|
||||
|
||||
void Physics_Free(void) {
|
||||
Event_UnregisterVoid(&WorldEvents_MapLoaded, NULL, Physics_OnNewMapLoaded);
|
||||
Event_UnregisterBlock(&UserEvents_BlockChanged, NULL, Physics_BlockChanged);
|
||||
}
|
||||
|
||||
void Physics_Tick(void) {
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
extern bool Physics_Enabled;
|
||||
void Physics_SetEnabled(bool enabled);
|
||||
void Physics_OnBlockChanged(int x, int y, int z, BlockID old, BlockID now);
|
||||
void Physics_Init(void);
|
||||
void Physics_Free(void);
|
||||
void Physics_Tick(void);
|
||||
|
@ -461,7 +461,7 @@ static void CuboidCommand_DoCuboid(void) {
|
||||
for (y = min.Y; y <= max.Y; y++) {
|
||||
for (z = min.Z; z <= max.Z; z++) {
|
||||
for (x = min.X; x <= max.X; x++) {
|
||||
Game_UpdateBlock(x, y, z, toPlace);
|
||||
Game_ChangeBlock(x, y, z, toPlace);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -566,7 +566,7 @@ void Chat_Send(const String* text, bool logUsage) {
|
||||
if (Commands_IsCommandPrefix(text)) {
|
||||
Commands_Execute(text);
|
||||
} else {
|
||||
ServerConnection_SendChat(text);
|
||||
ServerConnection.SendChat(text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ typedef signed __int64 int64_t;
|
||||
|
||||
#define CC_INLINE inline
|
||||
#define CC_NOINLINE __declspec(noinline)
|
||||
#define CC_ALIGN_HINT(x) /* TODO: Why does this cause LNK2005 errors */
|
||||
#define CC_ALIGN_HINT(x) __declspec(align(x))
|
||||
#ifndef CC_EXPORT
|
||||
#define CC_EXPORT __declspec(dllexport, noinline)
|
||||
#endif
|
||||
|
@ -940,7 +940,7 @@ static void LocalPlayer_DoRespawn(void) {
|
||||
if (World_IsValidPos_3I(pos)) {
|
||||
AABB_Make(&bb, &spawn, &p->Base.Size);
|
||||
for (y = pos.Y; y <= World_Height; y++) {
|
||||
spawnY = Respawn_HighestFreeY(&bb);
|
||||
spawnY = Respawn_HighestSolidY(&bb);
|
||||
|
||||
if (spawnY == RESPAWN_NOT_FOUND) {
|
||||
block = World_GetPhysicsBlock(pos.X, y, pos.Z);
|
||||
|
15
src/Game.c
15
src/Game.c
@ -194,6 +194,7 @@ void Game_Disconnect(const String* title, const String* reason) {
|
||||
Event_RaiseVoid(&WorldEvents_NewMap);
|
||||
Gui_FreeActive();
|
||||
Gui_SetActive(DisconnectScreen_MakeInstance(title, reason));
|
||||
Game_Reset();
|
||||
}
|
||||
|
||||
void Game_Reset(void) {
|
||||
@ -211,13 +212,13 @@ void Game_Reset(void) {
|
||||
void Game_UpdateBlock(int x, int y, int z, BlockID block) {
|
||||
struct ChunkInfo* chunk;
|
||||
int cx = x >> 4, cy = y >> 4, cz = z >> 4;
|
||||
BlockID oldBlock = World_GetBlock(x, y, z);
|
||||
BlockID old = World_GetBlock(x, y, z);
|
||||
World_SetBlock(x, y, z, block);
|
||||
|
||||
if (Weather_Heightmap) {
|
||||
EnvRenderer_OnBlockChanged(x, y, z, oldBlock, block);
|
||||
EnvRenderer_OnBlockChanged(x, y, z, old, block);
|
||||
}
|
||||
Lighting_OnBlockChanged(x, y, z, oldBlock, block);
|
||||
Lighting_OnBlockChanged(x, y, z, old, block);
|
||||
|
||||
/* Refresh the chunk the block was located in. */
|
||||
chunk = MapRenderer_GetChunk(cx, cy, cz);
|
||||
@ -225,6 +226,12 @@ void Game_UpdateBlock(int x, int y, int z, BlockID block) {
|
||||
MapRenderer_RefreshChunk(cx, cy, cz);
|
||||
}
|
||||
|
||||
void Game_ChangeBlock(int x, int y, int z, BlockID block) {
|
||||
BlockID old = World_GetBlock(x, y, z);
|
||||
Game_UpdateBlock(x, y, z, block);
|
||||
ServerConnection.SendBlock(x, y, z, old, block);
|
||||
}
|
||||
|
||||
bool Game_CanPick(BlockID block) {
|
||||
if (Block_Draw[block] == DRAW_GAS) return false;
|
||||
if (Block_Draw[block] == DRAW_SPRITE) return true;
|
||||
@ -526,7 +533,7 @@ void Game_Load(void) {
|
||||
|
||||
Gui_FreeActive();
|
||||
Gui_SetActive(LoadingScreen_MakeInstance(&title, &String_Empty));
|
||||
ServerConnection_BeginConnect();
|
||||
ServerConnection.BeginConnect();
|
||||
}
|
||||
|
||||
void Game_SetFpsLimit(enum FpsLimit method) {
|
||||
|
@ -82,7 +82,12 @@ void Game_UserSetViewDistance(int distance);
|
||||
void Game_UpdateProjection(void);
|
||||
void Game_Disconnect(const String* title, const String* reason);
|
||||
void Game_Reset(void);
|
||||
void Game_UpdateBlock(int x, int y, int z, BlockID block);
|
||||
/* Sets the block in the map at the given coordinates, then updates state associated with the block. */
|
||||
/* (updating state means recalculating light, redrawing chunk block is in, etc) */
|
||||
/* NOTE: This does NOT notify the server, use Game_ChangeBlock for that. */
|
||||
CC_EXPORT void Game_UpdateBlock(int x, int y, int z, BlockID block);
|
||||
/* Calls Game_UpdateBlock, then sends the block change to the server. */
|
||||
CC_EXPORT void Game_ChangeBlock(int x, int y, int z, BlockID block);
|
||||
bool Game_CanPick(BlockID block);
|
||||
bool Game_UpdateTexture(GfxResourceID* texId, struct Stream* src, const String* file, uint8_t* skinType);
|
||||
bool Game_ValidateBitmap(const String* file, Bitmap* bmp);
|
||||
|
@ -44,7 +44,7 @@ static void InputHandler_ButtonStateUpdate(MouseButton button, bool pressed) {
|
||||
}
|
||||
|
||||
input_buttonsDown[button] = pressed;
|
||||
ServerConnection_SendPlayerClick(button, pressed,
|
||||
ServerConnection.SendPlayerClick(button, pressed,
|
||||
(EntityID)input_pickingId, &Game_SelectedPos);
|
||||
}
|
||||
|
||||
@ -347,7 +347,7 @@ void InputHandler_PickBlocks(bool cooldown, bool left, bool middle, bool right)
|
||||
old = World_GetBlock(p.X, p.Y, p.Z);
|
||||
if (Block_Draw[old] == DRAW_GAS || !Block_CanDelete[old]) return;
|
||||
|
||||
Game_UpdateBlock(p.X, p.Y, p.Z, BLOCK_AIR);
|
||||
Game_ChangeBlock(p.X, p.Y, p.Z, BLOCK_AIR);
|
||||
Event_RaiseBlock(&UserEvents_BlockChanged, p, old, BLOCK_AIR);
|
||||
} else if (right) {
|
||||
p = Game_SelectedPos.TranslatedPos;
|
||||
@ -362,7 +362,7 @@ void InputHandler_PickBlocks(bool cooldown, bool left, bool middle, bool right)
|
||||
if (Block_Draw[block] == DRAW_GAS && Block_Draw[old] != DRAW_GAS) return;
|
||||
if (!InputHandler_CheckIsFree(block)) return;
|
||||
|
||||
Game_UpdateBlock(p.X, p.Y, p.Z, block);
|
||||
Game_ChangeBlock(p.X, p.Y, p.Z, block);
|
||||
Event_RaiseBlock(&UserEvents_BlockChanged, p, old, block);
|
||||
} else if (middle) {
|
||||
p = Game_SelectedPos.BlockPos;
|
||||
|
@ -106,8 +106,6 @@ extern GfxResourceID Model_Vb;
|
||||
extern VertexP3fT2fC4b Model_Vertices[MODEL_MAX_VERTICES];
|
||||
extern struct Model* Human_ModelPtr;
|
||||
|
||||
void Models_Init(void);
|
||||
void Models_Free(void);
|
||||
/* Returns pointer to model whose name caselessly matches given name. */
|
||||
CC_EXPORT struct Model* Model_Get(const String* name);
|
||||
/* Returns index of cached texture whose name caselessly matches given name. */
|
||||
|
@ -1521,7 +1521,7 @@ static bool DisconnectScreen_MouseDown(void* screen, int x, int y, MouseButton b
|
||||
|
||||
Gui_FreeActive();
|
||||
Gui_SetActive(LoadingScreen_MakeInstance(&title, &String_Empty));
|
||||
ServerConnection_BeginConnect();
|
||||
ServerConnection.BeginConnect();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -28,17 +28,12 @@ static char server_motdBuffer[STRING_SIZE];
|
||||
static char server_appBuffer[STRING_SIZE];
|
||||
static int server_ticks;
|
||||
|
||||
struct ServerConnectionFuncs ServerConnection;
|
||||
bool ServerConnection_IsSinglePlayer, ServerConnection_Disconnected;
|
||||
String ServerConnection_ServerName = String_FromArray(server_nameBuffer);
|
||||
String ServerConnection_ServerMOTD = String_FromArray(server_motdBuffer);
|
||||
String ServerConnection_AppName = String_FromArray(server_appBuffer);
|
||||
|
||||
void (*ServerConnection_BeginConnect)(void);
|
||||
void (*ServerConnection_SendChat)(const String* text);
|
||||
void (*ServerConnection_SendPosition)(Vector3 pos, float rotY, float headX);
|
||||
void (*ServerConnection_SendPlayerClick)(MouseButton button, bool isDown, EntityID targetId, struct PickedPos* pos);
|
||||
void (*ServerConnection_Tick)(struct ScheduledTask* task);
|
||||
|
||||
uint8_t* ServerConnection_WriteBuffer;
|
||||
bool ServerConnection_SupportsExtPlayerList, ServerConnection_SupportsPlayerClick;
|
||||
bool ServerConnection_SupportsPartialMessages, ServerConnection_SupportsFullCP437;
|
||||
@ -205,6 +200,10 @@ static void SPConnection_AddPart(const String* text) {
|
||||
Chat_Add(&tmp);
|
||||
}
|
||||
|
||||
static void SPConnection_SendBlock(int x, int y, int z, BlockID old, BlockID now) {
|
||||
Physics_OnBlockChanged(x, y, z, old, now);
|
||||
}
|
||||
|
||||
static void SPConnection_SendChat(const String* text) {
|
||||
String left, part;
|
||||
if (!text->length) return;
|
||||
@ -232,19 +231,21 @@ static void SPConnection_Tick(struct ScheduledTask* task) {
|
||||
server_ticks++;
|
||||
}
|
||||
|
||||
static struct ServerConnectionFuncs SPConnection = {
|
||||
SPConnection_BeginConnect, SPConnection_Tick,
|
||||
SPConnection_SendBlock, SPConnection_SendChat,
|
||||
SPConnection_SendPosition, SPConnection_SendPlayerClick
|
||||
};
|
||||
|
||||
static void SPConnection_Init(void) {
|
||||
ServerConnection_ResetState();
|
||||
Physics_Init();
|
||||
|
||||
ServerConnection_SupportsFullCP437 = !Game_ClassicMode;
|
||||
ServerConnection_SupportsPartialMessages = true;
|
||||
ServerConnection_IsSinglePlayer = true;
|
||||
|
||||
ServerConnection_BeginConnect = SPConnection_BeginConnect;
|
||||
ServerConnection_SendChat = SPConnection_SendChat;
|
||||
ServerConnection_SendPosition = SPConnection_SendPosition;
|
||||
ServerConnection_SendPlayerClick = SPConnection_SendPlayerClick;
|
||||
ServerConnection_Tick = SPConnection_Tick;
|
||||
|
||||
ServerConnection = SPConnection;
|
||||
ServerConnection_WriteBuffer = NULL;
|
||||
}
|
||||
|
||||
@ -269,16 +270,6 @@ static bool net_connecting;
|
||||
static TimeMS net_connectTimeout;
|
||||
#define NET_TIMEOUT_MS (15 * 1000)
|
||||
|
||||
static void MPConnection_BlockChanged(void* obj, Vector3I p, BlockID old, BlockID now) {
|
||||
if (now == BLOCK_AIR) {
|
||||
now = Inventory_SelectedBlock;
|
||||
Classic_WriteSetBlock(p.X, p.Y, p.Z, false, now);
|
||||
} else {
|
||||
Classic_WriteSetBlock(p.X, p.Y, p.Z, true, now);
|
||||
}
|
||||
Net_SendPacket();
|
||||
}
|
||||
|
||||
static void ServerConnection_Free(void);
|
||||
static void MPConnection_FinishConnect(void) {
|
||||
net_connecting = false;
|
||||
@ -334,7 +325,6 @@ static void MPConnection_TickConnect(void) {
|
||||
|
||||
static void MPConnection_BeginConnect(void) {
|
||||
ReturnCode res;
|
||||
Event_RegisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged);
|
||||
Socket_Create(&net_socket);
|
||||
ServerConnection_Disconnected = false;
|
||||
|
||||
@ -348,6 +338,16 @@ static void MPConnection_BeginConnect(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static void MPConnection_SendBlock(int x, int y, int z, BlockID old, BlockID now) {
|
||||
if (now == BLOCK_AIR) {
|
||||
now = Inventory_SelectedBlock;
|
||||
Classic_WriteSetBlock(x, y, z, false, now);
|
||||
} else {
|
||||
Classic_WriteSetBlock(x, y, z, true, now);
|
||||
}
|
||||
Net_SendPacket();
|
||||
}
|
||||
|
||||
static void MPConnection_SendChat(const String* text) {
|
||||
String left, part;
|
||||
if (!text->length || net_connecting) return;
|
||||
@ -514,17 +514,18 @@ void Net_SendPacket(void) {
|
||||
}
|
||||
}
|
||||
|
||||
static struct ServerConnectionFuncs MPConnection = {
|
||||
MPConnection_BeginConnect, MPConnection_Tick,
|
||||
MPConnection_SendBlock, MPConnection_SendChat,
|
||||
MPConnection_SendPosition, MPConnection_SendPlayerClick
|
||||
};
|
||||
|
||||
static void MPConnection_Init(void) {
|
||||
ServerConnection_ResetState();
|
||||
ServerConnection_IsSinglePlayer = false;
|
||||
|
||||
ServerConnection_BeginConnect = MPConnection_BeginConnect;
|
||||
ServerConnection_SendChat = MPConnection_SendChat;
|
||||
ServerConnection_SendPosition = MPConnection_SendPosition;
|
||||
ServerConnection_SendPlayerClick = MPConnection_SendPlayerClick;
|
||||
ServerConnection_Tick = MPConnection_Tick;
|
||||
|
||||
net_readCurrent = net_readBuffer;
|
||||
ServerConnection = MPConnection;
|
||||
net_readCurrent = net_readBuffer;
|
||||
ServerConnection_WriteBuffer = net_writeBuffer;
|
||||
}
|
||||
|
||||
@ -561,8 +562,8 @@ static void ServerConnection_Init(void) {
|
||||
MPConnection_Init();
|
||||
}
|
||||
|
||||
Gfx_LostContextFunction = ServerConnection_Tick;
|
||||
ScheduledTask_Add(GAME_NET_TICKS, ServerConnection_Tick);
|
||||
Gfx_LostContextFunction = ServerConnection.Tick;
|
||||
ScheduledTask_Add(GAME_NET_TICKS, ServerConnection.Tick);
|
||||
String_AppendConst(&ServerConnection_AppName, PROGRAM_APP_NAME);
|
||||
}
|
||||
|
||||
@ -571,7 +572,6 @@ static void ServerConnection_Free(void) {
|
||||
Physics_Free();
|
||||
} else {
|
||||
if (ServerConnection_Disconnected) return;
|
||||
Event_UnregisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged);
|
||||
Socket_Close(net_socket);
|
||||
ServerConnection_Disconnected = true;
|
||||
}
|
||||
|
@ -46,22 +46,45 @@ int PingList_NextPingData(void);
|
||||
void PingList_Update(int data);
|
||||
int PingList_AveragePingMs(void);
|
||||
|
||||
/* Whether the player is connected to singleplayer/loopback server. */
|
||||
extern bool ServerConnection_IsSinglePlayer;
|
||||
/* Whether the player has been disconnected from the server. */
|
||||
extern bool ServerConnection_Disconnected;
|
||||
/* The current name of the server. (Shows as first line when loading) */
|
||||
extern String ServerConnection_ServerName;
|
||||
/* The current MOTD of the server. (Shows as second line when loading) */
|
||||
extern String ServerConnection_ServerMOTD;
|
||||
/* The software name the client identifies itself as being to the server. */
|
||||
/* By default this is the same as PROGRAM_APP_NAME */
|
||||
extern String ServerConnection_AppName;
|
||||
|
||||
extern void (*ServerConnection_BeginConnect)(void);
|
||||
extern void (*ServerConnection_SendChat)(const String* text);
|
||||
extern void (*ServerConnection_SendPosition)(Vector3 pos, float rotY, float headX);
|
||||
extern void (*ServerConnection_SendPlayerClick)(MouseButton button, bool isDown, EntityID targetId, struct PickedPos* pos);
|
||||
extern void (*ServerConnection_Tick)(struct ScheduledTask* task);
|
||||
struct ServerConnectionFuncs {
|
||||
/* Begins connecting to the server. */
|
||||
/* NOTE: Usually asynchronous, but not always. */
|
||||
void (*BeginConnect)(void);
|
||||
/* Ticks state of the server. */
|
||||
void (*Tick)(struct ScheduledTask* task);
|
||||
/* Sends a block update to the server. */
|
||||
void (*SendBlock)(int x, int y, int z, BlockID old, BlockID now);
|
||||
/* Sends a chat message to the server. */
|
||||
void (*SendChat)(const String* text);
|
||||
/* Sends a position update to the server. */
|
||||
void (*SendPosition)(Vector3 pos, float rotY, float headX);
|
||||
/* Sends a PlayerClick packet to the server. */
|
||||
void (*SendPlayerClick)(MouseButton button, bool isDown, EntityID targetId, struct PickedPos* pos);
|
||||
};
|
||||
|
||||
/* Currently active connection to a server. */
|
||||
extern struct ServerConnectionFuncs ServerConnection;
|
||||
extern uint8_t* ServerConnection_WriteBuffer;
|
||||
|
||||
/* Whether the server supports separate tab list from entities in world. */
|
||||
extern bool ServerConnection_SupportsExtPlayerList;
|
||||
/* Whether the server supports packet with detailed info on mouse clicks. */
|
||||
extern bool ServerConnection_SupportsPlayerClick;
|
||||
/* Whether the server supports combining multiple chat packets into one. */
|
||||
extern bool ServerConnection_SupportsPartialMessages;
|
||||
/* Whether the server supports all of code page 437, not just ASCII. */
|
||||
extern bool ServerConnection_SupportsFullCP437;
|
||||
|
||||
void ServerConnection_RetrieveTexturePack(const String* url);
|
||||
|
10
src/World.c
10
src/World.c
@ -253,11 +253,11 @@ void Env_SetShadowCol(PackedCol col) {
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Respawning--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
float Respawn_HighestFreeY(struct AABB* bb) {
|
||||
float Respawn_HighestSolidY(struct AABB* bb) {
|
||||
int minX = Math_Floor(bb->Min.X), maxX = Math_Floor(bb->Max.X);
|
||||
int minY = Math_Floor(bb->Min.Y), maxY = Math_Floor(bb->Max.Y);
|
||||
int minZ = Math_Floor(bb->Min.Z), maxZ = Math_Floor(bb->Max.Z);
|
||||
float spawnY = RESPAWN_NOT_FOUND;
|
||||
float highestY = RESPAWN_NOT_FOUND;
|
||||
|
||||
BlockID block;
|
||||
struct AABB blockBB;
|
||||
@ -274,11 +274,11 @@ float Respawn_HighestFreeY(struct AABB* bb) {
|
||||
|
||||
if (Block_Collide[block] != COLLIDE_SOLID) continue;
|
||||
if (!AABB_Intersects(bb, &blockBB)) continue;
|
||||
if (blockBB.Max.Y > spawnY) spawnY = blockBB.Max.Y;
|
||||
if (blockBB.Max.Y > highestY) highestY = blockBB.Max.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
return spawnY;
|
||||
return highestY;
|
||||
}
|
||||
|
||||
Vector3 Respawn_FindSpawnPosition(float x, float z, Vector3 modelSize) {
|
||||
@ -292,7 +292,7 @@ Vector3 Respawn_FindSpawnPosition(float x, float z, Vector3 modelSize) {
|
||||
spawn.Y = 0.0f;
|
||||
|
||||
for (y = World_Height; y >= 0; y--) {
|
||||
highestY = Respawn_HighestFreeY(&bb);
|
||||
highestY = Respawn_HighestSolidY(&bb);
|
||||
if (highestY != RESPAWN_NOT_FOUND) {
|
||||
spawn.Y = highestY; break;
|
||||
}
|
||||
|
10
src/World.h
10
src/World.h
@ -129,9 +129,11 @@ CC_EXPORT void Env_SetSunCol(PackedCol col);
|
||||
CC_EXPORT void Env_SetShadowCol(PackedCol col);
|
||||
|
||||
#define RESPAWN_NOT_FOUND -100000.0f
|
||||
/* Finds the highest free Y coordinate in the given bounding box */
|
||||
float Respawn_HighestFreeY(struct AABB* bb);
|
||||
/* Finds a suitable spawn position for the entity. */
|
||||
/* Works by iterating downwards from top of world until ground is found. */
|
||||
/* Finds the highest Y coordinate of any solid block that intersects the given bounding box */
|
||||
/* So essentially, means max(Y + Block_MaxBB[block].Y) over all solid blocks the AABB touches */
|
||||
/* Returns RESPAWN_NOT_FOUND when no intersecting solid blocks are found. */
|
||||
float Respawn_HighestSolidY(struct AABB* bb);
|
||||
/* Finds a suitable initial spawn position for the entity. */
|
||||
/* Works by iterating downwards from top of world until solid ground is found. */
|
||||
Vector3 Respawn_FindSpawnPosition(float x, float z, Vector3 modelSize);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user