Skip to content

Commit 8d656cd

Browse files
committed
Many Network/multiplayer fixes
1 parent 8931e3c commit 8d656cd

File tree

14 files changed

+148
-41
lines changed

14 files changed

+148
-41
lines changed

src/client/client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ void Client::onPeerDisconnected(peer_t peer_id)
237237
m_state = ClientState::None;
238238

239239
// send event for client destruction
240-
if (m_eventhandler) {
240+
{
241241
GameEvent e(GameEvent::C2G_DIALOG);
242242
e.text = new std::string("Server disconnected");
243243
sendNewEvent(e);

src/client/client_packethandler.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void Client::pkt_Hello(Packet &pkt)
3131
m_players.emplace(m_my_peer_id, player);
3232

3333
m_state = ClientState::LobbyIdle;
34-
printf("Client: hello. my peer_id=%d\n", m_my_peer_id);
34+
printf("Client: got HELLO. my peer_id=%u\n", m_my_peer_id);
3535
}
3636

3737
void Client::pkt_Error(Packet &pkt)
@@ -51,12 +51,9 @@ void Client::pkt_Lobby(Packet &pkt)
5151
std::string world_id(pkt.readStr16());
5252

5353
LobbyWorld world;
54+
world.readCommon(pkt);
5455
world.size.X = pkt.read<u16>();
5556
world.size.Y = pkt.read<u16>();
56-
world.title = pkt.readStr16();
57-
world.owner = pkt.readStr16();
58-
world.online = pkt.read<u16>();
59-
world.plays = pkt.read<u32>();
6057

6158
world_list.emplace(world_id, world);
6259
}
@@ -77,6 +74,7 @@ void Client::pkt_WorldData(Packet &pkt)
7774
RefCnt<World> world(new World(m_world_id));
7875
world->drop(); // kept alive by RefCnt
7976

77+
world->getMeta().readCommon(pkt);
8078
blockpos_t size;
8179
pkt.read<u16>(size.X);
8280
pkt.read<u16>(size.Y);
@@ -137,9 +135,11 @@ void Client::pkt_Leave(Packet &pkt)
137135

138136
m_players.erase(peer_id);
139137

140-
GameEvent e(GameEvent::C2G_PLAYER_LEAVE);
141-
e.player = player;
142-
sendNewEvent(e);
138+
{
139+
GameEvent e(GameEvent::C2G_PLAYER_LEAVE);
140+
e.player = player;
141+
sendNewEvent(e);
142+
}
143143

144144
delete player;
145145

src/client/gameevent.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
#include "gameevent.h"
22

3+
GameEventHandler::~GameEventHandler()
4+
{
5+
setEventHandler(nullptr);
6+
}
7+
38
void GameEventHandler::setEventHandler(GameEventHandler *eh)
49
{
510
if (eh == m_eventhandler)
611
return;
712

8-
if (m_eventhandler)
9-
m_eventhandler->setEventHandler(nullptr);
10-
13+
GameEventHandler *old_eh = m_eventhandler;
1114
m_eventhandler = eh;
12-
eh->setEventHandler(this);
15+
16+
if (old_eh)
17+
old_eh->setEventHandler(nullptr);
18+
if (eh)
19+
eh->setEventHandler(this);
1320
}
1421

1522
bool GameEventHandler::sendNewEvent(GameEvent &e)

src/client/gameevent.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ struct GameEvent {
5757
// Callback execution (1 <---> 1 link)
5858
class GameEventHandler {
5959
public:
60+
virtual ~GameEventHandler();
61+
6062
void setEventHandler(GameEventHandler *eh);
6163
bool sendNewEvent(GameEvent &e); // for memory cleanup
6264

6365
// Callback function to overload. Do NOT call manually!
6466
virtual bool OnEvent(GameEvent &e) = 0;
6567

66-
protected:
68+
private:
6769
GameEventHandler *m_eventhandler = nullptr;
6870
};

src/core/connection.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,25 @@ Connection::Connection(Connection::ConnectionType type, const char *name)
7272

7373
Connection::~Connection()
7474
{
75+
DEBUGLOG("--- ENet %s: Cleaning up ...\n", m_name);
7576
m_running = false;
7677

78+
for (size_t i = 0; i < m_host->peerCount; ++i)
79+
enet_peer_disconnect_later(&m_host->peers[i], 0);
80+
enet_host_flush(m_host);
81+
7782
if (m_thread) {
78-
pthread_join(m_thread, nullptr);
79-
m_thread = 0;
83+
if (pthread_join(m_thread, nullptr) < 0) {
84+
ERRORLOG("--- ENet %s: Failed to join thread status=%d\n", m_name, errno);
85+
}
8086
}
8187

8288
// Apply force if needed
8389
for (size_t i = 0; i < m_host->peerCount; ++i)
8490
enet_peer_reset(&m_host->peers[i]);
8591

8692
enet_host_destroy(m_host);
93+
DEBUGLOG("--- ENet %s: Cleanup done\n", m_name);
8794
}
8895

8996
// -------------- Public members -------------
@@ -134,6 +141,7 @@ bool Connection::listenAsync(PacketProcessor &proc)
134141
return false;
135142

136143
m_running = true;
144+
m_processor = &proc;
137145

138146
int status = pthread_create(&m_thread, nullptr, &recvAsync, this);
139147

@@ -144,7 +152,6 @@ bool Connection::listenAsync(PacketProcessor &proc)
144152
return false;
145153
}
146154

