changes to handing of digging (non backwards-compatible i guess)
authorPerttu Ahola <celeron55@gmail.com>
Thu, 23 Dec 2010 20:35:53 +0000 (22:35 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Thu, 23 Dec 2010 20:35:53 +0000 (22:35 +0200)
14 files changed:
Makefile
data/crack.png
minetest.vcproj
src/client.cpp
src/client.h
src/clientserver.h
src/constants.h
src/defaultsettings.cpp
src/guiPauseMenu.cpp
src/guiTextInputMenu.cpp
src/irrlichtwrapper.cpp
src/main.cpp
src/server.cpp
src/server.h

index 39ab170598f958fb2be13bfe063f1bdafecf7c73..5dad9433f6c2ebdc0909e620024cdbc18f9ac747 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,12 @@
 # Makefile for Irrlicht Examples\r
 # It's usually sufficient to change just the target name and source file list\r
 # and be sure that CXX is set to a valid compiler\r
-TARGET = test\r
 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\r
-SOURCES = $(addprefix src/, $(SOURCE_FILES))\r
-BUILD_DIR = build\r
-OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))\r
+\r
+DEBUG_TARGET = debugtest\r
+DEBUG_SOURCES = $(addprefix src/, $(SOURCE_FILES))\r
+DEBUG_BUILD_DIR = debugbuild\r
+DEBUG_OBJECTS = $(addprefix $(DEBUG_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))\r
 \r
 FAST_TARGET = fasttest\r
 FAST_SOURCES = $(addprefix src/, $(SOURCE_FILES))\r
@@ -24,48 +25,49 @@ JTHREADPATH = ../jthread/jthread-1.2.1
 #CXXFLAGS = -O2 -ffast-math -Wall -fomit-frame-pointer -pipe\r
 #CXXFLAGS = -O2 -ffast-math -Wall -g -pipe\r
 #CXXFLAGS = -O1 -ffast-math -Wall -g\r
-CXXFLAGS = -Wall -g -O0\r
+CXXFLAGS = -Wall -g -O1\r
 \r
-all: fast_linux\r
+all: fast\r
 \r
 ifeq ($(HOSTTYPE), x86_64)\r
 LIBSELECT=64\r
 endif\r
 \r
-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\r
-all_linux fast_linux: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src\r
-fast_linux server_linux: CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686\r
-server_linux: LDFLAGS = -L$(JTHREADPATH)/src/.libs -ljthread -lz -lpthread\r
-server_linux: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DSERVER\r
-all_linux fast_linux clean_linux: SYSTEM=Linux\r
+debug fast: LDFLAGS = -L/usr/X11R6/lib$(LIBSELECT) -L$(IRRLICHTPATH)/lib/Linux -L$(JTHREADPATH)/src/.libs -lIrrlicht -lGL -lXxf86vm -lXext -lX11 -ljthread -lz\r
+debug: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DDEBUG\r
+fast: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DUNITTEST_DISABLE\r
+fast server: CXXFLAGS = -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops -mtune=i686\r
+server: LDFLAGS = -L$(JTHREADPATH)/src/.libs -ljthread -lz -lpthread\r
+server: CPPFLAGS = -I$(IRRLICHTPATH)/include -I/usr/X11R6/include -I$(JTHREADPATH)/src -DSERVER -DUNITTEST_DISABLE\r
+debug fast clean_debug: SYSTEM=Linux\r
 \r
-DESTPATH = bin/$(TARGET)\r
+DEBUG_DESTPATH = bin/$(DEBUG_TARGET)\r
 FAST_DESTPATH = bin/$(FAST_TARGET)\r
 SERVER_DESTPATH = bin/$(SERVER_TARGET)\r
 \r
 # Build commands\r
 \r
