diff --git a/Makefile b/Makefile index 39ab17059..5dad9433f 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ # Makefile for Irrlicht Examples # It's usually sufficient to change just the target name and source file list # and be sure that CXX is set to a valid compiler -TARGET = test SOURCE_FILES = guiTextInputMenu.cpp guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp -SOURCES = $(addprefix src/, $(SOURCE_FILES)) -BUILD_DIR = build -OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o)) + +DEBUG_TARGET = debugtest +DEBUG_SOURCES = $(addprefix src/, $(SOURCE_FILES)) +DEBUG_BUILD_DIR = debugbuild +DEBUG_OBJECTS = $(addprefix $(DEBUG_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o)) FAST_TARGET = fasttest FAST_SOURCES = $(addprefix src/, $(SOURCE_FILES)) @@ -24,48 +25,49 @@ JTHREADPATH = ../jthread/jthread-1.2.1 #CXXFLAGS = -O2 -ffast-math -Wall -fomit-frame-pointer -pipe #CXXFLAGS = -O2 -ffast-math -Wall -g -pipe #CXXFLAGS = -O1 -ffast-math -Wall -g -CXXFLAGS = -Wall -g -O0 +CXXFLAGS = -Wall -g -O1 -all: fast_linux +all: fast ifeq ($(HOSTTYPE), x86_64) LIBSELECT=64 endif -all_linux fast_linux: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L$(IRRLICHTPATH)/lib/Linux -L$(JTHREADPATH)/src/.libs -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -ljthread -lz -all_linux fast_linux: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -fast_linux server_linux: CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686 -server_linux: LDFLAGS = -L$(JTHREADPATH)/src/.libs -ljthread -lz -lpthread -server_linux: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DSERVER -all_linux fast_linux clean_linux: SYSTEM=Linux +debug fast: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L$(IRRLICHTPATH)/lib/Linux -L$(JTHREADPATH)/src/.libs -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -ljthread -lz +debug: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DDEBUG +fast: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DUNITTEST_DISABLE +fast server: CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686 +server: LDFLAGS = -L$(JTHREADPATH)/src/.libs -ljthread -lz -lpthread +server: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DSERVER -DUNITTEST_DISABLE +debug fast clean_debug: SYSTEM=Linux -DESTPATH = bin/$(TARGET) +DEBUG_DESTPATH = bin/$(DEBUG_TARGET) FAST_DESTPATH = bin/$(FAST_TARGET) SERVER_DESTPATH = bin/$(SERVER_TARGET) # Build commands -all_linux: $(BUILD_DIR) $(DESTPATH) -fast_linux: $(FAST_BUILD_DIR) $(FAST_DESTPATH) -server_linux: $(SERVER_BUILD_DIR) $(SERVER_DESTPATH) +debug: $(DEBUG_BUILD_DIR) $(DEBUG_DESTPATH) +fast: $(FAST_BUILD_DIR) $(FAST_DESTPATH) +server: $(SERVER_BUILD_DIR) $(SERVER_DESTPATH) -$(BUILD_DIR): - mkdir -p $(BUILD_DIR) +$(DEBUG_BUILD_DIR): + mkdir -p $(DEBUG_BUILD_DIR) $(FAST_BUILD_DIR): mkdir -p $(FAST_BUILD_DIR) $(SERVER_BUILD_DIR): mkdir -p $(SERVER_BUILD_DIR) -$(DESTPATH): $(OBJECTS) - $(CXX) -o $@ $(OBJECTS) $(LDFLAGS) +$(DEBUG_DESTPATH): $(DEBUG_OBJECTS) + $(CXX) -o $@ $(DEBUG_OBJECTS) $(LDFLAGS) $(FAST_DESTPATH): $(FAST_OBJECTS) - $(CXX) -o $@ $(FAST_OBJECTS) $(LDFLAGS) -DUNITTEST_DISABLE + $(CXX) -o $@ $(FAST_OBJECTS) $(LDFLAGS) $(SERVER_DESTPATH): $(SERVER_OBJECTS) - $(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS) -DSERVER -DUNITTEST_DISABLE + $(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS) -$(BUILD_DIR)/%.o: src/%.cpp +$(DEBUG_BUILD_DIR)/%.o: src/%.cpp $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) $(FAST_BUILD_DIR)/%.o: src/%.cpp @@ -74,15 +76,15 @@ $(FAST_BUILD_DIR)/%.o: src/%.cpp $(SERVER_BUILD_DIR)/%.o: src/%.cpp $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) -clean: clean_linux clean_fast_linux clean_server_linux +clean: clean_debug clean_fast clean_server -clean_linux: - @$(RM) $(OBJECTS) $(DESTPATH) +clean_debug: + @$(RM) $(DEBUG_OBJECTS) $(DEBUG_DESTPATH) -clean_fast_linux: +clean_fast: @$(RM) $(FAST_OBJECTS) $(FAST_DESTPATH) -clean_server_linux: +clean_server: @$(RM) $(SERVER_OBJECTS) $(SERVER_DESTPATH) -.PHONY: all all_win32 clean clean_linux clean_win32 clean_fast_linux clean_server_linux +.PHONY: all all_win32 clean clean_debug clean_win32 clean_fast clean_server diff --git a/data/crack.png b/data/crack.png index e39b74da0..0fef2a6fd 100644 Binary files a/data/crack.png and b/data/crack.png differ diff --git a/minetest.vcproj b/minetest.vcproj index f27c4bcdc..f7a125d0d 100644 --- a/minetest.vcproj +++ b/minetest.vcproj @@ -206,6 +206,10 @@ RelativePath=".\src\guiPauseMenu.cpp" > + + diff --git a/src/client.cpp b/src/client.cpp index 23f9d2a55..ff40f674f 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -447,8 +447,6 @@ void Client::ReceiveAll() "InvalidIncomingDataException: what()=" < modified_blocks; - - try - { - JMutexAutoLock envlock(m_env_mutex); - //TimeTaker t("removeNodeAndUpdate", m_device); - m_env.getMap().removeNodeAndUpdate(p, modified_blocks); - } - catch(InvalidPositionException &e) - { - } - - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - //m_env.getMap().updateMeshes(p); - mesh_updater.add(p); - } + removeNode(p); } else if(command == TOCLIENT_ADDNODE) { @@ -1078,24 +1084,7 @@ bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater) MapNode n; n.deSerialize(&data[8], ser_version); - core::map modified_blocks; - - try - { - JMutexAutoLock envlock(m_env_mutex); - m_env.getMap().addNodeAndUpdate(p, n, modified_blocks); - } - catch(InvalidPositionException &e) - {} - - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) - { - v3s16 p = i.getNode()->getKey(); - //m_env.getMap().updateMeshes(p); - mesh_updater.add(p); - } + addNode(p, n); } else if(command == TOCLIENT_BLOCKDATA) { @@ -1190,25 +1179,6 @@ bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater) } } //envlock - - // Old version has zero lighting, update it. - if(ser_version == 0 || ser_version == 1) - { - derr_client<<"Client: Block in old format: " - "Calculating lighting"< blocks_changed; - blocks_changed.insert(block->getPos(), block); - core::map modified_blocks; - m_env.getMap().updateLighting(blocks_changed, modified_blocks); - } - - /* - Update Mesh of this block and blocks at x-, y- and z- - */ - - //m_env.getMap().updateMeshes(block->getPos()); - mesh_updater.add(block->getPos()); - /* Acknowledge block. */ @@ -1227,39 +1197,13 @@ bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater) // Send as reliable m_con.Send(PEER_ID_SERVER, 1, reply, true); -#if 0 /* - Remove from history + Update Mesh of this block and blocks at x-, y- and z-. + Environment should not be locked as it interlocks with the + main thread, from which is will want to retrieve textures. */ - { - JMutexAutoLock lock(m_fetchblock_mutex); - - if(m_fetchblock_history.find(p) != NULL) - { - m_fetchblock_history.remove(p); - } - else - { - /* - Acknowledge block. - */ - /* - [0] u16 command - [2] u8 count - [3] v3s16 pos_0 - [3+6] v3s16 pos_1 - ... - */ - u32 replysize = 2+1+6; - SharedBuffer reply(replysize); - writeU16(&reply[0], TOSERVER_GOTBLOCKS); - reply[2] = 1; - writeV3S16(&reply[3], p); - // Send as reliable - m_con.Send(PEER_ID_SERVER, 1, reply, true); - } - } -#endif + + m_env.getMap().updateMeshes(block->getPos(), getDayNightRatio()); } else { @@ -1383,71 +1327,6 @@ IncomingPacket Client::getPacket() return packet; } -#if 0 -void Client::removeNode(v3s16 nodepos) -{ - if(connectedAndInitialized() == false){ - dout_client< data(8); - writeU16(&data[0], TOSERVER_REMOVENODE); - writeS16(&data[2], nodepos.X); - writeS16(&data[4], nodepos.Y); - writeS16(&data[6], nodepos.Z); - Send(0, data, true); -} - -void Client::addNodeFromInventory(v3s16 nodepos, u16 i) -{ - if(connectedAndInitialized() == false){ - dout_client< data(datasize); - writeU16(&data[0], TOSERVER_ADDNODE_FROM_INVENTORY); - writeS16(&data[2], nodepos.X); - writeS16(&data[4], nodepos.Y); - writeS16(&data[6], nodepos.Z); - writeU16(&data[8], i); - Send(0, data, true); -} -#endif - void Client::groundAction(u8 action, v3s16 nodepos_undersurface, v3s16 nodepos_oversurface, u16 item) { @@ -1563,6 +1442,34 @@ void Client::sendInventoryAction(InventoryAction *a) Send(0, data, true); } +void Client::sendChatMessage(const std::wstring &message) +{ + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOSERVER_CHAT_MESSAGE); + os.write((char*)buf, 2); + + // Write length + writeU16(buf, message.size()); + os.write((char*)buf, 2); + + // Write string + for(u32 i=0; i data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); +} + void Client::sendPlayerPos() { JMutexAutoLock envlock(m_env_mutex); @@ -1610,7 +1517,52 @@ void Client::sendPlayerPos() Send(0, data, false); } +void Client::removeNode(v3s16 p) +{ + JMutexAutoLock envlock(m_env_mutex); + + core::map modified_blocks; + try + { + //TimeTaker t("removeNodeAndUpdate", m_device); + m_env.getMap().removeNodeAndUpdate(p, modified_blocks); + } + catch(InvalidPositionException &e) + { + } + + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) + { + v3s16 p = i.getNode()->getKey(); + m_env.getMap().updateMeshes(p, m_env.getDayNightRatio()); + } +} + +void Client::addNode(v3s16 p, MapNode n) +{ + JMutexAutoLock envlock(m_env_mutex); + + core::map modified_blocks; + + try + { + m_env.getMap().addNodeAndUpdate(p, n, modified_blocks); + } + catch(InvalidPositionException &e) + {} + + for(core::map::Iterator + i = modified_blocks.getIterator(); + i.atEnd() == false; i++) + { + v3s16 p = i.getNode()->getKey(); + m_env.getMap().updateMeshes(p, m_env.getDayNightRatio()); + } +} + void Client::updateCamera(v3f pos, v3f dir) { m_env.getMap().updateCamera(pos, dir); diff --git a/src/client.h b/src/client.h index 3c8bbfaf6..6fb608b84 100644 --- a/src/client.h +++ b/src/client.h @@ -191,6 +191,12 @@ public: void sendSignText(v3s16 blockpos, s16 id, std::string text); void sendInventoryAction(InventoryAction *a); + void sendChatMessage(const std::wstring &message); + + // locks envlock + void removeNode(v3s16 p); + // locks envlock + void addNode(v3s16 p, MapNode n); void updateCamera(v3f pos, v3f dir); @@ -201,14 +207,7 @@ public: // Returns InvalidPositionException if not found //f32 getGroundHeight(v2s16 p); - // Returns InvalidPositionException if not found - //bool isNodeUnderground(v3s16 p); - // Note: The players should not be exposed outside - // Return value is valid until client is destroyed - //Player * getLocalPlayer(); - // Return value is valid until step() - //core::list getPlayers(); v3f getPlayerPosition(); void setPlayerControl(PlayerControl &control); @@ -218,8 +217,6 @@ public: bool getLocalInventoryUpdated(); // Copies the inventory of the local player to parameter void getLocalInventory(Inventory &dst); - // TODO: Functions for sending inventory editing commands to - // server // Gets closest object pointed by the shootline // Returns NULL if not found @@ -260,7 +257,25 @@ public: return 0.0; return peer->avg_rtt; } - + + bool getChatMessage(std::wstring &message) + { + if(m_chat_queue.size() == 0) + return false; + message = m_chat_queue.pop_front(); + return true; + } + + void addChatMessage(const std::wstring &message) + { + JMutexAutoLock envlock(m_env_mutex); + LocalPlayer *player = m_env.getLocalPlayer(); + assert(player != NULL); + std::wstring name = narrow_to_wide(player->getName()); + m_chat_queue.push_back( + (std::wstring)L"<"+name+L"> "+message); + } + private: // Virtual methods from con::PeerHandler @@ -273,7 +288,7 @@ private: void sendPlayerPos(); // This sends the player's current name etc to the server void sendPlayerInfo(); - + float m_packetcounter_timer; float m_delete_unused_sectors_timer; float m_connection_reinit_timer; @@ -321,6 +336,8 @@ private: // 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT //s32 m_daynight_i; //u32 m_daynight_ratio; + + Queue m_chat_queue; }; #endif // !SERVER diff --git a/src/clientserver.h b/src/clientserver.h index c8a114841..07b1cf60f 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -98,6 +98,14 @@ enum ToClientCommand u16 command u16 time (0-23999) */ + + TOCLIENT_CHAT_MESSAGE = 0x30, + /* + u16 command + u16 length + wstring message + */ + }; enum ToServerCommand @@ -179,6 +187,7 @@ enum ToServerCommand 0: start digging (from undersurface) 1: place block (to abovesurface) 2: stop digging (all parameters ignored) + 3: digging completed */ TOSERVER_RELEASE = 0x29, // Not used @@ -196,6 +205,14 @@ enum ToServerCommand /* See InventoryAction in inventory.h */ + + TOSERVER_CHAT_MESSAGE = 0x32, + /* + u16 command + u16 length + wstring message + */ + }; inline SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time) diff --git a/src/constants.h b/src/constants.h index cf394ca02..b6b09b50b 100644 --- a/src/constants.h +++ b/src/constants.h @@ -47,7 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc., // Time after building, during which the following limit // is in use -#define FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING 2.0 +//#define FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING 2.0 // This many blocks are sent when player is building #define LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS 0 // Override for the previous one when distance of block @@ -69,7 +69,11 @@ with this program; if not, write to the Free Software Foundation, Inc., // Whether to catch all std::exceptions. // Assert will be called on such an event. -#define CATCH_UNHANDLED_EXCEPTIONS 1 +#ifdef DEBUG + #define CATCH_UNHANDLED_EXCEPTIONS 0 +#else + #define CATCH_UNHANDLED_EXCEPTIONS 1 +#endif /* Collecting active blocks is stopped after object data @@ -80,7 +84,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define WATER_LEVEL (0) // Length of cracking animation in count of images -#define CRACK_ANIMATION_LENGTH 4 +#define CRACK_ANIMATION_LENGTH 5 #endif diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index b288d028c..66564bc1f 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -60,5 +60,6 @@ void set_default_settings() g_settings.setDefault("time_speed", "96"); g_settings.setDefault("server_unload_unused_sectors_timeout", "60"); g_settings.setDefault("server_map_save_interval", "60"); + g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0"); } diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index 2a0b3cb0c..ae1f58a9d 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -106,6 +106,7 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) L"- R: Toggle viewing all loaded chunks\n" L"- I: Inventory menu\n" L"- ESC: This menu\n" + L"- T: Chat\n" L"\n" L"To generate a new map, remove the map directory.\n"; Environment->addStaticText(text, rect, false, true, this, 258); diff --git a/src/guiTextInputMenu.cpp b/src/guiTextInputMenu.cpp index 0668aa7b3..787680bc5 100644 --- a/src/guiTextInputMenu.cpp +++ b/src/guiTextInputMenu.cpp @@ -37,6 +37,8 @@ GUITextInputMenu::GUITextInputMenu(gui::IGUIEnvironment* env, GUITextInputMenu::~GUITextInputMenu() { removeChildren(); + if(m_dest) + delete m_dest; } void GUITextInputMenu::removeChildren() @@ -173,6 +175,16 @@ bool GUITextInputMenu::OnEvent(const SEvent& event) break; } } + if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER) + { + switch(event.GUIEvent.Caller->getID()) + { + case 256: + acceptInput(); + quitMenu(); + break; + } + } } return Parent ? Parent->OnEvent(event) : false; diff --git a/src/irrlichtwrapper.cpp b/src/irrlichtwrapper.cpp index 51511eb34..c012b136e 100644 --- a/src/irrlichtwrapper.cpp +++ b/src/irrlichtwrapper.cpp @@ -51,16 +51,25 @@ video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec) // Throw a request in m_get_texture_queue.add(spec, 0, 0, &result_queue); - dstream<<"Waiting for texture "< - result = result_queue.pop_front(1000); + dstream<<"Waiting for texture from main thread: " + < + result = result_queue.pop_front(1000); + + // Check that at least something worked OK + assert(result.key.name == spec.name); - t = result.item; + t = result.item; + } + catch(ItemNotFoundException &e) + { + dstream<<"Waiting for texture timed out."<getTime(); } +/* + Text input system +*/ + +struct TextDestSign : public TextDest +{ + TextDestSign(v3s16 blockpos, s16 id, Client *client) + { + m_blockpos = blockpos; + m_id = id; + m_client = client; + } + void gotText(std::wstring text) + { + std::string ntext = wide_to_narrow(text); + dstream<<"Changing text of a sign object: " + <sendSignText(m_blockpos, m_id, ntext); + } + + v3s16 m_blockpos; + s16 m_id; + Client *m_client; +}; + +struct TextDestChat : public TextDest +{ + TextDestChat(Client *client) + { + m_client = client; + } + void gotText(std::wstring text) + { + m_client->sendChatMessage(text); + m_client->addChatMessage(text); + } + + Client *m_client; +}; + class MyEventReceiver : public IEventReceiver { public: @@ -371,6 +415,14 @@ public: &g_active_menu_count))->drop(); return true; } + if(event.KeyInput.Key == irr::KEY_KEY_T) + { + TextDest *dest = new TextDestChat(g_client); + + (new GUITextInputMenu(guienv, guiroot, -1, + &g_active_menu_count, dest, + L""))->drop(); + } } // Material selection @@ -965,31 +1017,6 @@ private: s32 m_selection; }; -/* - Text input system -*/ - -struct TextDestSign : public TextDest -{ - TextDestSign(v3s16 blockpos, s16 id, Client *client) - { - m_blockpos = blockpos; - m_id = id; - m_client = client; - } - void gotText(std::wstring text) - { - std::string ntext = wide_to_narrow(text); - dstream<<"Changing text of a sign object: " - <sendSignText(m_blockpos, m_id, ntext); - } - - v3s16 m_blockpos; - s16 m_id; - Client *m_client; -}; - int main(int argc, char *argv[]) { /* @@ -1334,6 +1361,10 @@ int main(int argc, char *argv[]) gui::IGUIFont* font = guienv->getFont("../data/fontlucida.png"); if(font) skin->setFont(font); + + u32 text_height = font->getDimension(L"Hello, world!").Height; + dstream<<"text_height="<setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); @@ -1343,11 +1374,7 @@ int main(int argc, char *argv[]) const wchar_t *text = L"Loading and connecting..."; core::vector2d center(screenW/2, screenH/2); - core::dimension2d textd = font->getDimension(text); - std::cout<(70, 60, 795, 150), + false, true); + core::list chat_lines; + //chat_lines.push_back(L"Minetest-c55 up and running!"); + /* Some statistics are collected in these */ @@ -2033,7 +2070,7 @@ int main(int argc, char *argv[]) if(g_input->getLeftClicked() || (g_input->getLeftState() && nodepos != nodepos_old)) { - std::cout<getLeftClicked()) @@ -2042,23 +2079,28 @@ int main(int argc, char *argv[]) } if(g_input->getLeftState()) { - float dig_time_complete = 0.5; MapNode n = client.getNode(nodepos); + + // TODO: Get this from some table that is sent by server + float dig_time_complete = 0.5; if(n.d == CONTENT_STONE) dig_time_complete = 1.5; - float dig_time_complete0 = dig_time_complete+client.getAvgRtt()*2; - if(dig_time_complete0 < 0.0) - dig_time_complete0 = 0.0; - dig_index = (u16)((float)CRACK_ANIMATION_LENGTH - * dig_time/dig_time_complete0); + * dig_time/dig_time_complete); - if(dig_time > 0.125 && dig_index < CRACK_ANIMATION_LENGTH) + if(dig_index < CRACK_ANIMATION_LENGTH) { //dstream<<"dig_index="<getLeftReleased()) { - std::cout<getRightReleased()) @@ -2180,16 +2223,44 @@ int main(int argc, char *argv[]) } { - /*wchar_t temptext[100]; - swprintf(temptext, 100, - SWPRINTF_CHARSTRING, - infotext.substr(0,99).c_str() - ); - - guitext_info->setText(temptext);*/ - guitext_info->setText(infotext.c_str()); } + + /* + Get chat messages from client + */ + { + // Get messages + std::wstring message; + while(client.getChatMessage(message)) + { + chat_lines.push_back(message); + if(chat_lines.size() > 5) + { + core::list::Iterator + i = chat_lines.begin(); + chat_lines.erase(i); + } + } + // Append them to form the whole static text and throw + // it to the gui element + std::wstring whole; + for(core::list::Iterator + i = chat_lines.begin(); + i != chat_lines.end(); i++) + { + whole += (*i) + L'\n'; + } + chat_guitext->setText(whole.c_str()); + // Update gui element size and position + core::rect rect( + 10, + screensize.Y - 10 - text_height*chat_lines.size(), + screensize.X - 10, + screensize.Y - 10 + ); + chat_guitext->setRelativePosition(rect); + } /* Inventory diff --git a/src/server.cpp b/src/server.cpp index 8b063b60d..d7bd22668 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -355,8 +355,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, { SharedPtr lock(m_time_from_building.getLock()); m_time_from_building.m_value += dtime; - if(m_time_from_building.m_value - < FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING) + /*if(m_time_from_building.m_value + < FULL_BLOCK_SEND_ENABLE_MIN_TIME_FROM_BUILDING)*/ + if(m_time_from_building.m_value < g_settings.getFloat( + "full_block_send_enable_min_time_from_building")) { maximum_simultaneous_block_sends = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS; @@ -1188,7 +1190,7 @@ void Server::AsyncRunStep() NOTE: Some of this could be moved to RemoteClient */ - +#if 0 { JMutexAutoLock envlock(m_env_mutex); JMutexAutoLock conlock(m_con_mutex); @@ -1208,7 +1210,10 @@ void Server::AsyncRunStep() client->m_dig_time_remaining -= dtime; if(client->m_dig_time_remaining > 0) + { + client->m_time_from_building.set(0.0); continue; + } v3s16 p_under = client->m_dig_position; @@ -1287,6 +1292,7 @@ void Server::AsyncRunStep() v.blitBack(modified_blocks); } } +#endif // Send object positions { @@ -1493,6 +1499,20 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) m_time_of_day.get()); m_con.Send(peer->id, 0, data, true); } + + // Send information about joining in chat + { + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(peer_id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + + std::wstring message; + message += L"*** "; + message += name; + message += L" joined game"; + BroadcastChatMessage(message); + } return; } @@ -1688,7 +1708,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) */ if(action == 0) { + /* + NOTE: This can be used in the future to check if + somebody is cheating, by checking the timing. + */ +#if 0 u8 content; try @@ -1728,7 +1753,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Reset build time counter getClient(peer->id)->m_time_from_building.set(0.0); - +#endif } // action == 0 /* @@ -1736,11 +1761,117 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) */ else if(action == 2) { +#if 0 RemoteClient *client = getClient(peer->id); JMutexAutoLock digmutex(client->m_dig_mutex); client->m_dig_tool_item = -1; +#endif } + /* + 3: Digging completed + */ + if(action == 3) + { + // Mandatory parameter; actually used for nothing + core::map modified_blocks; + + u8 material; + + try + { + // Get material at position + material = m_env.getMap().getNode(p_under).d; + // If it's not diggable, do nothing + if(content_diggable(material) == false) + { + derr_server<<"Server: Not finishing digging: Node not diggable" + < reply(replysize); + writeU16(&reply[0], TOCLIENT_REMOVENODE); + writeS16(&reply[2], p_under.X); + writeS16(&reply[4], p_under.Y); + writeS16(&reply[6], p_under.Z); + + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + // Get client and check that it is valid + RemoteClient *client = i.getNode()->getValue(); + assert(client->peer_id == i.getNode()->getKey()); + if(client->serialization_version == SER_FMT_VER_INVALID) + continue; + + // Don't send if it's the same one + if(peer_id == client->peer_id) + continue; + + // Send as reliable + m_con.Send(client->peer_id, 0, reply, true); + } + + /* + Update and send inventory + */ + + if(g_settings.getBool("creative_mode") == false) + { + // Add to inventory and send inventory + InventoryItem *item = new MaterialItem(material, 1); + player->inventory.addItem("main", item); + SendInventory(player->peer_id); + } + + /* + Remove the node + (this takes some time so it is done after the quick stuff) + */ + m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks); + + /* + Update water + */ + + // Update water pressure around modification + // This also adds it to m_flow_active_nodes if appropriate + + MapVoxelManipulator v(&m_env.getMap()); + v.m_disable_water_climb = + g_settings.getBool("disable_water_climb"); + + VoxelArea area(p_under-v3s16(1,1,1), p_under+v3s16(1,1,1)); + + try + { + v.updateAreaWaterPressure(area, m_flow_active_nodes); + } + catch(ProcessingLimitException &e) + { + dstream<<"Processing limit reached (1)"<::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + // Get client and check that it is valid + RemoteClient *client = i.getNode()->getValue(); + assert(client->peer_id == i.getNode()->getKey()); + if(client->serialization_version == SER_FMT_VER_INVALID) + continue; + + // Don't send if it's the same one + if(peer_id == client->peer_id) + continue; + + // Get player name of this client + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(client->peer_id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + + SendChatMessage(client->peer_id, + std::wstring(L"<")+name+L"> "+message); + } + } else { derr_server<<"WARNING: Server::ProcessData(): Ignoring " @@ -2401,8 +2584,6 @@ void Server::SendInventory(u16 peer_id) { DSTACK(__FUNCTION_NAME); - //JMutexAutoLock envlock(m_env_mutex); - Player* player = m_env.getPlayer(peer_id); /* @@ -2464,12 +2645,56 @@ void Server::SendInventory(u16 peer_id) writeU16(&data[0], TOCLIENT_INVENTORY); memcpy(&data[2], s.c_str(), s.size()); - //JMutexAutoLock conlock(m_con_mutex); - // Send as reliable m_con.Send(peer_id, 0, data, true); } +void Server::SendChatMessage(u16 peer_id, const std::wstring &message) +{ + DSTACK(__FUNCTION_NAME); + + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOCLIENT_CHAT_MESSAGE); + os.write((char*)buf, 2); + + // Write length + writeU16(buf, message.size()); + os.write((char*)buf, 2); + + // Write string + for(u32 i=0; i data((u8*)s.c_str(), s.size()); + // Send as reliable + m_con.Send(peer_id, 0, data, true); +} + +void Server::BroadcastChatMessage(const std::wstring &message) +{ + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + // Get client and check that it is valid + RemoteClient *client = i.getNode()->getValue(); + assert(client->peer_id == i.getNode()->getKey()); + if(client->serialization_version == SER_FMT_VER_INVALID) + continue; + + SendChatMessage(client->peer_id, message); + } +} + void Server::SendBlocks(float dtime) { DSTACK(__FUNCTION_NAME); diff --git a/src/server.h b/src/server.h index d002d9f4c..f1baaf240 100644 --- a/src/server.h +++ b/src/server.h @@ -242,9 +242,9 @@ public: m_blocks_sent_mutex.Init(); m_blocks_sending_mutex.Init(); - m_dig_mutex.Init(); + /*m_dig_mutex.Init(); m_dig_time_remaining = 0; - m_dig_tool_item = -1; + m_dig_tool_item = -1;*/ } ~RemoteClient() { @@ -301,11 +301,11 @@ public: // Time from last placing or removing blocks MutexedVariable m_time_from_building; - JMutex m_dig_mutex; + /*JMutex m_dig_mutex; float m_dig_time_remaining; // -1 = not digging s16 m_dig_tool_item; - v3s16 m_dig_position; + v3s16 m_dig_position;*/ private: /* @@ -416,6 +416,9 @@ private: void SendObjectData(float dtime); void SendPlayerInfos(); void SendInventory(u16 peer_id); + void SendChatMessage(u16 peer_id, const std::wstring &message); + void BroadcastChatMessage(const std::wstring &message); + // Sends blocks to clients void SendBlocks(float dtime);