147-
m_processor = &proc;
148155
return m_running;
149156
}
150157

@@ -179,6 +186,9 @@ void Connection::send(peer_t peer_id, uint16_t flags, Packet &pkt)
179186
enet_host_broadcast(m_host, channel, pkt.data());
180187
} else {
181188
auto peer = findPeer(peer_id);
189+
if (!peer)
190+
return;
191+
182192
peer_id = peer->connectID;
183193
enet_peer_send(peer, channel, pkt.data());
184194
}
@@ -195,6 +205,7 @@ void *Connection::recvAsync(void *con_p)
195205
con->recvAsyncInternal();
196206

197207
printf("<-- ENet %s: Thread stop\n", con->m_name);
208+
con->m_thread = 0;
198209
return nullptr;
199210
}
200211

@@ -216,13 +227,16 @@ void Connection::recvAsyncInternal()
216227
enet_peer_disconnect_later(&m_host->peers[i], 0);
217228
}
218229

219-
if (enet_host_service(m_host, &event, 100) <= 0) {
220-
// Abort after 2000 ms
230+
int status = enet_host_service(m_host, &event, 100);
231+
if (status < 0) {
232+
ERRORLOG("--- ENet %s: Got host error code %d\n", m_name, status);
233+
}
234+
if (status <= 0) {
235+
// Abort after 500 ms
221236
if (shutdown_seen > 0) {
222-
if (++shutdown_seen > 20)
237+
if (++shutdown_seen > 5)
223238
break;
224239
}
225-
226240
continue;
227241
}
228242

@@ -297,6 +311,6 @@ _ENetPeer *Connection::findPeer(peer_t peer_id)
297311
return &m_host->peers[i];
298312
}
299313

300-
throw std::runtime_error((std::stringstream() << "Cannot find peer_id=" << peer_id).str());
314+
return nullptr;
301315
}
302316

src/core/packet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ void Packet::writeStr16(const std::string &str)
142142

143143
void Packet::ensureCapacity(size_t nbytes)
144144
{
145-
if (m_write_offset + nbytes > size())
145+
if (m_write_offset + nbytes > m_data->dataLength)
146146
enet_packet_resize(m_data, (m_write_offset + nbytes) * 2);
147147
}
148148

src/core/world.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
#include "world.h"
22
#include "macros.h"
3+
#include "packet.h"
34
#include <cstring> // memset
45

6+
void WorldMeta::readCommon(Packet &pkt)
7+
{
8+
title = pkt.readStr16();
9+
owner = pkt.readStr16();
10+
online = pkt.read<u16>();
11+
plays = pkt.read<u32>();
12+
}
13+
14+
void WorldMeta::writeCommon(Packet &pkt)
15+
{
16+
pkt.writeStr16(title);
17+
pkt.writeStr16(owner);
18+
pkt.write<u16>(online);
19+
pkt.write<u32>(plays);
20+
}
21+
22+
523
template class RefCnt<World>;
624

725
World::World(const std::string &id) :

src/core/world.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@
66
#include <string>
77

88
class Player;
9+
class Packet;
910

1011
struct BlockUpdate : public Block {
1112
peer_t peer_id;
1213
};
1314

1415
struct WorldMeta {
16+
void readCommon(Packet &pkt);
17+
void writeCommon(Packet &pkt);
18+
1519
const std::string id;
1620
std::string edit_code;
1721
std::string title;

src/gui/gameplay.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,13 @@ bool SceneGameplay::OnEvent(GameEvent &e)
324324
m_chathistory_text.append(line);
325325
m_chathistory->setText(m_chathistory_text.c_str());
326326
}
327+
return true;
328+
case E::C2G_DIALOG:
329+
printf(" * SYSTEM: %s\n", e.text->c_str());
327330
break;
331+
case E::C2G_DISCONNECT:
332+
m_gui->disconnect();
333+
return true;
328334
default: break;
329335
}
330336
return false;
@@ -429,7 +435,8 @@ void SceneGameplay::updateWorld()
429435