-all_linux: $(BUILD_DIR) $(DESTPATH)\r
-fast_linux: $(FAST_BUILD_DIR) $(FAST_DESTPATH)\r
-server_linux: $(SERVER_BUILD_DIR) $(SERVER_DESTPATH)\r
+debug: $(DEBUG_BUILD_DIR) $(DEBUG_DESTPATH)\r
+fast: $(FAST_BUILD_DIR) $(FAST_DESTPATH)\r
+server: $(SERVER_BUILD_DIR) $(SERVER_DESTPATH)\r
 \r
-$(BUILD_DIR):\r
-       mkdir -p $(BUILD_DIR)\r
+$(DEBUG_BUILD_DIR):\r
+       mkdir -p $(DEBUG_BUILD_DIR)\r
 $(FAST_BUILD_DIR):\r
        mkdir -p $(FAST_BUILD_DIR)\r
 $(SERVER_BUILD_DIR):\r
        mkdir -p $(SERVER_BUILD_DIR)\r
 \r
-$(DESTPATH): $(OBJECTS)\r
-       $(CXX) -o $@ $(OBJECTS) $(LDFLAGS)\r
+$(DEBUG_DESTPATH): $(DEBUG_OBJECTS)\r
+       $(CXX) -o $@ $(DEBUG_OBJECTS) $(LDFLAGS)\r
 \r
 $(FAST_DESTPATH): $(FAST_OBJECTS)\r
-       $(CXX) -o $@ $(FAST_OBJECTS) $(LDFLAGS) -DUNITTEST_DISABLE\r
+       $(CXX) -o $@ $(FAST_OBJECTS) $(LDFLAGS)\r
 \r
 $(SERVER_DESTPATH): $(SERVER_OBJECTS)\r
-       $(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS) -DSERVER -DUNITTEST_DISABLE\r
+       $(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS)\r
 \r
-$(BUILD_DIR)/%.o: src/%.cpp\r
+$(DEBUG_BUILD_DIR)/%.o: src/%.cpp\r
        $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS)\r
 \r
 $(FAST_BUILD_DIR)/%.o: src/%.cpp\r
@@ -74,15 +76,15 @@ $(FAST_BUILD_DIR)/%.o: src/%.cpp
 $(SERVER_BUILD_DIR)/%.o: src/%.cpp\r
        $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS)\r
 \r
-clean: clean_linux clean_fast_linux clean_server_linux\r
+clean: clean_debug clean_fast clean_server\r
 \r
-clean_linux:\r
-       @$(RM) $(OBJECTS) $(DESTPATH)\r
+clean_debug:\r
+       @$(RM) $(DEBUG_OBJECTS) $(DEBUG_DESTPATH)\r
 \r
-clean_fast_linux:\r
+clean_fast:\r
        @$(RM) $(FAST_OBJECTS) $(FAST_DESTPATH)\r
 \r
-clean_server_linux:\r
+clean_server:\r
        @$(RM) $(SERVER_OBJECTS) $(SERVER_DESTPATH)\r
 \r
-.PHONY: all all_win32 clean clean_linux clean_win32 clean_fast_linux clean_server_linux\r
+.PHONY: all all_win32 clean clean_debug clean_win32 clean_fast clean_server\r
index e39b74da01343f285f9874e1ed00e3dd0a4314ea..0fef2a6fddd13c5d5c851ce38943703ff51e89bd 100644 (file)
Binary files a/data/crack.png and b/data/crack.png differ
index f27c4bcdcbf3a6a6744123619e667d17adf3e05d..f7a125d0d9e929940afe0fc5eaecf244e60709c2 100644 (file)
                                RelativePath=".\src\guiPauseMenu.cpp"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\src\guiTextInputMenu.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\src\heightmap.cpp"\r
                                >\r
index 23f9d2a555948ed5cfd3fe0ae1e0a42071858d4d..ff40f674f4aa81f16f5562474e88c6e5914b91a5 100644 (file)
@@ -447,8 +447,6 @@ void Client::ReceiveAll()
                                        "InvalidIncomingDataException: what()="
                                        <<e.what()<<std::endl;
                }
