Skip to content

Commit e3589a0

Browse files
committed
fix player entities desyncing on join sometimes
1 parent bad337a commit e3589a0

File tree

5 files changed

+43
-21
lines changed

5 files changed

+43
-21
lines changed

include/packets.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ int cs_chat (int client_fd);
2121
int cs_interact (int client_fd);
2222
int cs_playerInput (int client_fd);
2323
int cs_playerCommand (int client_fd);
24+
int cs_playerLoaded (int client_fd);
2425

2526
// Clientbound packets
2627
int sc_statusResponse (int client_fd);

include/procedures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ void resetPlayerData (PlayerData *player);
1515
int reservePlayerData (int client_fd, uint8_t *uuid, char* name);
1616
int getPlayerData (int client_fd, PlayerData **output);
1717
void handlePlayerDisconnect (int client_fd);
18+
void handlePlayerJoin (PlayerData* player);
1819
void disconnectClient (int *client_fd, int cause);
1920
int givePlayerItem (PlayerData *player, uint16_t item, uint8_t count);
2021
void spawnPlayer (PlayerData *player);

src/main.c

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -126,22 +126,13 @@ void handlePacket (int client_fd, int length, int packet_id, int state) {
126126
// Send full client spawn sequence
127127
spawnPlayer(player);
128128

129-
// Prepare join message for broadcast
130-
uint8_t player_name_len = strlen(player->name);
131-
strcpy((char *)recv_buffer, player->name);
132-
strcpy((char *)recv_buffer + player_name_len, " joined the game");
133-
134-
// Register all existing players and spawn their entities, and broadcast
135-
// information about the joining player to all existing players.
129+
// Register all existing players and spawn their entities
136130
for (int i = 0; i < MAX_PLAYERS; i ++) {
137131
if (player_data[i].client_fd == -1) continue;
138-
if (player_data[i].flags & 0x20 && player_data[i].client_fd != client_fd) continue;
132+
// Note that this will also filter out the joining player
133+
if (player_data[i].flags & 0x20) continue;
139134
sc_playerInfoUpdateAddPlayer(client_fd, player_data[i]);
140-
sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, 16 + player_name_len);
141-
if (player_data[i].client_fd == client_fd) continue;
142-
sc_playerInfoUpdateAddPlayer(player_data[i].client_fd, *player);
143135
sc_spawnEntityPlayer(client_fd, player_data[i]);
144-
sc_spawnEntityPlayer(player_data[i].client_fd, *player);
145136
}
146137

147138
// Send information about all other entities (mobs)
@@ -431,14 +422,9 @@ void handlePacket (int client_fd, int length, int packet_id, int state) {
431422
if (state == STATE_PLAY) cs_playerInput(client_fd);
432423
break;
433424

434-
case 0x2B: { // Player Loaded
435-
PlayerData *player;
436-
if (getPlayerData(client_fd, &player)) break;
437-
// Clear "client loading" flag and fallback timer
438-
player->flags &= ~0x20;
439-
player->flagval_16 = 0;
425+
case 0x2B:
426+
if (state == STATE_PLAY) cs_playerLoaded(client_fd);
440427
break;
441-
}
442428

443429
case 0x34:
444430
if (state == STATE_PLAY) cs_setHeldItem(client_fd);

src/packets.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,18 @@ int sc_pickupItem (int client_fd, int collected, int collector, uint8_t count) {
11781178
return 0;
11791179
}
11801180

1181+
// C->S Player Loaded
1182+
int cs_playerLoaded (int client_fd) {
1183+
1184+
PlayerData *player;
1185+
if (getPlayerData(client_fd, &player)) return 1;
1186+
1187+
// Redirect handling to player join procedure
1188+
handlePlayerJoin(player);
1189+
1190+
return 0;
1191+
}
1192+
11811193
// S->C Registry Data (multiple packets) and Update Tags (configuration, multiple packets)
11821194
int sc_registries (int client_fd) {
11831195

src/procedures.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,29 @@ void handlePlayerDisconnect (int client_fd) {
146146
}
147147
}
148148

149+
// Marks a client as connected and broadcasts their data to other players
150+
void handlePlayerJoin (PlayerData* player) {
151+
152+
// Prepare join message for broadcast
153+
uint8_t player_name_len = strlen(player->name);
154+
strcpy((char *)recv_buffer, player->name);
155+
strcpy((char *)recv_buffer + player_name_len, " joined the game");
156+
157+
// Inform other clients (and the joining client) of the player's name and entity
158+
for (int i = 0; i < MAX_PLAYERS; i ++) {
159+
sc_systemChat(player_data[i].client_fd, (char *)recv_buffer, 16 + player_name_len);
160+
sc_playerInfoUpdateAddPlayer(player_data[i].client_fd, *player);
161+
if (player_data[i].client_fd != player->client_fd) {
162+
sc_spawnEntityPlayer(player_data[i].client_fd, *player);
163+
}
164+
}
165+
166+
// Clear "client loading" flag and fallback timer
167+
player->flags &= ~0x20;
168+
player->flagval_16 = 0;
169+
170+
}
171+
149172
void disconnectClient (int *client_fd, int cause) {
150173
if (*client_fd == -1) return;
151174
client_count --;
@@ -1414,8 +1437,7 @@ void handleServerTick (int64_t time_since_last_tick) {
14141437
// If 3 seconds (60 vanilla ticks) have passed, assume player has loaded
14151438
player->flagval_16 ++;
14161439
if (player->flagval_16 > (uint16_t)(3 * TICKS_PER_SECOND)) {
1417-
player->flags &= ~0x20;
1418-
player->flagval_16 = 0;
1440+
handlePlayerJoin(player);
14191441
} else continue;
14201442
}
14211443
// Reset player attack cooldown

0 commit comments

Comments
 (0)