forked from Mirrorlandia_minetest/minetest
Improve loading screen and protocol
This commit is contained in:
parent
cde35d1606
commit
7696a38543
@ -211,7 +211,11 @@ Client::Client(
|
||||
m_time_of_day(0),
|
||||
m_map_seed(0),
|
||||
m_password(password),
|
||||
m_access_denied(false)
|
||||
m_access_denied(false),
|
||||
m_texture_receive_progress(0),
|
||||
m_textures_received(false),
|
||||
m_tooldef_received(false),
|
||||
m_nodedef_received(false)
|
||||
{
|
||||
m_packetcounter_timer = 0.0;
|
||||
//m_delete_unused_sectors_timer = 0.0;
|
||||
@ -661,8 +665,14 @@ void Client::deletingPeer(con::Peer *peer, bool timeout)
|
||||
void Client::ReceiveAll()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
u32 start_ms = porting::getTimeMs();
|
||||
for(;;)
|
||||
{
|
||||
// Limit time even if there would be huge amounts of data to
|
||||
// process
|
||||
if(porting::getTimeMs() > start_ms + 100)
|
||||
break;
|
||||
|
||||
try{
|
||||
Receive();
|
||||
}
|
||||
@ -1505,24 +1515,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
event.deathscreen.camera_point_target_z = camera_point_target.Z;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_TOOLDEF)
|
||||
{
|
||||
infostream<<"Client: Received tool definitions: packet size: "
|
||||
<<datasize<<std::endl;
|
||||
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
m_mesh_update_thread.stop();
|
||||
|
||||
std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
|
||||
m_tooldef->deSerialize(tmp_is);
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
m_mesh_update_thread.Start();
|
||||
}
|
||||
else if(command == TOCLIENT_TEXTURES)
|
||||
{
|
||||
infostream<<"Client: Received textures: packet size: "<<datasize
|
||||
@ -1539,7 +1531,9 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
|
||||
/*
|
||||
u16 command
|
||||
u32 number of textures
|
||||
u16 total number of texture bunches
|
||||
u16 index of this bunch
|
||||
u32 number of textures in this bunch
|
||||
for each texture {
|
||||
u16 length of name
|
||||
string name
|
||||
@ -1547,6 +1541,11 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
data
|
||||
}
|
||||
*/
|
||||
int num_bunches = readU16(is);
|
||||
int bunch_i = readU16(is);
|
||||
m_texture_receive_progress = (float)bunch_i / (float)(num_bunches - 1);
|
||||
if(bunch_i == num_bunches - 1)
|
||||
m_textures_received = true;
|
||||
int num_textures = readU32(is);
|
||||
infostream<<"Client: Received textures: count: "<<num_textures
|
||||
<<std::endl;
|
||||
@ -1572,6 +1571,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
rfile->drop();
|
||||
}
|
||||
|
||||
if(m_nodedef_received && m_textures_received){
|
||||
// Rebuild inherited images and recreate textures
|
||||
m_tsrc->rebuildImagesAndTextures();
|
||||
|
||||
@ -1581,6 +1581,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
|
||||
// Update node textures
|
||||
m_nodedef->updateTextures(m_tsrc);
|
||||
}
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
@ -1590,6 +1591,26 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
event.type = CE_TEXTURES_UPDATED;
|
||||
m_client_event_queue.push_back(event);
|
||||
}
|
||||
else if(command == TOCLIENT_TOOLDEF)
|
||||
{
|
||||
infostream<<"Client: Received tool definitions: packet size: "
|
||||
<<datasize<<std::endl;
|
||||
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
m_tooldef_received = true;
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
m_mesh_update_thread.stop();
|
||||
|
||||
std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
|
||||
m_tooldef->deSerialize(tmp_is);
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
m_mesh_update_thread.Start();
|
||||
}
|
||||
else if(command == TOCLIENT_NODEDEF)
|
||||
{
|
||||
infostream<<"Client: Received node definitions: packet size: "
|
||||
@ -1598,18 +1619,22 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
|
||||
m_nodedef_received = true;
|
||||
|
||||
// Stop threads while updating content definitions
|
||||
m_mesh_update_thread.stop();
|
||||
|
||||
std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
|
||||
m_nodedef->deSerialize(tmp_is, this);
|
||||
|
||||
if(m_textures_received){
|
||||
// Update texture atlas
|
||||
if(g_settings->getBool("enable_texture_atlas"))
|
||||
m_tsrc->buildMainAtlas(this);
|
||||
|
||||
// Update node textures
|
||||
m_nodedef->updateTextures(m_tsrc);
|
||||
}
|
||||
|
||||
// Resume threads
|
||||
m_mesh_update_thread.setRun(true);
|
||||
|
18
src/client.h
18
src/client.h
@ -305,12 +305,22 @@ public:
|
||||
// Get event from queue. CE_NONE is returned if queue is empty.
|
||||
ClientEvent getClientEvent();
|
||||
|
||||
inline bool accessDenied()
|
||||
bool accessDenied()
|
||||
{ return m_access_denied; }
|
||||
|
||||
inline std::wstring accessDeniedReason()
|
||||
std::wstring accessDeniedReason()
|
||||
{ return m_access_denied_reason; }
|
||||
|
||||
float textureReceiveProgress()
|
||||
{ return m_texture_receive_progress; }
|
||||
|
||||
bool texturesReceived()
|
||||
{ return m_textures_received; }
|
||||
bool tooldefReceived()
|
||||
{ return m_tooldef_received; }
|
||||
bool nodedefReceived()
|
||||
{ return m_nodedef_received; }
|
||||
|
||||
float getRTT(void);
|
||||
|
||||
// IGameDef interface
|
||||
@ -367,6 +377,10 @@ private:
|
||||
std::wstring m_access_denied_reason;
|
||||
InventoryContext m_inventory_context;
|
||||
Queue<ClientEvent> m_client_event_queue;
|
||||
float m_texture_receive_progress;
|
||||
bool m_textures_received;
|
||||
bool m_tooldef_received;
|
||||
bool m_nodedef_received;
|
||||
friend class FarMesh;
|
||||
};
|
||||
|
||||
|
@ -28,8 +28,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
PROTOCOL_VERSION 3:
|
||||
Base for writing changes here
|
||||
PROTOCOL_VERSION 4:
|
||||
Add TOCLIENT_TOOLDEF
|
||||
Add TOCLIENT_TEXTURES
|
||||
Add TOCLIENT_TOOLDEF
|
||||
Add TOCLIENT_NODEDEF
|
||||
*/
|
||||
|
||||
@ -195,17 +195,12 @@ enum ToClientCommand
|
||||
v3f1000 camera point target (to point the death cause or whatever)
|
||||
*/
|
||||
|
||||
TOCLIENT_TOOLDEF = 0x38,
|
||||
TOCLIENT_TEXTURES = 0x38,
|
||||
/*
|
||||
u16 command
|
||||
u32 length of the next item
|
||||
serialized ToolDefManager
|
||||
*/
|
||||
|
||||
TOCLIENT_TEXTURES = 0x39,
|
||||
/*
|
||||
u16 command
|
||||
u32 number of textures
|
||||
u16 total number of texture bunches
|
||||
u16 index of this bunch
|
||||
u32 number of textures in this bunch
|
||||
for each texture {
|
||||
u16 length of name
|
||||
string name
|
||||
@ -214,18 +209,19 @@ enum ToClientCommand
|
||||
}
|
||||
*/
|
||||
|
||||
TOCLIENT_TOOLDEF = 0x39,
|
||||
/*
|
||||
u16 command
|
||||
u32 length of the next item
|
||||
serialized ToolDefManager
|
||||
*/
|
||||
|
||||
TOCLIENT_NODEDEF = 0x3a,
|
||||
/*
|
||||
u16 command
|
||||
u32 length of the next item
|
||||
serialized NodeDefManager
|
||||
*/
|
||||
|
||||
//TOCLIENT_CONTENT_SENDING_MODE = 0x38,
|
||||
/*
|
||||
u16 command
|
||||
u8 mode (0 = off, 1 = on)
|
||||
*/
|
||||
};
|
||||
|
||||
enum ToServerCommand
|
||||
|
106
src/game.cpp
106
src/game.cpp
@ -632,21 +632,18 @@ void the_game(
|
||||
/*
|
||||
Draw "Loading" screen
|
||||
*/
|
||||
/*gui::IGUIStaticText *gui_loadingtext = */
|
||||
//draw_load_screen(L"Loading and connecting...", driver, font);
|
||||
|
||||
draw_load_screen(L"Loading...", driver, font);
|
||||
|
||||
// Create tool definition manager
|
||||
IWritableToolDefManager *tooldef = createToolDefManager();
|
||||
// Create texture source
|
||||
IWritableTextureSource *tsrc = createTextureSource(device);
|
||||
|
||||
// These will be filled by data received from the server
|
||||
// Create tool definition manager
|
||||
IWritableToolDefManager *tooldef = createToolDefManager();
|
||||
// Create node definition manager
|
||||
IWritableNodeDefManager *nodedef = createNodeDefManager();
|
||||
|
||||
// Fill node feature table with default definitions
|
||||
//content_mapnode_init(nodedef);
|
||||
|
||||
/*
|
||||
Create server.
|
||||
SharedPtr will delete it when it goes out of scope.
|
||||
@ -703,53 +700,50 @@ void the_game(
|
||||
infostream<<std::endl;
|
||||
client.connect(connect_address);
|
||||
|
||||
/*
|
||||
Wait for server to accept connection
|
||||
*/
|
||||
bool could_connect = false;
|
||||
|
||||
try{
|
||||
float frametime = 0.033;
|
||||
const float timeout = 10.0;
|
||||
float time_counter = 0.0;
|
||||
for(;;)
|
||||
{
|
||||
if(client.connectedAndInitialized())
|
||||
{
|
||||
// Update client and server
|
||||
client.step(frametime);
|
||||
if(server != NULL)
|
||||
server->step(frametime);
|
||||
|
||||
// End condition
|
||||
if(client.connectedAndInitialized()){
|
||||
could_connect = true;
|
||||
break;
|
||||
}
|
||||
// Break conditions
|
||||
if(client.accessDenied())
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Wait for 10 seconds
|
||||
if(time_counter >= 10.0)
|
||||
{
|
||||
if(time_counter >= timeout)
|
||||
break;
|
||||
}
|
||||
|
||||
// Display status
|
||||
std::wostringstream ss;
|
||||
ss<<L"Connecting to server... (timeout in ";
|
||||
ss<<(int)(10.0 - time_counter + 1.0);
|
||||
ss<<(int)(timeout - time_counter + 1.0);
|
||||
ss<<L" seconds)";
|
||||
draw_load_screen(ss.str(), driver, font);
|
||||
|
||||
/*// Update screen
|
||||
driver->beginScene(true, true, video::SColor(255,0,0,0));
|
||||
guienv->drawAll();
|
||||
driver->endScene();*/
|
||||
|
||||
// Update client and server
|
||||
|
||||
client.step(0.1);
|
||||
|
||||
if(server != NULL)
|
||||
server->step(0.1);
|
||||
|
||||
// Delay a bit
|
||||
sleep_ms(100);
|
||||
time_counter += 0.1;
|
||||
sleep_ms(1000*frametime);
|
||||
time_counter += frametime;
|
||||
}
|
||||
}
|
||||
catch(con::PeerNotFoundException &e)
|
||||
{}
|
||||
|
||||
/*
|
||||
Handle failure to connect
|
||||
*/
|
||||
if(could_connect == false)
|
||||
{
|
||||
if(client.accessDenied())
|
||||
@ -767,6 +761,56 @@ void the_game(
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Wait until content has been received
|
||||
*/
|
||||
bool got_content = false;
|
||||
{
|
||||
float frametime = 0.033;
|
||||
const float timeout = 5.0;
|
||||
float time_counter = 0.0;
|
||||
for(;;)
|
||||
{
|
||||
// Update client and server
|
||||
client.step(frametime);
|
||||
if(server != NULL)
|
||||
server->step(frametime);
|
||||
|
||||
// End condition
|
||||
if(client.texturesReceived() &&
|
||||
client.tooldefReceived() &&
|
||||
client.nodedefReceived()){
|
||||
got_content = true;
|
||||
break;
|
||||
}
|
||||
// Break conditions
|
||||
if(!client.connectedAndInitialized())
|
||||
break;
|
||||
if(time_counter >= timeout)
|
||||
break;
|
||||
|
||||
// Display status
|
||||
std::wostringstream ss;
|
||||
ss<<L"Waiting content... (continuing anyway in ";
|
||||
ss<<(int)(timeout - time_counter + 1.0);
|
||||
ss<<L" seconds)\n";
|
||||
|
||||
ss<<(client.tooldefReceived()?L"[X]":L"[ ]");
|
||||
ss<<L" Tool definitions\n";
|
||||
ss<<(client.nodedefReceived()?L"[X]":L"[ ]");
|
||||
ss<<L" Node definitions\n";
|
||||
//ss<<(client.texturesReceived()?L"[X]":L"[ ]");
|
||||
ss<<L"["<<(int)(client.textureReceiveProgress()*100+0.5)<<L"%] ";
|
||||
ss<<L" Textures\n";
|
||||
|
||||
draw_load_screen(ss.str(), driver, font);
|
||||
|
||||
// Delay a bit
|
||||
sleep_ms(1000*frametime);
|
||||
time_counter += frametime;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Create skybox
|
||||
*/
|
||||
|
@ -2139,15 +2139,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
Send some initialization data
|
||||
*/
|
||||
|
||||
// Send textures
|
||||
SendTextures(peer_id);
|
||||
|
||||
// Send tool definitions
|
||||
SendToolDef(m_con, peer_id, m_toolmgr);
|
||||
|
||||
// Send node definitions
|
||||
SendNodeDef(m_con, peer_id, m_nodemgr);
|
||||
|
||||
// Send textures
|
||||
SendTextures(peer_id);
|
||||
|
||||
// Send player info to all players
|
||||
SendPlayerInfos();
|
||||
|
||||
@ -4160,7 +4160,13 @@ void Server::SendTextures(u16 peer_id)
|
||||
|
||||
/* Read textures */
|
||||
|
||||
core::list<SendableTexture> textures;
|
||||
// Put 5kB in one bunch (this is not accurate)
|
||||
u32 bytes_per_bunch = 5000;
|
||||
|
||||
core::array< core::list<SendableTexture> > texture_bunches;
|
||||
texture_bunches.push_back(core::list<SendableTexture>());
|
||||
|
||||
u32 texture_size_bunch_total = 0;
|
||||
core::list<ModSpec> mods = getMods(m_modspaths);
|
||||
for(core::list<ModSpec>::Iterator i = mods.begin();
|
||||
i != mods.end(); i++){
|
||||
@ -4186,6 +4192,7 @@ void Server::SendTextures(u16 peer_id)
|
||||
fis.read(buf, 1024);
|
||||
std::streamsize len = fis.gcount();
|
||||
tmp_os.write(buf, len);
|
||||
texture_size_bunch_total += len;
|
||||
if(fis.eof())
|
||||
break;
|
||||
if(!fis.good()){
|
||||
@ -4201,15 +4208,27 @@ void Server::SendTextures(u16 peer_id)
|
||||
errorstream<<"Server::SendTextures(): Loaded \""
|
||||
<<tname<<"\""<<std::endl;
|
||||
// Put in list
|
||||
textures.push_back(SendableTexture(tname, tpath, tmp_os.str()));
|
||||
texture_bunches[texture_bunches.size()-1].push_back(
|
||||
SendableTexture(tname, tpath, tmp_os.str()));
|
||||
|
||||
// Start next bunch if got enough data
|
||||
if(texture_size_bunch_total >= bytes_per_bunch){
|
||||
texture_bunches.push_back(core::list<SendableTexture>());
|
||||
texture_size_bunch_total = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create and send packet */
|
||||
/* Create and send packets */
|
||||
|
||||
u32 num_bunches = texture_bunches.size();
|
||||
for(u32 i=0; i<num_bunches; i++)
|
||||
{
|
||||
/*
|
||||
u16 command
|
||||
u32 number of textures
|
||||
u16 total number of texture bunches
|
||||
u16 index of this bunch
|
||||
u32 number of textures in this bunch
|
||||
for each texture {
|
||||
u16 length of name
|
||||
string name
|
||||
@ -4220,21 +4239,26 @@ void Server::SendTextures(u16 peer_id)
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
||||
writeU16(os, TOCLIENT_TEXTURES);
|
||||
writeU32(os, textures.size());
|
||||
writeU16(os, num_bunches);
|
||||
writeU16(os, i);
|
||||
writeU32(os, texture_bunches[i].size());
|
||||
|
||||
for(core::list<SendableTexture>::Iterator i = textures.begin();
|
||||
i != textures.end(); i++){
|
||||
os<<serializeString(i->name);
|
||||
os<<serializeLongString(i->data);
|
||||
for(core::list<SendableTexture>::Iterator
|
||||
j = texture_bunches[i].begin();
|
||||
j != texture_bunches[i].end(); j++){
|
||||
os<<serializeString(j->name);
|
||||
os<<serializeLongString(j->data);
|
||||
}
|
||||
|
||||
// Make data buffer
|
||||
std::string s = os.str();
|
||||
infostream<<"Server::SendTextures(): number of textures: "
|
||||
<<textures.size()<<", data size: "<<s.size()<<std::endl;
|
||||
infostream<<"Server::SendTextures(): number of textures in bunch["
|
||||
<<i<<"]: "<<texture_bunches[i].size()
|
||||
<<", size: "<<s.size()<<std::endl;
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// Send as reliable
|
||||
m_con.Send(peer_id, 0, data, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user