-               //TODO: Testing
-               //break;
        }
 }
 
@@ -985,6 +983,33 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                m_time_of_day.set(time);
                //dstream<<"Client: time="<<time<<std::endl;
        }
+       else if(command == TOCLIENT_CHAT_MESSAGE)
+       {
+               /*
+                       u16 command
+                       u16 length
+                       wstring message
+               */
+               u8 buf[6];
+               std::string datastring((char*)&data[2], datasize-2);
+               std::istringstream is(datastring, std::ios_base::binary);
+               
+               // Read stuff
+               is.read((char*)buf, 2);
+               u16 len = readU16(buf);
+               
+               std::wstring message;
+               for(u16 i=0; i<len; i++)
+               {
+                       is.read((char*)buf, 2);
+                       message += (wchar_t)readU16(buf);
+               }
+
+               /*dstream<<"Client received chat message: "
+                               <<wide_to_narrow(message)<<std::endl;*/
+               
+               m_chat_queue.push_back(message);
+       }
        // Default to queueing it (for slow commands)
        else
        {
@@ -1042,26 +1067,7 @@ bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater)
                // This will clear the cracking animation after digging
                ((ClientMap&)m_env.getMap()).clearTempMod(p);
 
-               core::map<v3s16, MapBlock*> 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<v3s16, MapBlock * >::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<v3s16, MapBlock*> modified_blocks;
-
-               try
-               {
-                       JMutexAutoLock envlock(m_env_mutex);
-                       m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
-               }
-               catch(InvalidPositionException &e)
-               {}
-               
-               for(core::map<v3s16, MapBlock * >::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"<<std::endl;
-                       core::map<v3s16, MapBlock*> blocks_changed;
-                       blocks_changed.insert(block->getPos(), block);
-                       core::map<v3s16, MapBlock*> 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<u8> 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<<DTIME<<"Client::removeNode() cancelled (not connected)"
-                               <<std::endl;
-               return;
-       }
-       
-       // Test that the position exists
-       try{
-               JMutexAutoLock envlock(m_env_mutex);
-               m_env.getMap().getNode(nodepos);
-       }
-       catch(InvalidPositionException &e)
-       {
-               dout_client<<DTIME<<"Client::removeNode() cancelled (doesn't exist)"
-                               <<std::endl;
-               return;
-       }
-
-       SharedBuffer<u8> 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<<DTIME<<"Client::addNodeFromInventory() "
-                               "cancelled (not connected)"
-                               <<std::endl;
-               return;
-       }
-       
-       // Test that the position exists
-       try{
-               JMutexAutoLock envlock(m_env_mutex);
-               m_env.getMap().getNode(nodepos);
-       }
-       catch(InvalidPositionException &e)
-       {
-               dout_client<<DTIME<<"Client::addNode() cancelled (doesn't exist)"
-                               <<std::endl;
-               return;
-       }
-
-       //u8 ser_version = m_server_ser_ver;
-
-       // SUGGESTION: The validity of the operation could be checked here too
-
-       u8 datasize = 2 + 6 + 2;
-       SharedBuffer<u8> 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<message.size(); i++)
+       {
+               u16 w = message[i];
+               writeU16(buf, w);
+               os.write((char*)buf, 2);
+       }
+       
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> 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<v3s16, MapBlock*> modified_blocks;
 
+       try
+       {
+               //TimeTaker t("removeNodeAndUpdate", m_device);
+               m_env.getMap().removeNodeAndUpdate(p, modified_blocks);
+       }
+       catch(InvalidPositionException &e)
+       {
+       }
+       
+       for(core::map<v3s16, MapBlock * >::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<v3s16, MapBlock*> modified_blocks;
+
+       try
+       {
+               m_env.getMap().addNodeAndUpdate(p, n, modified_blocks);
+       }
+       catch(InvalidPositionException &e)
+       {}
+       
+       for(core::map<v3s16, MapBlock * >::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);
index 3c8bbfaf6206e5872d6a6dc8f10c9cc0bd77494c..6fb608b84f522e45a6669d5c0adb5abb5ebb6636 100644 (file)
@@ -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<Player*> 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<std::wstring> m_chat_queue;
 };
 
 #endif // !SERVER
