Permalink
Browse files

Fix game being stuffed after getting disconnected

  • Loading branch information...
UnknownShadow200 committed Nov 27, 2018
1 parent 0ace7af commit 04c3683ba1d493eb815aa685de7f3f317a766fb9
Showing with 103 additions and 69 deletions.
  1. +5 −7 src/BlockPhysics.c
  2. +1 −0 src/BlockPhysics.h
  3. +2 −2 src/Chat.c
  4. +1 −1 src/Core.h
  5. +1 −1 src/Entity.c
  6. +11 −4 src/Game.c
  7. +6 −1 src/Game.h
  8. +3 −3 src/InputHandler.c
  9. +0 −2 src/Model.h
  10. +1 −1 src/Screens.c
  11. +33 −33 src/ServerConnection.c
  12. +28 −5 src/ServerConnection.h
  13. +5 −5 src/World.c
  14. +6 −4 src/World.h
@@ -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);
@@ -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,20 +212,26 @@ 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);
chunk->AllAir &= Block_Draw[block] == DRAW_GAS;
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);
Oops, something went wrong.

0 comments on commit 04c3683

Please sign in to comment.