430436
void SceneGameplay::updatePlayerlist()
431437
{
432-
if (!m_need_playerlist_update)
438+
auto world = m_gui->getClient()->getWorld();
439+
if (!m_need_playerlist_update || !world)
433440
return;
434441

435442
m_need_playerlist_update = false;
@@ -456,14 +463,30 @@ void SceneGameplay::updatePlayerlist()
456463
u32 i = e->addItem(wstr.c_str());
457464
e->setItemOverrideColor(i, 0xFFFFFFFF);
458465
}
466+
467+
// Add world ID and online count
468+
{
469+
rect.UpperLeftCorner.Y = 5;
470+
rect.LowerRightCorner.X += 200;
471+
auto meta = world->getMeta();
472+
std::string src_text;
473+
src_text.append("ID: " + meta.id);
474+
src_text.append("\r\nOwner: " + meta.owner);
475+
476+
core::stringw dst_text;
477+
core::multibyteToWString(dst_text, src_text.c_str());
478+
479+
auto e = m_gui->gui->addStaticText(dst_text.c_str(), rect);
480+
e->setOverrideColor(0xFFFFFFFF);
481+
}
459482
}
460483

461484
void SceneGameplay::updatePlayerPositions()
462485
{
463486
auto smgr = m_world_smgr;
464487
auto texture = m_gui->driver->getTexture("assets/textures/smileys.png");
465488

466-
auto children = m_players->getChildren();
489+
std::list<scene::ISceneNode *> children = m_players->getChildren();
467490
auto players = m_gui->getClient()->getPlayerList();
468491
for (auto it : *players.ptr()) {
469492
auto pos = it.second->pos;
@@ -472,10 +495,9 @@ void SceneGameplay::updatePlayerPositions()
472495
s32 bb_id = it.first + ID_PlayerOffset;
473496
scene::ISceneNode *bb = nullptr;
474497
for (auto &c : children) {
475-
if (c->getID() == bb_id) {
498+
if (c && c->getID() == bb_id) {
476499
bb = c;
477500
c = nullptr; // mark as handled
478-
break;
479501
}
480502
}
481503

@@ -498,6 +520,7 @@ void SceneGameplay::updatePlayerPositions()
498520
mat.setTextureTranslate((it.first % tiles) / (float)tiles, 0);
499521
mat.setTextureScale(1.0f / tiles, 1);
500522

523+
501524
// Add nametag
502525
core::stringw namew;
503526
core::multibyteToWString(namew, it.second->name.c_str());

src/gui/gui.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,15 @@ Gui::Gui()
6767

6868
Gui::~Gui()
6969
{
70+
// Avoid double-frees caused by callback chains
71+
setEventHandler(nullptr);
72+
73+
delete m_client;
74+
delete m_server;
75+
7076
for (auto it : m_handlers)
7177
delete it.second;
78+
m_handlers.clear();
7279

7380
delete device;
7481
}
@@ -227,6 +234,16 @@ void Gui::connect(SceneConnect *sc)
227234
void Gui::disconnect()
228235
{
229236
setNextScene(SceneHandlerType::Connect);
237+
238+
if (m_client) {
239+
delete m_client;
240+
m_client = nullptr;
241+
}
242+
243+
if (m_server) {
244+
delete m_server;
245+
m_server = nullptr;
246+
}
230247
}
231248

232249
void Gui::joinWorld(SceneLobby *sc)

src/gui/gui.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,12 @@ class Gui : public IEventReceiver, public GameEventHandler {
9494
class SceneHandler {
9595
public:
9696
virtual ~SceneHandler() {}
97+
9798
DISABLE_COPY(SceneHandler)
9899

99100
void init(Gui *gui) { m_gui = gui; }
100101

101-
virtual void draw() = 0;
102+
virtual void draw() = 0; // GUI updates
102103
virtual void step(float dtime) = 0;
103104
virtual bool OnEvent(const SEvent &e) = 0;
104105
virtual bool OnEvent(GameEvent &e) = 0;

src/server/server.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,13 @@ void Server::onPeerDisconnected(peer_t peer_id)
145145
if (!player)
146146
return;
147147

148+
{
149+
Packet pkt;
150+
pkt.write(Packet2Client::Leave);
151+
pkt.write(peer_id);
152+
broadcastInWorld(player, 0, pkt);
153+
}
154+
148155
player->setWorld(nullptr);
149156
m_players.erase(peer_id);
150157

0 commit comments

Comments
 (0)