index c8a114841d940b320af6d801a00df6fee3b44d53..07b1cf60f317daa3fc0e90174b08afec6c920995 100644 (file)
@@ -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<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time)
index cf394ca02101a2e44f7ba2721bd913aae86f3cc1..b6b09b50bb6c3c98b42e13848d8831116d58841f 100644 (file)
@@ -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
 
index b288d028c5068d9748f203aaaa09a28e18a60159..66564bc1f177c8976d12796e008e950c9d86d4f6 100644 (file)
@@ -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");
 }
 
index 2a0b3cb0c653c8cf9aac8e8dce9cc3b18da5dadd..ae1f58a9d40cdb410bee922385e5ef67f70f2620 100644 (file)
@@ -106,6 +106,7 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
                L"- R: Toggle viewing all loaded chunks\n"\r
                L"- I: Inventory menu\n"\r
                L"- ESC: This menu\n"\r
+               L"- T: Chat\n"\r
                L"\n"\r
                L"To generate a new map, remove the map directory.\n";\r
                Environment->addStaticText(text, rect, false, true, this, 258);\r
index 0668aa7b33ac1916d993adf2eafff76f9e9aae6d..787680bc51f00c00b5d4dd38f60a642f63aad614 100644 (file)
@@ -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;
index 51511eb34fcc6f7eb8fefee6e2352e263560b42f..c012b136e80df098746ff8c1b6c95d50a31fb131 100644 (file)
@@ -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 "<<spec.name<<std::endl;
-
-               // Wait result
-               GetResult<TextureSpec, video::ITexture*, u8, u8>
-                               result = result_queue.pop_front(1000);
+               dstream<<"Waiting for texture from main thread: "
+                               <<spec.name<<std::endl;
                
-               // Check that at least something worked OK
-               assert(result.key.name == spec.name);
-
-               t = result.item;
+               try
+               {
+                       // Wait result for a second
+                       GetResult<TextureSpec, video::ITexture*, u8, u8>
+                                       result = result_queue.pop_front(1000);
+               
+                       // Check that at least something worked OK
+                       assert(result.key.name == spec.name);
+
+                       t = result.item;
+               }
+               catch(ItemNotFoundException &e)
+               {
+                       dstream<<"Waiting for texture timed out."<<std::endl;
+                       t = NULL;
+               }
        }
 
        // Add to cache and return
index da727811e96bc69998164c600069de6f6ebf02cc..cfc47bbb279a79120e6c09362a4535378c31b878 100644 (file)
@@ -167,6 +167,9 @@ TODO: Better handling of objects and mobs
 TODO: Draw big amounts of torches better (that is, throw them in the\r
       same meshbuffer (can the meshcollector class be used?))\r
 \r
+TODO: Check if the usage of Client::isFetchingBlocks() in\r
+      updateViewingRange() actually does something\r
+\r
 Doing now:\r
 ======================================================================\r
 \r
@@ -270,6 +273,7 @@ extern void set_default_settings();
 u16 g_selected_item = 0;\r
 \r
 IrrlichtDevice *g_device = NULL;\r
+Client *g_client = NULL;\r
 \r
 /*\r
        GUI Stuff\r
@@ -323,6 +327,46 @@ u32 getTimeMs()
        return g_irrlicht->getTime();\r
 }\r
 \r
+/*\r
+       Text input system\r
+*/\r
+\r
+struct TextDestSign : public TextDest\r
+{\r
+       TextDestSign(v3s16 blockpos, s16 id, Client *client)\r
+       {\r
+               m_blockpos = blockpos;\r
+               m_id = id;\r
+               m_client = client;\r
+       }\r
+       void gotText(std::wstring text)\r
+       {\r
+               std::string ntext = wide_to_narrow(text);\r
+               dstream<<"Changing text of a sign object: "\r
+                               <<ntext<<std::endl;\r
+               m_client->sendSignText(m_blockpos, m_id, ntext);\r
+       }\r
+\r
+       v3s16 m_blockpos;\r
+       s16 m_id;\r
+       Client *m_client;\r
+};\r
+\r
+struct TextDestChat : public TextDest\r
+{\r
+       TextDestChat(Client *client)\r
+       {\r
+               m_client = client;\r
+       }\r
+       void gotText(std::wstring text)\r
+       {\r
+               m_client->sendChatMessage(text);\r
+               m_client->addChatMessage(text);\r
+       }\r
+\r
+       Client *m_client;\r
+};\r
+\r
 class MyEventReceiver : public IEventReceiver\r
 {\r
 public:\r
@@ -371,6 +415,14 @@ public:
                                                                &g_active_menu_count))->drop();\r
                                                return true;\r
                                        }\r
+                                       if(event.KeyInput.Key == irr::KEY_KEY_T)\r
+                                       {\r
+                                               TextDest *dest = new TextDestChat(g_client);\r
+\r
+                                               (new GUITextInputMenu(guienv, guiroot, -1,\r
+                                                               &g_active_menu_count, dest,\r
+                                                               L""))->drop();\r
+                                       }\r
                                }\r
 \r
                                // Material selection\r
@@ -965,31 +1017,6 @@ private:
        s32 m_selection;\r
 };\r
 \r
-/*\r
-       Text input system\r
-*/\r
-\r
-struct TextDestSign : public TextDest\r
-{\r
-       TextDestSign(v3s16 blockpos, s16 id, Client *client)\r
-       {\r
-               m_blockpos = blockpos;\r
-               m_id = id;\r
-               m_client = client;\r
-       }\r
-       void gotText(std::wstring text)\r
-       {\r
-               std::string ntext = wide_to_narrow(text);\r
-               dstream<<"Changing text of a sign object: "\r
-                               <<ntext<<std::endl;\r
-               m_client->sendSignText(m_blockpos, m_id, ntext);\r
-       }\r
-\r
-       v3s16 m_blockpos;\r
-       s16 m_id;\r
-       Client *m_client;\r
-};\r
-\r
 int main(int argc, char *argv[])\r
 {\r
        /*\r
@@ -1334,6 +1361,10 @@ int main(int argc, char *argv[])
        gui::IGUIFont* font = guienv->getFont("../data/fontlucida.png");\r
        if(font)\r
                skin->setFont(font);\r
+       \r
+       u32 text_height = font->getDimension(L"Hello, world!").Height;\r
+       dstream<<"text_height="<<text_height<<std::endl;\r
+\r
        //skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0));\r
        skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255));\r
        //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0));\r
@@ -1343,11 +1374,7 @@ int main(int argc, char *argv[])
        \r
        const wchar_t *text = L"Loading and connecting...";\r
        core::vector2d<s32> center(screenW/2, screenH/2);\r
-       core::dimension2d<u32> textd = font->getDimension(text);\r
-       std::cout<<DTIME<<"Text w="<<textd.Width<<" h="<<textd.Height<<std::endl;\r
-       // Have to add a bit to disable the text from word wrapping\r
-       //core::vector2d<s32> textsize(textd.Width+4, textd.Height);\r
-       core::vector2d<s32> textsize(300, textd.Height);\r
+       core::vector2d<s32> textsize(300, text_height);\r
        core::rect<s32> textrect(center - textsize/2, center + textsize/2);\r
 \r
        gui::IGUIStaticText *gui_loadingtext = guienv->addStaticText(\r
@@ -1389,6 +1416,8 @@ int main(int argc, char *argv[])
                        g_range_mutex,\r
                        g_viewing_range_nodes,\r
                        g_viewing_range_all);\r
+                       \r
+       g_client = &client;\r
        \r
        Address connect_address(0,0,0,0, port);\r
        try{\r
@@ -1498,6 +1527,14 @@ int main(int argc, char *argv[])
                        core::rect<s32>(100, 70, 100+400, 70+(textsize.Y+5)),\r
                        false, false);\r
        \r
+       // Chat text\r
+       gui::IGUIStaticText *chat_guitext = guienv->addStaticText(\r
+                       L"Chat here\nOther line\nOther line\nOther line\nOther line",\r
+                       core::rect<s32>(70, 60, 795, 150),\r
+                       false, true);\r
+       core::list<std::wstring> chat_lines;\r
+       //chat_lines.push_back(L"Minetest-c55 up and running!");\r
+       \r
        /*\r
                Some statistics are collected in these\r
        */\r
@@ -2033,7 +2070,7 @@ int main(int argc, char *argv[])
                        if(g_input->getLeftClicked() ||\r
                                        (g_input->getLeftState() && nodepos != nodepos_old))\r
                        {\r
-                               std::cout<<DTIME<<"Ground left-clicked"<<std::endl;\r
+                               dstream<<DTIME<<"Started digging"<<std::endl;\r
                                client.groundAction(0, nodepos, neighbourpos, g_selected_item);\r
                        }\r
                        if(g_input->getLeftClicked())\r
@@ -2042,23 +2079,28 @@ int main(int argc, char *argv[])
                        }\r
                        if(g_input->getLeftState())\r
                        {\r
-                               float dig_time_complete = 0.5;\r
                                MapNode n = client.getNode(nodepos);\r
+\r
+                               // TODO: Get this from some table that is sent by server\r
+                               float dig_time_complete = 0.5;\r
                                if(n.d == CONTENT_STONE)\r
                                        dig_time_complete = 1.5;\r
                                \r
-                               float dig_time_complete0 = dig_time_complete+client.getAvgRtt()*2;\r
-                               if(dig_time_complete0 < 0.0)\r
-                                       dig_time_complete0 = 0.0;\r
-\r
                                dig_index = (u16)((float)CRACK_ANIMATION_LENGTH\r
-                                               * dig_time/dig_time_complete0);\r
+                                               * dig_time/dig_time_complete);\r
 \r
-                               if(dig_time > 0.125 && dig_index < CRACK_ANIMATION_LENGTH)\r
+                               if(dig_index < CRACK_ANIMATION_LENGTH)\r
                                {\r
                                        //dstream<<"dig_index="<<dig_index<<std::endl;\r
                                        client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));\r
                                }\r
+                               else\r
+                               {\r
+                                       dstream<<DTIME<<"Digging completed"<<std::endl;\r
+                                       client.groundAction(3, nodepos, neighbourpos, g_selected_item);\r
+                                       client.clearTempMod(nodepos);\r
+                                       client.removeNode(nodepos);\r
+                               }\r
 \r
                                dig_time += dtime;\r
                        }\r
@@ -2081,7 +2123,8 @@ int main(int argc, char *argv[])
                \r
                if(g_input->getLeftReleased())\r
                {\r
-                       std::cout<<DTIME<<"Left released"<<std::endl;\r
+                       std::cout<<DTIME<<"Left button released (stopped digging)"\r
+                                       <<std::endl;\r
                        client.groundAction(2, v3s16(0,0,0), v3s16(0,0,0), 0);\r
                }\r
                if(g_input->getRightReleased())\r
@@ -2180,16 +2223,44 @@ int main(int argc, char *argv[])
                }\r
                \r
                {\r
-                       /*wchar_t temptext[100];\r
-                       swprintf(temptext, 100,\r
-                                       SWPRINTF_CHARSTRING,\r
-                                       infotext.substr(0,99).c_str()\r
-                                       );\r
-\r
-                       guitext_info->setText(temptext);*/\r
-\r
                        guitext_info->setText(infotext.c_str());\r
                }\r
+               \r
+               /*\r
+                       Get chat messages from client\r
+               */\r
+               {\r
+                       // Get messages\r
+                       std::wstring message;\r
+                       while(client.getChatMessage(message))\r
+                       {\r
+                               chat_lines.push_back(message);\r
+                               if(chat_lines.size() > 5)\r
+                               {\r
+                                       core::list<std::wstring>::Iterator\r
+                                                       i = chat_lines.begin();\r
+                                       chat_lines.erase(i);\r
+                               }\r
+                       }\r
+                       // Append them to form the whole static text and throw\r
+                       // it to the gui element\r
+                       std::wstring whole;\r
+                       for(core::list<std::wstring>::Iterator\r
+                                       i = chat_lines.begin();\r
+                                       i != chat_lines.end(); i++)\r
+                       {\r
+                               whole += (*i) + L'\n';\r
+                       }\r
+                       chat_guitext->setText(whole.c_str());\r
+                       // Update gui element size and position\r
+                       core::rect<s32> rect(\r
+                                       10,\r
+                                       screensize.Y - 10 - text_height*chat_lines.size(),\r
+                                       screensize.X - 10,\r
+                                       screensize.Y - 10\r
+                       );\r
+                       chat_guitext->setRelativePosition(rect);\r
+               }\r
 \r
                /*\r
                        Inventory\r
index 8b063b60d8aaa514b9a6889dbfc0f37ab6bfaef8..d7bd226683e05df86c1f46ab7a2d524d21397f5e 100644 (file)
@@ -355,8 +355,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
        {
                SharedPtr<JMutexAutoLock> 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<v3s16, MapBlock*> 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"
+                                                       <<std::endl;
+                                       return;
+                               }
+                       }
+                       catch(InvalidPositionException &e)
+                       {
+                               derr_server<<"Server: Not finishing digging: Node not found"
+                                               <<std::endl;
+                               return;
+                       }
+                       
+                       //TODO: Send to only other clients
+                       
+                       /*
+                               Send the removal to all other clients
+                       */
+
+                       // Create packet
+                       u32 replysize = 8;
+                       SharedBuffer<u8> 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<u16, RemoteClient*>::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)"<<std::endl;
+                       }
+                       
+                       v.blitBack(modified_blocks);
+               }
+               
                /*
                        1: place block
                */
@@ -1948,6 +2079,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        }
 
                } // action == 1
+
                /*
                        Catch invalid actions
                */
@@ -2100,6 +2232,57 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                        <<std::endl;
                }
        }
+       else if(command == TOSERVER_CHAT_MESSAGE)
+       {
+               /*
+                       u16 command
+                       u16 length
+                       wstring message
+               */
+               u8 buf[6];
+               std::string datastring((char*)&data[2], datasize-2);
+               std::istringstream is(datastring, std::ios_base::binary);
+               
+               // Read stuff
+               is.read((char*)buf, 2);
+               u16 len = readU16(buf);
+               
+               std::wstring message;
+               for(u16 i=0; i<len; i++)
+               {
+                       is.read((char*)buf, 2);
+                       message += (wchar_t)readU16(buf);
+               }
+
+               dstream<<"CHAT: "<<wide_to_narrow(message)<<std::endl;
+
+               /*
+                       Send the message to all other clients
+               */
+               for(core::map<u16, RemoteClient*>::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<message.size(); i++)
+       {
+               u16 w = message[i];
+               writeU16(buf, w);
+               os.write((char*)buf, 2);
+       }
+       
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> 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<u16, RemoteClient*>::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);
index d002d9f4c9cf1afb390cc5828dd2eac0023002f4..f1baaf24042dfe156a5d78811c94f7c6433ae420 100644 (file)
@@ -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<float> 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);