├── src ├── .gitignore ├── admin.txt ├── rules.txt ├── motd.txt ├── mersenne.h ├── sockets.h ├── config.cfg ├── logger.h ├── Makefile ├── logger.cpp ├── config.h ├── mineserver.h ├── mapgen.h ├── physics.h ├── chat.h ├── mersenne.cpp ├── tools.h ├── item_alias.cfg ├── nbt.h ├── constants.cpp ├── tools.cpp ├── user.h ├── vec.h ├── config.cpp ├── sockets.cpp ├── map.h ├── constants.h ├── chat.cpp ├── mineserver.cpp ├── physics.cpp ├── packets.h ├── commands.cpp ├── nbt.cpp └── mapgen.cpp ├── bin ├── admin.txt ├── rules.txt ├── motd.txt └── config.cfg ├── .gitignore ├── mineserver ├── mineserver.sln ├── vs2008 │ ├── mineserver.sln │ └── mineserver.vcproj └── mineserver.vcxproj ├── LICENSE.noiseutils ├── LICENSE ├── CMakeLists.txt └── README.md /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | mineserver 3 | -------------------------------------------------------------------------------- /bin/admin.txt: -------------------------------------------------------------------------------- 1 | # Add admin names below 2 | 3 | -------------------------------------------------------------------------------- /src/admin.txt: -------------------------------------------------------------------------------- 1 | # Commentline 2 | Psoden 3 | fador -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS junk 2 | .DS_Store 3 | Thumbs.db 4 | 5 | # Default test map 6 | src/testmap 7 | 8 | -------------------------------------------------------------------------------- /bin/rules.txt: -------------------------------------------------------------------------------- 1 | # Server rules here 2 | §4Server rules 3 | 1. Do not whine 4 | 2. Whine 5 | 3. Whining is required 6 | 4. ^__________^ -------------------------------------------------------------------------------- /src/rules.txt: -------------------------------------------------------------------------------- 1 | # Server rules here 2 | §4Server rules 3 | 1. Do not whine 4 | 2. Whine 5 | 3. Whining is required 6 | 4. ^__________^ -------------------------------------------------------------------------------- /bin/motd.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Write message of the day here. 3 | # Lines beginning with # are commentlines and will not be sent to player 4 | # 5 | > §aWelcome to Mineserver! 6 | > §bThis is MOTD 7 | > §fThis is third line of MOTD :E -------------------------------------------------------------------------------- /src/motd.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Write message of the day here. 3 | # Lines beginning with # are commentlines and will not be sent to player 4 | # 5 | > §aWelcome to Mineserver! 6 | > §bThis is MOTD 7 | > §fThis is third line of MOTD :E -------------------------------------------------------------------------------- /mineserver/mineserver.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mineserver", "mineserver.vcxproj", "{7F6D1DAB-AA49-4343-B28E-C3E647BE5007}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Debug|Win32.Build.0 = Debug|Win32 14 | {7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Release|Win32.ActiveCfg = Release|Win32 15 | {7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /mineserver/vs2008/mineserver.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mineserver", "mineserver.vcproj", "{62837E01-24FA-4205-9533-950FBB5DBDD2}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {62837E01-24FA-4205-9533-950FBB5DBDD2}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {62837E01-24FA-4205-9533-950FBB5DBDD2}.Debug|Win32.Build.0 = Debug|Win32 14 | {62837E01-24FA-4205-9533-950FBB5DBDD2}.Release|Win32.ActiveCfg = Release|Win32 15 | {62837E01-24FA-4205-9533-950FBB5DBDD2}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /LICENSE.noiseutils: -------------------------------------------------------------------------------- 1 | noiseutils.cpp/noiseutils.h 2 | 3 | Copyright (C) 2003-2005 Jason Bevins 4 | 5 | This library is free software; you can redistribute it and/or modify it 6 | under the terms of the GNU Lesser General Public License as published by 7 | the Free Software Foundation; either version 2.1 of the License, or (at 8 | your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, but WITHOUT 11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 13 | License (COPYING.txt) for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public License 16 | along with this library; if not, write to the Free Software Foundation, 17 | Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | The developer's email is jlbezigvins@gmzigail.com (for great email, take 20 | off every 'zig'.) 21 | -------------------------------------------------------------------------------- /src/mersenne.h: -------------------------------------------------------------------------------- 1 | /* 2 | Random number generator class 3 | ============================= 4 | Created - Sarah "Voodoo Doll" White (2006/01/24) 5 | */ 6 | 7 | #ifndef _MERSENNE_H 8 | #define _MERSENNE_H 9 | 10 | class Random { 11 | // Arbitrary constants that work well 12 | static const int N = 624; 13 | static const int M = 397; 14 | static const unsigned long MATRIX_A = 0x9908b0dfUL; 15 | static const unsigned long UPPER_MASK = 0x80000000UL; 16 | static const unsigned long LOWER_MASK = 0x7fffffffUL; 17 | static const unsigned long MAX = 0xffffffffUL; 18 | 19 | unsigned long x[N]; // Random number pool 20 | int next; // Current pool index 21 | public: 22 | Random(unsigned long seed = 1) : next(0) { seedgen(seed); } 23 | 24 | // Return a uniform deviate in the range [0,1) 25 | double uniform(); 26 | // Return a uniform deviate in the range [0,hi) 27 | unsigned uniform(unsigned hi); 28 | // Return a uniform deviate in the range [lo,hi) 29 | unsigned uniform(unsigned lo, unsigned hi); 30 | private: 31 | void seedgen(unsigned long seed); 32 | unsigned long randgen(); 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /bin/config.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Mineserver configuration 3 | # 4 | 5 | # Server name 6 | servername = "Mineserver alpha testserver" 7 | 8 | # Userlimit 9 | userlimit = 50 10 | 11 | # IP 12 | ip = "0.0.0.0" 13 | 14 | # Port 15 | port = 25565 16 | 17 | # Admin file 18 | admin_file = "admin.txt" 19 | 20 | # Item alias file 21 | items_file = "items.txt" 22 | 23 | # MOTD file 24 | motd_file = "motd.txt" 25 | 26 | # Rules file 27 | rules_file = "rules.txt" 28 | 29 | # Map Release time - time in seconds to keep unused map chunks in memory 30 | # Memory vs. CPU tradeoff. Reloading map data takes a bit of CPU each time 31 | # but the map in memory consumes it around 100kb/chunk 32 | map_release_time = 10 33 | 34 | # Map directory 35 | mapdir = "testmap" 36 | 37 | # Message for wrong client version 38 | wrong_protocol_message = "Wrong protocol version" 39 | 40 | # Server full message 41 | server_full_message = "Server is currently full" 42 | 43 | # Default kick message 44 | default_kick_message = "This is a default kick message" 45 | 46 | # ==== Item kits ==== 47 | # Define your own kits with kit_ = ", , ..., " 48 | # Kits can be spawned ingame with /kit 49 | 50 | # Starterkit (/kit starter) Stone spade, pickaxe, axe, five torches 51 | kit_starter = "273, 274, 275, 50, 50, 50, 50, 50" 52 | 53 | # Is liquid physics turned on (1 = on, 0 = off) 54 | liquid_physics = 1 55 | 56 | # Generate flatland map 57 | map_flatland = false; 58 | 59 | # Ore Density 60 | oreDensity = 24 61 | 62 | # Sea level 63 | seaLevel = 63 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, The Mineserver Project 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the The Mineserver Project nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /src/sockets.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | void accept_callback(int fd, short ev, void *arg); 29 | -------------------------------------------------------------------------------- /src/config.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Mineserver configuration 3 | # 4 | 5 | # Server name 6 | servername = "Mineserver alpha testserver" 7 | 8 | # Userlimit 9 | userlimit = 50 10 | 11 | # IP 12 | ip = "0.0.0.0" 13 | 14 | # Port 15 | port = 25565 16 | 17 | # Admin file 18 | admin_file = "admin.txt" 19 | 20 | # Item alias file 21 | items_file = "items.txt" 22 | 23 | # MOTD file 24 | motd_file = "motd.txt" 25 | 26 | # Rules file 27 | rules_file = "rules.txt" 28 | 29 | # Map Release time - time in seconds to keep unused map chunks in memory 30 | # Memory vs. CPU tradeoff. Reloading map data takes a bit of CPU each time 31 | # but the map in memory consumes it around 100kb/chunk 32 | map_release_time = 10 33 | 34 | # Do you want to use a whitelist? Yay or Nay. 35 | use_whitelist = false 36 | 37 | # Map directory 38 | mapdir = "testmap" 39 | 40 | # Message for wrong client version 41 | wrong_protocol_message = "Wrong protocol version" 42 | 43 | # Server full message 44 | server_full_message = "Server is currently full" 45 | 46 | # Default kick message 47 | default_kick_message = "This is a default kick message" 48 | 49 | # Default ban message 50 | default_banned_message = "You have been banned from this server" 51 | 52 | # Default whitelist message 53 | default_whitelist_message = "You are not on the whitelist" 54 | 55 | # ==== Item kits ==== 56 | # Define your own kits with kit_ = ", , ..., " 57 | # Kits can be spawned ingame with /kit 58 | 59 | # Starterkit (/kit starter) Stone spade, pickaxe, axe, five torches 60 | kit_starter = "273, 274, 275, 50, 50, 50, 50, 50" 61 | 62 | # Is liquid physics turned on (1 = on, 0 = off) 63 | liquid_physics = 1 64 | 65 | # Generate flatland map 66 | map_flatland = false; 67 | 68 | # Ore Density 69 | oreDensity = 24 70 | 71 | # Sea level 72 | seaLevel = 63 73 | -------------------------------------------------------------------------------- /src/logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | // 29 | // Mineserver logger.h 30 | // 31 | #include 32 | 33 | #define LOG(msg) Logger::get().log(msg, std::string(__FILE__), __LINE__) 34 | 35 | class Logger 36 | { 37 | private: 38 | Logger() 39 | { 40 | } 41 | public: 42 | void log(std::string msg, std::string file, int line); 43 | static Logger &get(); 44 | }; 45 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/sh 2 | SYSTEM = $(shell uname) 3 | 4 | DFLAGS = 5 | 6 | ifeq ($(SYSTEM),Darwin) 7 | DFLAGS += -D__APPLE__ 8 | endif 9 | 10 | ifeq ($(SYSTEM),FreeBSD) 11 | DFLAGS += -D__FREEBSD__ 12 | endif 13 | 14 | ifeq ($(SYSTEM),SunOS) 15 | DFLAGS += -D__SOLARIS__ 16 | endif 17 | 18 | ifeq ($(SYSTEM),mingw) 19 | LFLAGS = -lws2_32 20 | endif 21 | 22 | 23 | RM = rm -f 24 | CXX = g++ 25 | CC = $(CXX) 26 | LDFLAGS += -L/usr/local/lib -L/usr/lib -levent -lz -lnoise $(LFLAGS) 27 | CXXFLAGS += $(DFLAGS) -I. -I/usr/Local/include -I/usr/include 28 | 29 | OBJS = map.o chat.o commands.o config.o constants.o logger.o mapgen.o nbt.o packets.o physics.o sockets.o tools.o user.o noiseutils.o mersenne.o mineserver.o 30 | PROG = ./mineserver 31 | PROGS = $(PROG) 32 | 33 | $(PROGS): $(OBJS) 34 | 35 | clean: 36 | $(RM) $(OBJS) $(PROGS) 37 | 38 | all: $(PROGS) 39 | 40 | chat.o: chat.cpp logger.h constants.h tools.h map.h user.h chat.h config.h physics.h 41 | commands.o: commands.cpp logger.h constants.h tools.h map.h user.h chat.h config.h physics.h 42 | config.o: config.cpp logger.h constants.h config.h 43 | constants.o: constants.cpp constants.h 44 | logger.o: logger.cpp logger.h 45 | map.o: map.cpp logger.h tools.h map.h user.h nbt.h config.h 46 | mapgen.o: mapgen.cpp logger.h constants.h config.h mapgen.h mersenne.h noiseutils.h 47 | nbt.o: nbt.cpp tools.h nbt.h map.h 48 | packets.o: packets.cpp constants.h logger.h sockets.h tools.h map.h user.h chat.h config.h nbt.h packets.h physics.h 49 | physics.o: physics.cpp logger.h constants.h config.h user.h map.h vec.h physics.h 50 | sockets.o: sockets.cpp logger.h constants.h tools.h user.h map.h chat.h nbt.h packets.h 51 | tools.o: tools.cpp tools.h 52 | user.o: user.cpp constants.h logger.h tools.h map.h user.h nbt.h chat.h packets.h 53 | mineserver.o: mineserver.cpp constants.h logger.h sockets.h tools.h map.h user.h chat.h mapgen.h config.h nbt.h packets.h physics.h 54 | noiseutils.o: noiseutils.h noiseutils.cpp 55 | mersenne.o: mersenne.cpp mersenne.h 56 | -------------------------------------------------------------------------------- /src/logger.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | // 29 | // Mineserver logger.cpp 30 | // 31 | 32 | #include 33 | //#include 34 | #include 35 | #include 36 | #include "logger.h" 37 | 38 | Logger &Logger::get() 39 | { 40 | static Logger instance; 41 | return instance; 42 | } 43 | 44 | // Log to terminal 45 | void Logger::log(std::string msg, std::string file, int line) 46 | { 47 | std::cout << "[" << file << "@" << line << "]: " << msg << std::endl; 48 | } 49 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CONFIG_H 29 | #define _CONFIG_H 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | class Conf 36 | { 37 | private: 38 | Conf() {} 39 | std::map confSet; 40 | public: 41 | static Conf &get(); 42 | bool load(std::string configFile); 43 | int iValue(std::string name); 44 | std::string sValue(std::string name); 45 | bool bValue(std::string name); 46 | std::vector vValue(std::string name); 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/mineserver.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _MINESERVER_H 29 | #define _MINESERVER_H 30 | 31 | #include 32 | 33 | class Mineserver 34 | { 35 | private: 36 | struct event m_listenEvent; 37 | event_base *m_eventBase; 38 | int m_socketlisten; 39 | bool m_running; 40 | 41 | public: 42 | static Mineserver &Get() 43 | { 44 | static Mineserver server; 45 | return server; 46 | } 47 | 48 | Mineserver(); 49 | int Run(int argc, char *argv[]); 50 | bool Stop(); 51 | event_base *GetEventBase(); 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/mapgen.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010 Drew Gottlieb - with code from fragmer and TkTech 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | // This code is modified from MySMP C# server by Drew Gottlieb 24 | // Thanks! 25 | 26 | #ifndef _MAPGEN_H 27 | #define _MAPGEN_H 28 | 29 | #ifdef WIN32 30 | #include 31 | #else 32 | #include 33 | #endif 34 | #include "noiseutils.h" 35 | 36 | class MapGen 37 | { 38 | private: 39 | uint8 *blocks; 40 | uint8 *blockdata; 41 | uint8 *skylight; 42 | uint8 *blocklight; 43 | uint8 *heightmap; 44 | 45 | /*float** heightMap; 46 | float** steepnessMap; 47 | float** caveTop; 48 | float** caveBottom; 49 | float** caveTop2; 50 | float** caveBottom2;*/ 51 | 52 | int m_seed; 53 | int oreDensity; 54 | int seaLevel; 55 | 56 | float perlinScale; 57 | 58 | //int getHeightmapIndex(char x, char z); 59 | //void calculateHeightmap(); 60 | 61 | void loadFlatgrass(); 62 | void generateWithNoise(int x, int z); 63 | 64 | noise::module::Perlin perlinNoise; 65 | noise::utils::NoiseMap heightMap; 66 | noise::utils::NoiseMapBuilderPlane heightMapBuilder; 67 | 68 | noise::module::RidgedMulti mountainTerrain; 69 | 70 | noise::module::Billow baseFlatTerrain; 71 | noise::module::ScaleBias flatTerrain; 72 | 73 | noise::module::Perlin terrainType; 74 | 75 | noise::module::Select finalTerrain; 76 | 77 | public: 78 | MapGen(int seed); 79 | ~MapGen(); 80 | void generateChunk(int x, int z); 81 | 82 | }; 83 | 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/physics.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _PHYSICS_H 29 | #define _PHYSICS_H 30 | 31 | class Physics 32 | { 33 | private: 34 | enum { TYPE_WATER, TYPE_LAVA } SimType; 35 | enum { M0, M1, M2, M3, M4, M5, M6, M7, M_FALLING } SimState; 36 | 37 | struct SimBlock 38 | { 39 | uint8 id; 40 | vec pos; 41 | uint8 meta; 42 | SimBlock() 43 | { 44 | } 45 | SimBlock(uint8 id, vec pos, uint8 meta) 46 | { 47 | this->id = id; 48 | this->pos = pos; 49 | this->meta = meta; 50 | } 51 | }; 52 | 53 | struct Sim 54 | { 55 | char type; 56 | std::vector blocks; 57 | 58 | Sim(char stype, SimBlock initblock) 59 | : type(stype), 60 | blocks(1, initblock) 61 | { 62 | } 63 | }; 64 | 65 | Physics() 66 | { 67 | enabled = true; 68 | } 69 | std::vector simList; 70 | public: 71 | bool enabled; 72 | static Physics &get(); 73 | bool update(); 74 | bool addSimulation(vec pos); 75 | bool checkSurrounding(vec pos); 76 | }; 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/chat.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CHAT_H 29 | #define _CHAT_H 30 | 31 | class Chat 32 | { 33 | public: 34 | enum MessageTarget 35 | { 36 | ALL, 37 | USER, 38 | OTHERS, 39 | ADMINS 40 | }; 41 | typedef void (*ChatCommand)(User *, std::string, std::deque ); 42 | //Chat(); 43 | std::deque admins; 44 | std::deque banned; 45 | std::deque whitelist; 46 | bool handleMsg( User *user, std::string msg ); 47 | bool sendMsg( User *user, std::string msg, MessageTarget action = ALL ); 48 | bool sendUserlist( User *user ); 49 | bool loadAdmins(std::string adminFile); 50 | bool loadBanned(std::string bannedFile); 51 | bool loadWhitelist(std::string whitelistFile); 52 | bool checkMotd(std::string motdFile); 53 | void registerCommand(std::string name, ChatCommand command, bool adminOnly); 54 | static Chat &get(); 55 | private: 56 | typedef std::map CommandList; 57 | CommandList userCommands; 58 | CommandList adminCommands; 59 | Chat(); 60 | void registerStandardCommands(); 61 | std::deque parseCmd(std::string cmd); 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | project(Mineserver) 3 | cmake_policy(SET CMP0003 NEW) 4 | 5 | # project version 6 | set( ${PROJECT_NAME}_MAJOR_VERSION 0 ) 7 | set( ${PROJECT_NAME}_MINOR_VERSION 1 ) 8 | set( ${PROJECT_NAME}_PATCH_LEVEL 0 ) 9 | 10 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) 11 | set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) 12 | 13 | # Set compiler specific build flags 14 | IF (UNIX) 15 | add_definitions(-msse -Wunused -g3 -O3 -Wall) 16 | ENDIF() 17 | 18 | IF (MSVC_IDE) 19 | set(PLATFORM_C_FLAGS "/D \"WIN32\" /D \"_WINDOWS\" /fp:fast /EHsc") 20 | set(CMAKE_CXX_FLAGS "${PLATFORM_C_FLAGS}") 21 | set(CMAKE_CXX_FLAGS_RELEASE "${PLATFORM_C_FLAGS}") 22 | set(CMAKE_CXX_FLAGS_DEBUG "${PLATFORM_C_FLAGS} /MDd") 23 | ENDIF (MSVC_IDE) 24 | 25 | file(GLOB_RECURSE folder_source ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) 26 | source_group("Mineserver" FILES ${folder_source}) 27 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/) 28 | 29 | set(dependency_error False) 30 | 31 | # find libraries 32 | 33 | find_package(ZLIB REQUIRED) 34 | if (NOT ZLIB_FOUND) 35 | set(errors "${errors}\t\t- ZLib\n") 36 | set(dependency_error True) 37 | endif() 38 | 39 | 40 | #find_package(Lua51) 41 | #if (NOT LUA51_FOUND) 42 | # set(errors "${errors}\t\t- LUA 5.1\n") 43 | # set(dependency_error True) 44 | #endif() 45 | 46 | 47 | find_library(EVENT_LIBRARY 48 | NAMES libevent.so 49 | PATHS /usr/lib /usr/local/lib 50 | ) 51 | find_path(EVENT_INCLUDE_DIR 52 | NAMES event.h 53 | PATHS /usr/include /usr/local/include 54 | ) 55 | 56 | if (NOT EVENT_LIBRARY OR NOT EVENT_INCLUDE_DIR) 57 | set(errors "${errors}\t\t- Event library\n") 58 | set(dependency_error True) 59 | endif() 60 | 61 | find_library(NOISE_LIBRARY 62 | NAMES libnoise.so 63 | PATHS /usr/lib /usr/local/lib 64 | ) 65 | find_path(NOISE_INCLUDE_DIR 66 | NAMES libnoise/noise.h noise/noise.h 67 | PATHS /usr/include /usr/local/include 68 | ) 69 | 70 | if (NOT NOISE_LIBRARY OR NOT NOISE_INCLUDE_DIR) 71 | set(errors "${errors}\t\t- libNoise library\n") 72 | set(dependency_error True) 73 | endif() 74 | 75 | 76 | if (WINDOWS) 77 | # even if 64bit this is set 78 | set(exe "WIN32") 79 | endif () 80 | 81 | if (NOT dependency_error) 82 | include_directories(${ZLIB_INCLUDE_DIR}) 83 | # include_directories(${LUA_INCLUDE_DIR}) 84 | include_directories(${EVENT_INCLUDE_DIR}) 85 | include_directories(${NOISE_INCLUDE_DIR}) 86 | 87 | add_executable(mineserver ${exe} ${folder_source}) 88 | 89 | target_link_libraries(mineserver ${ZLIB_LIBRARY}) 90 | # target_link_libraries(mineserver ${LUA_LIBRARY}) 91 | target_link_libraries(mineserver ${EVENT_LIBRARY}) 92 | target_link_libraries(mineserver ${NOISE_LIBRARY}) 93 | else() 94 | message(FATAL_ERROR "\n\tNot all dependencies could be found:\n${errors}\n After installing them please rerun cmake.\n") 95 | endif() 96 | -------------------------------------------------------------------------------- /src/mersenne.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | 29 | #include "mersenne.h" 30 | 31 | double Random::uniform() 32 | { 33 | return randgen() * (1.0 / (MAX + 1.0)); 34 | } 35 | 36 | unsigned Random::uniform(unsigned hi) 37 | { 38 | return static_cast(uniform() * hi); 39 | } 40 | 41 | unsigned Random::uniform(unsigned lo, unsigned hi) 42 | { 43 | return lo + uniform(hi - lo); 44 | } 45 | 46 | void Random::seedgen(unsigned long seed) 47 | { 48 | x[0] = seed & MAX; 49 | 50 | for (int i = 1; i < N; i++) { 51 | x[i] = (1812433253UL * (x[i - 1] ^ (x[i - 1] >> 30)) + i); 52 | x[i] &= MAX; 53 | } 54 | } 55 | 56 | // Mersenne Twister algorithm 57 | unsigned long Random::randgen() 58 | { 59 | unsigned long rnd; 60 | 61 | // Refill the pool when exhausted 62 | if (next == N) { 63 | int a; 64 | 65 | for (int i = 0; i < N - 1; i++) { 66 | rnd = (x[i] & UPPER_MASK) | x[i + 1] & LOWER_MASK; 67 | a = (rnd & 0x1UL) ? MATRIX_A : 0x0UL; 68 | x[i] = x[(i + M) % N] ^ (rnd >> 1) ^ a; 69 | } 70 | 71 | rnd = (x[N - 1] & UPPER_MASK) | x[0] & LOWER_MASK; 72 | a = (rnd & 0x1UL) ? MATRIX_A : 0x0UL; 73 | x[N - 1] = x[M - 1] ^ (rnd >> 1) ^ a; 74 | 75 | next = 0; // Rewind index 76 | } 77 | 78 | rnd = x[next++]; // Grab the next number 79 | 80 | // Voodoo to improve distribution 81 | rnd ^= (rnd >> 11); 82 | rnd ^= (rnd << 7) & 0x9d2c5680UL; 83 | rnd ^= (rnd << 15) & 0xefc60000UL; 84 | rnd ^= (rnd >> 18); 85 | 86 | return rnd; 87 | } 88 | -------------------------------------------------------------------------------- /src/tools.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _TOOLS_H 29 | #define _TOOLS_H 30 | 31 | #include 32 | 33 | #ifdef WIN32 34 | #include 35 | #else 36 | #include 37 | #endif 38 | 39 | typedef uint8_t uint8; 40 | typedef int8_t sint8; 41 | typedef uint16_t uint16; 42 | typedef int16_t sint16; 43 | typedef uint32_t uint32; 44 | typedef int32_t sint32; 45 | typedef uint64_t uint64; 46 | typedef int64_t sint64; 47 | 48 | void putSint64(uint8 *buf, sint64 value); 49 | void putSint32(uint8 *buf, sint32 value); 50 | void putSint16(uint8 *buf, short value); 51 | void putDouble(uint8 *buf, double value); 52 | void putFloat(uint8 *buf, float value); 53 | 54 | sint64 getSint64(uint8 *buf); 55 | double getDouble(uint8 *buf); 56 | float getFloat(uint8 *buf); 57 | sint32 getSint32(uint8 *buf); 58 | sint32 getSint16(uint8 *buf); 59 | 60 | void my_itoa(int value, std::string &buf, int base); 61 | std::string base36_encode(int value); 62 | std::string strToLower(std::string temp); 63 | 64 | std::string dtos(double n); 65 | 66 | inline uint64 ntohll(uint64 v) 67 | { 68 | if(htons(1) == 1) // check if already big-endian 69 | return v; 70 | return (uint64)ntohl(v & 0x00000000ffffffff) << 32 | (uint64)ntohl( (v >> 32) & 0x00000000ffffffff); 71 | } 72 | 73 | //Converts block-coordinates to chunk coordinate 74 | inline sint32 blockToChunk(sint32 value) 75 | { 76 | return (value < 0) ? (((value+1)/16)-1) : (value/16); 77 | } 78 | 79 | //Converts absolute block-coordinates to chunk-block-coordinates 80 | inline sint32 blockToChunkBlock(sint32 value) 81 | { 82 | return (value < 0) ? (15+((value+1)%16)) : (value%16); 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/item_alias.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Aliases for give command 3 | # 4 | 5 | stone = 1 6 | grass = 2 7 | dirt = 3 8 | cobblestone = 4 9 | wood = 5 10 | sapling = 6 11 | bedrock = 7 12 | water = 8 13 | statwater = 9 14 | lava = 10 15 | statlava = 11 16 | sand = 12 17 | gravel = 13 18 | goldore = 14 19 | ironore = 15 20 | coalore = 16 21 | log = 17 22 | leaves = 18 23 | sponge = 19 24 | glass = 20 25 | cloth = 36 26 | yellowflower = 37 27 | redrose = 38 28 | brownmushroom = 39 29 | redmushroom = 40 30 | goldblock = 41 31 | ironblock = 42 32 | doublestep = 43 33 | step = 44 34 | brick = 45 35 | tnt = 46 36 | bookshelf = 47 37 | mossycobblestone = 48 38 | obsidian = 49 39 | torch = 50 40 | fire = 51 41 | mobspawner = 52 42 | woodenstairs = 53 43 | chest = 54 44 | redstonewire = 55 45 | diamondore = 56 46 | diamondblock = 57 47 | workbench = 58 48 | crops = 59 49 | soil = 60 50 | furnace = 61 51 | signpost = 63 52 | woodendoor = 64 53 | ladder = 65 54 | tracks = 66 55 | cobblestonestairs = 67 56 | wallsign = 68 57 | redstoneore = 73 58 | ice = 79 59 | cactus = 81 60 | snow = 80 61 | clay = 82 62 | reed = 83 63 | jukebox = 84 64 | fence = 85 65 | pumpkin = 86 66 | netherstone = 87 67 | slowsand = 88 68 | lightstone = 89 69 | portal = 90 70 | jackolantern = 91 71 | 72 | # items 73 | ironspade = 256 74 | ironpickaxe = 257 75 | ironaxe = 258 76 | flintandsteel = 259 77 | apple = 260 78 | bow = 261 79 | arrow = 262 80 | coal = 263 81 | diamond = 264 82 | ironingot = 265 83 | goldingot = 266 84 | ironsword = 267 85 | woodensword = 268 86 | woodenspade = 269 87 | woodenpickaxe = 270 88 | woodenaxe = 271 89 | stonesword = 272 90 | stonespade = 273 91 | stonepickaxe = 274 92 | stoneaxe = 275 93 | diamondsword = 276 94 | diamondspade = 277 95 | diamondpickaxe = 278 96 | diamondaxe = 279 97 | stick = 280 98 | bowl = 281 99 | mushroomsoup = 282 100 | goldsword = 283 101 | goldspade = 284 102 | goldpickaxe = 285 103 | goldaxe = 286 104 | string = 287 105 | feather = 288 106 | gunpowder = 289 107 | woodenhoe = 290 108 | stonehoe = 291 109 | ironhoe = 292 110 | diamondhoe = 293 111 | goldhoe = 294 112 | seeds = 295 113 | wheat = 296 114 | bread = 297 115 | leatherhelmet = 298 116 | leatherchestplate = 299 117 | leatherleggings = 300 118 | leatherboots = 301 119 | chainmailhelmet = 302 120 | chainmailchestplate = 303 121 | chainmailaleggings = 304 122 | chainmailboots = 305 123 | ironhelmet = 306 124 | ironchestplate = 307 125 | ironleggings = 308 126 | ironboots = 309 127 | diamondhelmet = 310 128 | diamondchestplate = 311 129 | diamondleggings = 312 130 | diamondboots = 313 131 | goldhelmet = 314 132 | goldchestplate = 315 133 | goldleggings = 316 134 | goldboots = 317 135 | flint = 318 136 | pork = 319 137 | grilledpork = 320 138 | paintings = 312 139 | goldenapple = 322 140 | sign = 323 141 | woodendoor = 324 142 | bucket = 325 143 | waterbucket = 326 144 | lavabucket = 327 145 | minecart = 328 146 | saddle = 329 147 | irondoor = 330 148 | redstone = 331 149 | snowball = 332 150 | boat = 333 151 | leather = 334 152 | milkbucket = 335 153 | claybrick = 336 154 | clayballs = 337 155 | reed = 338 156 | paper = 339 157 | book = 340 158 | slimeball = 341 159 | storageminecart = 342 160 | poweredminecart = 343 161 | egg = 344 162 | compass = 345 163 | fishingrod = 346 164 | watch = 347 165 | lightstonedust = 348 166 | rawfish = 349 167 | cookedfish = 350 168 | goldrecord = 2256 169 | greenrecord = 2257 -------------------------------------------------------------------------------- /src/nbt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _NBT_H 29 | #define _NBT_H 30 | 31 | #include 32 | 33 | class NBT_Value 34 | { 35 | public: 36 | enum eTAG_Type 37 | { 38 | TAG_END = 0, 39 | TAG_BYTE = 1, 40 | TAG_SHORT = 2, 41 | TAG_INT = 3, 42 | TAG_LONG = 4, 43 | TAG_FLOAT = 5, 44 | TAG_DOUBLE = 6, 45 | TAG_BYTE_ARRAY = 7, 46 | TAG_STRING = 8, 47 | TAG_LIST = 9, 48 | TAG_COMPOUND = 10 49 | }; 50 | 51 | NBT_Value(eTAG_Type type, eTAG_Type listType = TAG_END); 52 | NBT_Value(sint8 value); 53 | NBT_Value(sint16 value); 54 | NBT_Value(sint32 value); 55 | NBT_Value(sint64 value); 56 | NBT_Value(float value); 57 | NBT_Value(double value); 58 | 59 | NBT_Value(uint8 *buf, sint32 len); 60 | NBT_Value(const std::string &str); 61 | 62 | NBT_Value(eTAG_Type type, uint8 **buf, int &remaining); 63 | 64 | ~NBT_Value(); 65 | 66 | NBT_Value *operator[](const std::string &index); 67 | NBT_Value *operator[](const char *index); 68 | 69 | void Insert(const std::string &str, NBT_Value *val); 70 | 71 | operator sint8(); 72 | operator sint16(); 73 | operator sint32(); 74 | operator sint64(); 75 | operator float(); 76 | operator double(); 77 | 78 | NBT_Value &operator =(sint8 val); 79 | NBT_Value &operator =(sint16 val); 80 | NBT_Value &operator =(sint32 val); 81 | NBT_Value &operator =(sint64 val); 82 | NBT_Value &operator =(float val); 83 | NBT_Value &operator =(double val); 84 | 85 | std::vector *GetByteArray(); 86 | std::string *GetString(); 87 | eTAG_Type GetListType(); 88 | std::vector *GetList(); 89 | 90 | void SetType(eTAG_Type type, eTAG_Type listType = TAG_END); 91 | 92 | eTAG_Type GetType(); 93 | void cleanup(); 94 | 95 | static NBT_Value * LoadFromFile(const std::string &filename); 96 | void SaveToFile(const std::string &filename); 97 | 98 | void Write(std::vector &buffer); 99 | 100 | void Print(const std::string &name = std::string(""), int tabs=0); 101 | private: 102 | eTAG_Type m_type; 103 | union 104 | { 105 | sint8 byteVal; 106 | sint16 shortVal; 107 | sint32 intVal; 108 | sint64 longVal; 109 | float floatVal; 110 | double doubleVal; 111 | std::string *stringVal; 112 | std::vector *byteArrayVal; 113 | struct 114 | { 115 | eTAG_Type type; 116 | std::vector *data; 117 | } listVal; 118 | std::map *compoundVal; 119 | } m_value; 120 | }; 121 | 122 | #endif 123 | -------------------------------------------------------------------------------- /src/constants.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | #include "constants.h" 32 | 33 | std::map defaultConf; 34 | std::map BLOCKDROPS; 35 | 36 | void initConstants() 37 | { 38 | // Init configuration 39 | defaultConf.insert(std::pair("ip", "0.0.0.0")); 40 | defaultConf.insert(std::pair("port", "25565")); 41 | defaultConf.insert(std::pair("servername", "Minecraft server")); 42 | defaultConf.insert(std::pair("use_whitelist", "false")); 43 | defaultConf.insert(std::pair("mapdir", "testmap")); 44 | defaultConf.insert(std::pair("userlimit", "20")); 45 | defaultConf.insert(std::pair("map_release_time", "10")); 46 | defaultConf.insert(std::pair("liquid_physics", "true")); 47 | defaultConf.insert(std::pair("map_flatland", "false")); 48 | defaultConf.insert(std::pair("oreDensity", "24")); 49 | defaultConf.insert(std::pair("seaLevel", "63")); 50 | defaultConf.insert(std::pair("server_full_message", "Server is currently full")); 51 | defaultConf.insert(std::pair("default_kick_message", "You have been kicked")); 52 | defaultConf.insert(std::pair("wrong_protocol_message", "Wrong client protocol")); 53 | defaultConf.insert(std::pair("admin_file", "admin.txt")); 54 | defaultConf.insert(std::pair("motd_file", "motd.txt")); 55 | defaultConf.insert(std::pair("rules_file", "rules.txt")); 56 | 57 | // Block drops (10000 = 100%) 58 | BLOCKDROPS.insert(std::pair(BLOCK_STONE, Drop(BLOCK_COBBLESTONE, 10000, 1, true))); 59 | BLOCKDROPS.insert(std::pair(BLOCK_GRASS, Drop(BLOCK_DIRT, 10000, 1, true))); 60 | BLOCKDROPS.insert(std::pair(BLOCK_GRAVEL, Drop(ITEM_FLINT, 850, 1, false))); 61 | BLOCKDROPS.insert(std::pair(BLOCK_COAL_ORE, Drop(ITEM_COAL, 10000, 1, true))); 62 | BLOCKDROPS.insert(std::pair(BLOCK_LEAVES, Drop(BLOCK_SAPLING, 1200, 1, true))); 63 | BLOCKDROPS.insert(std::pair(BLOCK_DIAMOND_ORE, Drop(ITEM_DIAMOND, 10000, 1, true))); 64 | BLOCKDROPS.insert(std::pair(BLOCK_REDSTONE_ORE, Drop(ITEM_REDSTONE, 10000, 4, true))); 65 | BLOCKDROPS.insert(std::pair(BLOCK_CLAY, Drop(ITEM_CLAY_BALLS, 10000, 4, true))); 66 | 67 | // Blocks that drop nothing 68 | BLOCKDROPS.insert(std::pair(BLOCK_TNT, Drop(BLOCK_TNT, 10000, 0, true))); 69 | BLOCKDROPS.insert(std::pair(BLOCK_GLASS, Drop(BLOCK_GLASS, 10000, 0, true))); 70 | BLOCKDROPS.insert(std::pair(BLOCK_MOB_SPAWNER, Drop(BLOCK_MOB_SPAWNER, 10000, 0, true))); 71 | } 72 | -------------------------------------------------------------------------------- /src/tools.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifdef WIN32 29 | #include 30 | #include 31 | #else 32 | #include 33 | #endif 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "tools.h" 46 | #include "string.h" 47 | 48 | void putSint64(uint8 *buf, sint64 value) 49 | { 50 | uint64 nval = ntohll(value); 51 | memcpy(buf, &nval, 8); 52 | } 53 | 54 | void putSint32(uint8 *buf, sint32 value) 55 | { 56 | uint32 nval = htonl(value); 57 | memcpy(buf, &nval, 4); 58 | } 59 | 60 | void putSint16(uint8 *buf, short value) 61 | { 62 | short value2=htons(value); 63 | memcpy(buf, &value2, 2); 64 | } 65 | 66 | void putFloat(uint8 *buf, float value) 67 | { 68 | uint32 nval; 69 | memcpy(&nval, &value, 4); 70 | nval = htonl(nval); 71 | memcpy(buf, &nval, 4); 72 | } 73 | 74 | void putDouble(uint8 *buf, double value) 75 | { 76 | uint64 nval; 77 | memcpy(&nval, &value, 8); 78 | nval = ntohll(nval); 79 | memcpy(buf, &nval, 8); 80 | } 81 | 82 | double getDouble(uint8 *buf) 83 | { 84 | double val; 85 | uint64 ival = *reinterpret_cast(buf); 86 | ival = ntohll(ival); 87 | memcpy(&val, &ival, 8); 88 | return val; 89 | } 90 | 91 | float getFloat(uint8 *buf) 92 | { 93 | float val; 94 | int ival = ntohl(*reinterpret_cast(buf)); 95 | memcpy(&val, &ival, 4); 96 | return val; 97 | } 98 | 99 | sint64 getSint64(uint8 *buf) 100 | { 101 | sint64 val; 102 | val = *reinterpret_cast(buf); 103 | val = ntohll(val); 104 | return val; 105 | } 106 | 107 | sint32 getSint32(uint8 *buf) 108 | { 109 | int val = ntohl(*reinterpret_cast(buf)); 110 | return val; 111 | } 112 | 113 | sint32 getSint16(uint8 *buf) 114 | { 115 | short val = ntohs(*reinterpret_cast(buf)); 116 | 117 | return val; 118 | } 119 | 120 | std::string base36_encode(int value) 121 | { 122 | std::string output; 123 | my_itoa((int)abs(value), output, 36); 124 | if(value < 0) 125 | output.insert (output.begin(), '-'); 126 | 127 | return output; 128 | } 129 | 130 | void my_itoa(int value, std::string &buf, int base) 131 | { 132 | std::string hexarray("0123456789abcdefghijklmnopqrstuvwxyz"); 133 | int i = 30; 134 | buf = ""; 135 | 136 | if(!value) 137 | buf = "0"; 138 | 139 | for(; value && i; --i, value /= base) 140 | { 141 | buf.insert(buf.begin(), (char)hexarray[value % base]); 142 | } 143 | } 144 | 145 | std::string strToLower(std::string temp) 146 | { 147 | const int len = temp.length(); 148 | 149 | for(int i = 0; i != len; ++i) 150 | { 151 | temp[i] = std::tolower(temp[i]); 152 | } 153 | 154 | return temp; 155 | } 156 | 157 | std::string dtos( double n ) 158 | { 159 | std::ostringstream result; 160 | result << n; 161 | return result.str(); 162 | } -------------------------------------------------------------------------------- /src/user.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _USER_H 29 | #define _USER_H 30 | 31 | #include 32 | #include 33 | #include "vec.h" 34 | #include "tools.h" 35 | #include "constants.h" 36 | #include "packets.h" 37 | 38 | struct position 39 | { 40 | double x; 41 | double y; 42 | double z; 43 | double stance; 44 | float yaw; 45 | float pitch; 46 | }; 47 | 48 | struct Item 49 | { 50 | sint16 type; 51 | sint8 count; 52 | sint16 health; 53 | Item() 54 | { 55 | type = 0; 56 | count = 0; 57 | health = 0; 58 | } 59 | }; 60 | 61 | struct Inventory 62 | { 63 | Item main[36]; 64 | Item equipped[4]; 65 | Item crafting[4]; 66 | 67 | Inventory() 68 | { 69 | } 70 | }; 71 | 72 | class User 73 | { 74 | private: 75 | event m_event; 76 | public: 77 | 78 | User(int sock, uint32 EID); 79 | ~User(); 80 | 81 | int fd; 82 | 83 | //View distance in chunks -viewDistance <-> viewDistance 84 | static const int viewDistance = 10; 85 | uint8 action; 86 | bool waitForData; 87 | uint32 write_err_count; 88 | bool logged; 89 | bool admin; 90 | bool banned; 91 | bool whitelist; 92 | sint16 health; 93 | unsigned int UID; 94 | std::string nick; 95 | position pos; 96 | vec curChunk; 97 | Inventory inv; 98 | 99 | //Input buffer 100 | Packet buffer; 101 | 102 | bool checkBanned(std::string _nick); 103 | bool checkWhitelist(std::string _nick); 104 | bool changeNick(std::string _nick); 105 | bool updatePos(double x, double y, double z, double stance); 106 | bool updateLook(float yaw, float pitch); 107 | 108 | bool sendOthers(uint8 *data, uint32 len); 109 | static bool sendAll(uint8 *data, uint32 len); 110 | static bool sendAdmins(uint8 *data, uint32 len); 111 | 112 | //Check inventory for space 113 | bool checkInventory(sint16 itemID, char count); 114 | 115 | //Load/save player data from/to a file at /players/.dat 116 | bool saveData(); 117 | bool loadData(); 118 | 119 | // Kick player 120 | bool kick(std::string kickMsg); 121 | 122 | //Map related 123 | 124 | //Map queue 125 | std::vector mapQueue; 126 | 127 | //Chunks needed to be removed from client 128 | std::vector mapRemoveQueue; 129 | 130 | //Known map pieces 131 | std::vector mapKnown; 132 | 133 | //Add map coords to queue 134 | bool addQueue(int x, int z); 135 | 136 | //Add map coords to remove queue 137 | bool addRemoveQueue(int x, int z); 138 | 139 | //Add known map piece 140 | bool addKnown(int x, int z); 141 | 142 | //Delete known map piece 143 | bool delKnown(int x, int z); 144 | 145 | //Push queued map data to client 146 | bool pushMap(); 147 | 148 | //Push remove queued map data to client 149 | bool popMap(); 150 | 151 | bool teleport(double x, double y, double z); 152 | bool spawnUser(int x, int y, int z); 153 | bool spawnOthers(); 154 | bool sethealth(int userHealth); 155 | bool respawn(); 156 | bool dropInventory(); 157 | 158 | struct event *GetEvent(); 159 | }; 160 | 161 | User *addUser(int sock, uint32 EID); 162 | bool remUser(int sock); 163 | bool isUser(int sock); 164 | uint32 generateEID(); 165 | 166 | extern std::vector Users; 167 | 168 | User *getUserByNick(std::string nick); 169 | 170 | #endif -------------------------------------------------------------------------------- /src/vec.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _VEC_H 29 | #define _VEC_H 30 | 31 | #if defined(__clang__) || defined(__gcc__) 32 | #define VEC_VECTORISED 33 | #endif 34 | 35 | class vec 36 | { 37 | private: 38 | #ifdef VEC_VECTORISED 39 | typedef int ivec __attribute__((vector_size(16))); 40 | union 41 | { 42 | int arrayValue[4]; 43 | ivec vectorValue; 44 | } data; 45 | vec(ivec vector) 46 | { 47 | data.vectorValue = vector; 48 | } 49 | #else 50 | union 51 | { 52 | int arrayValue[3]; 53 | } data; 54 | #endif 55 | public: 56 | vec(int x, int y, int z) 57 | { 58 | data.arrayValue[0] = x; 59 | data.arrayValue[1] = y; 60 | data.arrayValue[2] = z; 61 | } 62 | vec(const int values[3]) 63 | { 64 | data.arrayValue[0] = values[0]; 65 | data.arrayValue[1] = values[1]; 66 | data.arrayValue[2] = values[2]; 67 | } 68 | vec() 69 | { 70 | data.arrayValue[0] = 0; 71 | data.arrayValue[1] = 0; 72 | data.arrayValue[2] = 0; 73 | } 74 | vec(const vec &ov) 75 | { 76 | #ifdef VEC_VECTORISED 77 | data.vectorValue = ov.data.vectorValue; 78 | #else 79 | data.arrayValue[0] = ov.data.arrayValue[0]; 80 | data.arrayValue[1] = ov.data.arrayValue[1]; 81 | data.arrayValue[2] = ov.data.arrayValue[2]; 82 | #endif 83 | } 84 | 85 | vec& operator=(const vec &ov) 86 | { 87 | #ifdef VEC_VECTORISED 88 | data.vectorValue = ov.data.vectorValue; 89 | #else 90 | data.arrayValue[0] = ov.data.arrayValue[0]; 91 | data.arrayValue[1] = ov.data.arrayValue[1]; 92 | data.arrayValue[2] = ov.data.arrayValue[2]; 93 | #endif 94 | return *this; 95 | } 96 | 97 | int &x() 98 | { 99 | return data.arrayValue[0]; 100 | } 101 | int &y() 102 | { 103 | return data.arrayValue[1]; 104 | } 105 | int &z() 106 | { 107 | return data.arrayValue[2]; 108 | } 109 | const int &x() const 110 | { 111 | return data.arrayValue[0]; 112 | } 113 | const int &y() const 114 | { 115 | return data.arrayValue[1]; 116 | } 117 | const int &z() const 118 | { 119 | return data.arrayValue[2]; 120 | } 121 | 122 | vec operator+(const vec &ov) const 123 | { 124 | #ifdef VEC_VECTORISED 125 | return vec(data.vectorValue + ov.data.vectorValue); 126 | 127 | #else 128 | return vec(x() + ov.x(), 129 | y() + ov.y(), 130 | z() + ov.z()); 131 | 132 | #endif 133 | } 134 | vec operator-(const vec &ov) const 135 | { 136 | #ifdef VEC_VECTORISED 137 | return vec(data.vectorValue - ov.data.vectorValue); 138 | 139 | #else 140 | return vec(x() - ov.x(), 141 | y() - ov.y(), 142 | z() - ov.z()); 143 | 144 | #endif 145 | } 146 | vec operator-() const 147 | { 148 | #ifdef VEC_VECTORISED 149 | return vec(-data.vectorValue); 150 | 151 | #else 152 | return vec(-x(), 153 | -y(), 154 | -z()); 155 | 156 | #endif 157 | } 158 | 159 | vec& operator+=(const vec &ov) 160 | { 161 | return *this = *this + ov; 162 | } 163 | vec& operator-=(const vec &ov) 164 | { 165 | return *this = *this - ov; 166 | } 167 | 168 | int squareLength() const 169 | { 170 | return x()*x() + y()*y() + z()*z(); 171 | } 172 | 173 | static int squareDistance(const vec &x, const vec &y) 174 | { 175 | return (x - y).squareLength(); 176 | } 177 | }; 178 | 179 | #endif 180 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mineserver 2 | *by Fador & Nredor and others* 3 | 4 | You can find the core team from #mineserver @ irc.esper.net 5 | Also mail to developers@mineserver.be will reach us. 6 | 7 | Copyright (c) 2010, The Mineserver Project 8 | 9 | Custom Minecraft Alpha server software written in C++. 10 | 11 | ### == NOTICE == 12 | Currently in (early) development. (Alpha stage) 13 | Server still lacks some critical features and should be only used for testing. 14 | 15 | **Tested to build on** 16 | 17 | * Windows (VS2010 and VS2008 projects included) 18 | * Linux (Makefile included) 19 | * Mac OS X 20 | * FreeBSD / PCBSD 21 | 22 | We are trying to minimize memory and cpu usage compared to original Java server. 23 | 24 | ### Features 25 | * Various chat commands, more to come.. 26 | * NBT parsing/saving 27 | * Lightmap generation 28 | * Config file 29 | * Normal mining/item spawning/item pickups 30 | * Basic physics for gravel and sand 31 | * Experimental physics for water and lava 32 | * Flatland map generation 33 | * Working chests 34 | * Terrain generation 35 | 36 | ### ToDo (Arranged by priority) 37 | * Getting furnaces and signs to work (In progress) 38 | * Plugin support (and Lua plugin for scripting) 39 | * Multithreading 40 | * Server console 41 | * Growing trees and cactuses 42 | * One-click update 43 | * and more 44 | 45 | ### Chat commands 46 | 47 | **For all players** 48 | 49 | * /players : Lists online players 50 | * /about : Server name & version 51 | * /rules : Shows server rules 52 | * /home : Teleports user to map spawn location 53 | * /kit (name) : Gives kit. Items for kit defined in config.cfg with kit_(name) using itemId's 54 | 55 | **Admin only** 56 | 57 | * %text : Servermessage 58 | * &text : Admin-only message 59 | * /kick nick (kickmsg) : Kicks user with optional kick message 60 | * /ban nick : Bans (and kicks if online) user from server 61 | * /unban nick : Lift a ban 62 | * /save : Manually save map to disc 63 | * /ctp x y z : Teleport to coordinates (eg. /ctp 100 100 100) 64 | * /tp nick : Teleport yourself to nick's position 65 | * /tp nick1 nick2 : Teleport nick1 to nick2 66 | * /reload : Reload admins and configuration 67 | * /give nick id/alias (count) : Gives nick count pieces of id/alias. count = 1 is used if it is not provided. Support for over 64 items. Aliases configurable with item_alias.cfg 68 | * /rules nick : Shows server rules (from rules.txt) to nick 69 | * /gps (nick) : Without nick shows own coordinates. With nick shows nick's coordinates 70 | * /settime (time) : Sets server time. time = 0-24000 (0 and 24000 is day and about 15000 is night) 71 | 72 | ### Compiling 73 | Depends on (and tested with): 74 | 75 | [zlib 1.2.5](http://www.zlib.org) 76 | [libevent 1.4.14b](http://monkey.org/~provos/libevent/) 77 | [libnoise 1.0](http://libnoise.sourceforge.net/) 78 | 79 | * Installing on Debian and Ubuntu: (For Ubuntu libevent1 -> libevent-1.4-2) 80 | 81 | `sudo apt-get install libevent1 libevent-dev zlib1g zlib1g-dev libnoise-dev` 82 | 83 | * Installing on CentOS and RHEL 84 | 85 | `# Install EPEL (Extra Packages for Enterprise Linux)` 86 | `sudo su -c 'rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm'` 87 | `sudo yum install git libevent libevent-devel zlib zlib-devel libnoise-dev` 88 | 89 | * Installing on FreeBSD / PCBSD 90 | 91 | `sudo pkg_add -r libevent` 92 | 93 | **Compiling using linux (make & gcc):** 94 | 95 | * Download and extract source or use `git clone git://github.com/fador/mineserver.git` 96 | * Go to mineserver/src/ directory 97 | * Run `make` 98 | * Run server with `./mineserver` 99 | 100 | **Compiling using FreeBSD / PCBSD (gmake & g++):** 101 | 102 | * Download and extract source or use `git clone git://github.com/fador/mineserver.git` 103 | * Go to mineserver/src/ directory 104 | * Run `gmake` 105 | * Run server with `./mineserver` 106 | 107 | **Compiling using windows (VS2010/VS2008):** 108 | 109 | * Download and compile [zlib](http://www.zlib.org) or use [pre-built binaries](http://www.winimage.com/zLibDll/index.html) 110 | * Add zlib libraries to project (zlibstat.lib or zlibwapi.lib which requires also zlibwapi.dll in the same dir with the executable) 111 | * Download and compile [libevent](http://monkey.org/~provos/libevent/) 112 | * Download [libnoise 1.0](http://libnoise.sourceforge.net/) and add header/library files to project 113 | * Add libevent library to project (libevent.lib) 114 | * Build 115 | * Run mineserver.exe 116 | 117 | An example using commandline compiler available at http://www.microsoft.com/express/Windows/ Please change the ZLIB_INC_DIR, LIBEVENT_INC_DIR, ZLIB_LIB_DIR and LIBEVENT_LIB_DIR to those you keep the includes/libs. 118 | 119 | call "%VS100COMNTOOLS%vsvars32.bat" 120 | cl /I"ZLIB_INC_DIR;LIBEVENT_INC_DIR" /W3 /WX- /O2 /D ZLIB_WINAPI /D WIN32 /D NDEBUG /D _CRT_SECURE_NO_WARNINGS /EHsc *.cpp zlibwapi.lib libevent.lib Ws2_32.lib /link /OUT:mineserver.exe /LIBPATH:"ZLIB_LIB_DIR;LIBEVENT_LIB_DIR" 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /mineserver/mineserver.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | {7F6D1DAB-AA49-4343-B28E-C3E647BE5007} 48 | Win32Proj 49 | mineserver 50 | 51 | 52 | 53 | Application 54 | true 55 | Unicode 56 | 57 | 58 | Application 59 | false 60 | true 61 | Unicode 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | ZLIB_WINAPI;WIN32;DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 86 | %(AdditionalIncludeDirectories) 87 | 88 | 89 | Console 90 | true 91 | libnoise.lib;zlibwapi.lib;ws2_32.lib;libevent.lib;%(AdditionalDependencies) 92 | LIBCMT 93 | 94 | 95 | 96 | 97 | Level3 98 | 99 | 100 | Full 101 | true 102 | true 103 | WIN32;ZLIB_WINAPI;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CONSOLE;FTLOG=main;%(PreprocessorDefinitions) 104 | 105 | 106 | ProgramDatabase 107 | StreamingSIMDExtensions2 108 | Speed 109 | 110 | 111 | Console 112 | true 113 | true 114 | true 115 | libnoise.lib;zlibwapi.lib;libevent.lib;Ws2_32.lib;%(AdditionalDependencies) 116 | LIBCMT 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "logger.h" 38 | #include "constants.h" 39 | 40 | #include "config.h" 41 | 42 | Conf &Conf::get() 43 | { 44 | static Conf instance; 45 | return instance; 46 | } 47 | 48 | // Load/reload configuration 49 | bool Conf::load(std::string configFile) 50 | { 51 | std::cout << "Loading data from " << configFile << std::endl; 52 | std::ifstream ifs(configFile.c_str()); 53 | 54 | // If configfile does not exist 55 | if(ifs.fail() && configFile == CONFIG_FILE) 56 | { 57 | // TODO: Load default configuration from the internets! 58 | std::cout << ">>> " << configFile << " not found." << std::endl; 59 | 60 | std::ofstream confofs(configFile.c_str()); 61 | confofs << "#" << std::endl<< 62 | "# Load configuration example from:
" << std::endl<< 63 | "#" << std::endl; 64 | confofs.close(); 65 | 66 | this->load(CONFIG_FILE); 67 | } 68 | 69 | std::string temp; 70 | 71 | // Reading row at a time 72 | int del; 73 | int lineNum = 0; 74 | std::vector line; 75 | std::string text; 76 | while(getline(ifs, temp)) 77 | { 78 | //If empty line 79 | if(temp.size() == 0) 80 | continue; 81 | 82 | // If commentline -> skip to next 83 | if(temp[0] == COMMENTPREFIX) 84 | continue; 85 | 86 | // If not enough characters (Absolute min is 5: "a = s") 87 | if(temp.length() < 5) 88 | continue; 89 | 90 | // Init vars 91 | del = 0; 92 | line.clear(); 93 | 94 | // Process line 95 | while(temp.length() > 0) 96 | { 97 | // Remove white spaces and = characters -_- 98 | while(temp[0] == ' ' || temp[0] == '=') 99 | temp = temp.substr(1); 100 | 101 | // Split words 102 | del = temp.find(' '); 103 | if(del > -1) 104 | { 105 | line.push_back(temp.substr(0, del)); 106 | temp = temp.substr(del+1); 107 | } 108 | else 109 | { 110 | line.push_back(temp); 111 | break; 112 | } 113 | } 114 | 115 | // If under two words skip the line and log skipping. 116 | if(line.size() < 2) 117 | { 118 | std::cout << "Invalid configuration at line " << lineNum << " of " << configFile; 119 | continue; 120 | } 121 | 122 | // Construct strings if needed 123 | text = ""; 124 | if(line[1][0] == '"') 125 | { 126 | // Append to text 127 | for(unsigned int i = 1; i < line.size(); i++) 128 | { 129 | text += line[i] + " "; 130 | } 131 | // Remove "" 132 | text = text.substr(1, text.length()-3); 133 | } 134 | else 135 | text = line[1]; 136 | 137 | // Update existing configuration and add new lines 138 | if(confSet.find(line[0]) != confSet.end()) 139 | confSet[line[0]] = text; 140 | else 141 | { 142 | // Push to configuration 143 | confSet.insert(std::pair(line[0], text)); 144 | } 145 | 146 | // Count line numbers 147 | lineNum++; 148 | } 149 | ifs.close(); 150 | 151 | std::cout << "Loaded " << lineNum << " lines from " << configFile << std::endl; 152 | 153 | return true; 154 | } 155 | 156 | // Return values 157 | std::string Conf::sValue(std::string name) 158 | { 159 | if(confSet.find(name) != confSet.end()) 160 | return confSet[name]; 161 | else 162 | { 163 | std::cout << "Warning! " << name << " not defined in configuration. Using default value: "<< 164 | defaultConf[name] << std::endl; 165 | return defaultConf[name]; 166 | } 167 | } 168 | 169 | int Conf::iValue(std::string name) 170 | { 171 | if(confSet.find(name) != confSet.end()) 172 | return atoi(confSet[name].c_str()); 173 | else 174 | { 175 | std::cout << "Warning! " << name << " not defined in configuration. Using default value: "<< 176 | defaultConf[name] << std::endl; 177 | return atoi(defaultConf[name].c_str()); 178 | } 179 | } 180 | 181 | bool Conf::bValue(std::string name) 182 | { 183 | if(confSet.find(name) != confSet.end()) 184 | return (confSet[name] == "true")?true:false; 185 | else 186 | { 187 | std::cout << "Warning! " << name << " not defined in configuration. Using default value: "<< 188 | defaultConf[name] << std::endl; 189 | return (defaultConf[name] == "true")?true:false; 190 | } 191 | } 192 | 193 | std::vector Conf::vValue(std::string name) 194 | { 195 | std::vector temp; 196 | std::string tmpStr; 197 | int del; 198 | if(confSet.find(name) != confSet.end()) 199 | { 200 | tmpStr = confSet[name]; 201 | 202 | // Process "array" 203 | while(tmpStr.length() > 0) 204 | { 205 | // Remove white spaces characters 206 | while(tmpStr[0] == ' ') 207 | tmpStr = tmpStr.substr(1); 208 | 209 | // Split words 210 | del = tmpStr.find(','); 211 | if(del > -1) 212 | { 213 | temp.push_back(atoi(tmpStr.substr(0, del).c_str())); 214 | tmpStr = tmpStr.substr(del+1); 215 | } 216 | else 217 | { 218 | temp.push_back(atoi(tmpStr.c_str())); 219 | break; 220 | } 221 | } 222 | 223 | return temp; 224 | } 225 | else 226 | { 227 | std::cout << "Warning! " << name << " not defined in configuration." << std::endl; 228 | return temp; 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /src/sockets.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifdef WIN32 29 | #include 30 | #include 31 | #include 32 | typedef int socklen_t; 33 | #else 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #endif 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include "logger.h" 54 | #include "constants.h" 55 | 56 | #include "tools.h" 57 | 58 | #include "user.h" 59 | #include "map.h" 60 | #include "chat.h" 61 | #include "nbt.h" 62 | #include "packets.h" 63 | 64 | 65 | extern int setnonblock(int fd); 66 | 67 | 68 | void client_callback(int fd, 69 | short ev, 70 | void *arg) 71 | { 72 | User *user = (User *)arg; 73 | 74 | if(ev & EV_READ) 75 | { 76 | 77 | int read = 1; 78 | 79 | uint8 *buf = new uint8[2048]; 80 | 81 | read = recv(fd, (char*)buf, 2048, 0); 82 | if(read == 0) 83 | { 84 | std::cout << "Socket closed properly" << std::endl; 85 | //event_del(user->GetEvent()); 86 | 87 | #ifdef WIN32 88 | closesocket(user->fd); 89 | #else 90 | close(user->fd); 91 | #endif 92 | remUser(user->fd); 93 | return; 94 | } 95 | 96 | if(read == -1) 97 | { 98 | std::cout << "Socket had no data to read" << std::endl; 99 | #ifdef WIN32 100 | closesocket(user->fd); 101 | #else 102 | close(user->fd); 103 | #endif 104 | remUser(user->fd); 105 | return; 106 | } 107 | 108 | user->buffer.addToRead(buf, read); 109 | 110 | delete[] buf; 111 | 112 | user->buffer.reset(); 113 | 114 | while(user->buffer >> (sint8&)user->action) 115 | { 116 | //Variable len package 117 | if(PacketHandler::get().packets[user->action].len == PACKET_VARIABLE_LEN) 118 | { 119 | //Call specific function 120 | int (PacketHandler::*function)(User *) = 121 | PacketHandler::get().packets[user->action].function; 122 | bool disconnecting = user->action == 0xFF; 123 | int curpos = (PacketHandler::get().*function)(user); 124 | if(curpos == PACKET_NEED_MORE_DATA) 125 | { 126 | user->waitForData = true; 127 | event_set(user->GetEvent(), fd, EV_READ, client_callback, user); 128 | event_add(user->GetEvent(), NULL); 129 | return; 130 | } 131 | 132 | if(disconnecting) // disconnect -- player gone 133 | { 134 | return; 135 | } 136 | } 137 | else if(PacketHandler::get().packets[user->action].len == PACKET_DOES_NOT_EXIST) 138 | { 139 | printf("Unknown action: 0x%x\n", user->action); 140 | 141 | //event_del(user->GetEvent()); 142 | 143 | #ifdef WIN32 144 | closesocket(user->fd); 145 | #else 146 | close(user->fd); 147 | #endif 148 | remUser(user->fd); 149 | } 150 | else 151 | { 152 | if(!user->buffer.haveData(PacketHandler::get().packets[user->action].len)) 153 | { 154 | user->waitForData = true; 155 | event_set(user->GetEvent(), fd, EV_READ, client_callback, user); 156 | event_add(user->GetEvent(), NULL); 157 | return; 158 | } 159 | 160 | //Call specific function 161 | int (PacketHandler::*function)(User *) = PacketHandler::get().packets[user->action].function; 162 | (PacketHandler::get().*function)(user); 163 | } 164 | } //End while 165 | } 166 | 167 | int writeLen = user->buffer.getWriteLen(); 168 | if(writeLen) 169 | { 170 | int written = send(fd, (char*)user->buffer.getWrite(), writeLen, 0); 171 | if(written == -1) 172 | { 173 | if((errno != EAGAIN && errno != EINTR) || user->write_err_count>200) 174 | { 175 | std::cout << "Error writing to client" << std::endl; 176 | //event_del(user->GetEvent()); 177 | 178 | #ifdef WIN32 179 | closesocket(user->fd); 180 | #else 181 | close(user->fd); 182 | #endif 183 | remUser(user->fd); 184 | return; 185 | } 186 | else 187 | { 188 | user->write_err_count++; 189 | } 190 | 191 | } 192 | else 193 | { 194 | user->buffer.clearWrite(written); 195 | user->write_err_count=0; 196 | } 197 | 198 | if(user->buffer.getWriteLen()) 199 | { 200 | event_set(user->GetEvent(), fd, EV_WRITE|EV_READ, client_callback, user); 201 | event_add(user->GetEvent(), NULL); 202 | return; 203 | } 204 | } 205 | 206 | event_set(user->GetEvent(), fd, EV_READ, client_callback, user); 207 | event_add(user->GetEvent(), NULL); 208 | 209 | } 210 | 211 | void accept_callback(int fd, 212 | short ev, 213 | void *arg) 214 | { 215 | int client_fd; 216 | struct sockaddr_in client_addr; 217 | socklen_t client_len = sizeof(client_addr); 218 | 219 | 220 | client_fd = accept(fd, 221 | (struct sockaddr *)&client_addr, 222 | &client_len); 223 | if(client_fd < 0) 224 | { 225 | LOG("Client: accept() failed"); 226 | return; 227 | } 228 | User *client = addUser(client_fd, generateEID()); 229 | setnonblock(client_fd); 230 | 231 | event_set(client->GetEvent(), client_fd,EV_WRITE|EV_READ, client_callback, client); 232 | event_add(client->GetEvent(), NULL); 233 | 234 | } 235 | -------------------------------------------------------------------------------- /mineserver/vs2008/mineserver.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 26 | 29 | 32 | 35 | 38 | 41 | 53 | 56 | 59 | 62 | 72 | 75 | 78 | 81 | 84 | 87 | 90 | 93 | 94 | 102 | 105 | 108 | 111 | 114 | 117 | 128 | 131 | 134 | 137 | 146 | 149 | 152 | 155 | 158 | 161 | 164 | 167 | 168 | 169 | 170 | 171 | 172 | 177 | 180 | 181 | 184 | 185 | 188 | 189 | 192 | 193 | 196 | 197 | 200 | 201 | 204 | 205 | 208 | 209 | 212 | 213 | 216 | 217 | 220 | 221 | 224 | 225 | 228 | 229 | 232 | 233 | 236 | 237 | 240 | 241 | 242 | 247 | 250 | 251 | 254 | 255 | 258 | 259 | 262 | 263 | 266 | 267 | 270 | 271 | 274 | 275 | 278 | 279 | 282 | 283 | 286 | 287 | 290 | 291 | 294 | 295 | 298 | 299 | 302 | 303 | 306 | 307 | 310 | 311 | 312 | 317 | 318 | 319 | 320 | 321 | 322 | -------------------------------------------------------------------------------- /src/map.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _MAP_H_ 29 | #define _MAP_H_ 30 | 31 | #include 32 | #include 33 | #include "nbt.h" 34 | #include "user.h" 35 | #include "vec.h" 36 | 37 | struct sChunk 38 | { 39 | uint8 *blocks; 40 | uint8 *data; 41 | uint8 *blocklight; 42 | uint8 *skylight; 43 | uint8 *heightmap; 44 | sint32 x; 45 | sint32 z; 46 | NBT_Value *nbt; 47 | }; 48 | 49 | struct spawnedItem 50 | { 51 | int EID; 52 | sint16 item; 53 | char count; 54 | sint16 health; 55 | vec pos; 56 | time_t spawnedAt; 57 | uint32 spawnedBy; 58 | 59 | spawnedItem() 60 | { 61 | spawnedAt = time(0); 62 | spawnedBy = 0; 63 | } 64 | }; 65 | 66 | class Map 67 | { 68 | private: 69 | 70 | Map() 71 | { 72 | for(int i = 0; i < 256; i++) 73 | emitLight[i] = 0; 74 | emitLight[0x0A] = 15; // Lava 75 | emitLight[0x0B] = 15; // Stationary Lava 76 | emitLight[0x27] = 1; // Brown mushroom 77 | emitLight[0x32] = 14; // Torch 78 | emitLight[0x33] = 15; // Fire 79 | emitLight[0x3E] = 14; // Lit furnace 80 | emitLight[0x4A] = 9; // Redstone ore (Glowing) 81 | emitLight[0x4C] = 7; // Redstone Torch (On) 82 | emitLight[0x59] = 15; // Lightstone 83 | emitLight[0x5A] = 11; // Portal 84 | emitLight[0x5B] = 15; // Jack-O-Lantern 85 | 86 | for(int i = 0; i < 256; i++) 87 | stopLight[i] = 16; 88 | stopLight[0x00] = 0; // Empty 89 | stopLight[0x06] = 0; // Sapling 90 | stopLight[0x08] = 3; // Water 91 | stopLight[0x09] = 3; // Stationary water 92 | stopLight[0x12] = 3; // Leaves 93 | stopLight[0x14] = 0; // Glass 94 | stopLight[0x25] = 0; // Yellow flower 95 | stopLight[0x26] = 0; // Red rose 96 | stopLight[0x27] = 0; // Brown mushroom 97 | stopLight[0x28] = 0; // Red mushroom 98 | stopLight[0x32] = 0; // Torch 99 | stopLight[0x33] = 0; // Fire 100 | stopLight[0x34] = 0; // Mob spawner 101 | stopLight[0x37] = 0; // Redstone wire 102 | stopLight[0x40] = 0; // Wooden door 103 | stopLight[0x41] = 0; // Ladder 104 | stopLight[0x42] = 0; // Minecart track 105 | stopLight[0x47] = 0; // Iron door 106 | stopLight[0x4b] = 0; // Redstone Torch (Off) 107 | stopLight[0x4C] = 0; // Redstone Torch (On) 108 | stopLight[0x4e] = 0; // Snow 109 | stopLight[0x4f] = 3; // Ice 110 | stopLight[0x55] = 0; // Fence 111 | stopLight[0x5A] = 0; // Portal 112 | stopLight[0x5B] = 0; // Jack-O-Lantern 113 | stopLight[BLOCK_SIGN_POST] = 0; // Sign post 114 | stopLight[BLOCK_WALL_SIGN] = 0; // Wall sign 115 | } 116 | 117 | ~Map() 118 | { 119 | // Free all memory 120 | for(std::map::const_iterator it = maps.begin(); it != maps.end(); it = maps.begin()) 121 | releaseMap(maps[it->first].x, maps[it->first].z); 122 | 123 | //Free item memory 124 | for(std::map::const_iterator it = items.begin(); it != items.end(); ++it) 125 | delete items[it->first]; 126 | 127 | items.clear(); 128 | std::string infile = mapDirectory+"/level.dat"; 129 | 130 | NBT_Value *root = NBT_Value::LoadFromFile(infile); 131 | if(root != NULL) 132 | { 133 | NBT_Value &data = *((*root)["Data"]); 134 | 135 | //Get time from the map 136 | *data["Time"] = mapTime; 137 | 138 | root->SaveToFile(infile); 139 | 140 | delete root; 141 | } 142 | 143 | 144 | } 145 | 146 | public: 147 | 148 | std::string mapDirectory; 149 | 150 | // Map spawn position 151 | vec spawnPos; 152 | 153 | // How blocks affect light 154 | int stopLight[256]; 155 | 156 | // Blocks that emit light 157 | int emitLight[256]; 158 | 159 | // Store all maps here 160 | std::map maps; 161 | 162 | // Store the time map chunk has been last used 163 | std::map mapLastused; 164 | 165 | // Store if map has been modified 166 | std::map mapChanged; 167 | 168 | // Store item pointers for each chunk 169 | std::map > mapItems; 170 | 171 | //All spawned items on map 172 | std::map items; 173 | 174 | void posToId(int x, int z, uint32 *id); 175 | void idToPos(uint32 id, int *x, int *z); 176 | 177 | void initMap(); 178 | void freeMap(); 179 | void sendToUser(User *user, int x, int z); 180 | 181 | //Time in the map 182 | sint64 mapTime; 183 | 184 | // Map seed 185 | sint64 mapSeed; 186 | 187 | // Get pointer to struct 188 | sChunk *getMapData(int x, int z, bool generate = true); 189 | 190 | // Load map chunk 191 | bool loadMap(int x, int z, bool generate = true); 192 | 193 | // Save map chunk to disc 194 | bool saveMap(int x, int z); 195 | 196 | // Save whole map to disc (/save command) 197 | bool saveWholeMap(); 198 | 199 | // Generate light maps for chunk 200 | bool generateLight(int x, int z); 201 | bool generateLight(int x, int z, sChunk *chunk); 202 | 203 | // Release/save map chunk 204 | bool releaseMap(int x, int z); 205 | 206 | // Light get/set 207 | bool getLight(int x, int y, int z, uint8 *blocklight, uint8 *skylight); 208 | bool getLight(int x, int y, int z, uint8 *blocklight, uint8 *skylight, sChunk *chunk); 209 | bool setLight(int x, int y, int z, int blocklight, int skylight, int setLight); 210 | bool setLight(int x, int y, int z, int blocklight, int skylight, int setLight, sChunk *chunk); 211 | bool spreadLight(int x, int y, int z, int skylight, int blocklight); 212 | bool spreadLight(int x, int y, int z, int skylight, int blocklight, sChunk *chunk); 213 | 214 | // Block value/meta get/set 215 | bool getBlock(int x, int y, int z, uint8 *type, uint8 *meta, bool generate = true); 216 | bool getBlock(int x, int y, int z, uint8 *type, uint8 *meta, bool generate, sChunk *chunk); 217 | bool getBlock(vec pos, uint8 *type, uint8 *meta) 218 | { 219 | return getBlock(pos.x(), pos.y(), pos.z(), type, meta); 220 | } 221 | bool setBlock(int x, int y, int z, char type, char meta); 222 | bool setBlock(vec pos, char type, char meta) 223 | { 224 | return setBlock(pos.x(), pos.y(), pos.z(), type, meta); 225 | } 226 | 227 | bool sendBlockChange(int x, int y, int z, char type, char meta); 228 | bool sendBlockChange(vec pos, char type, char meta) 229 | { 230 | return sendBlockChange(pos.x(), pos.y(), pos.z(), type, meta); 231 | } 232 | 233 | bool sendPickupSpawn(spawnedItem item); 234 | void createPickupSpawn(int x, int y, int z, int type, int count); 235 | 236 | void setComplexEntity(sint32 x, sint32 y, sint32 z, NBT_Value *entity); 237 | 238 | static Map &get(); 239 | }; 240 | 241 | #endif 242 | -------------------------------------------------------------------------------- /src/constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _CONSTANTS_H 29 | #define _CONSTANTS_H 30 | 31 | #include 32 | #include "tools.h" 33 | 34 | // 35 | // Mineserver constants 36 | // 37 | 38 | //Player digging status 39 | enum 40 | { 41 | BLOCK_STATUS_STARTED_DIGGING, 42 | BLOCK_STATUS_DIGGING, 43 | BLOCK_STATUS_STOPPED_DIGGING, 44 | BLOCK_STATUS_BLOCK_BROKEN 45 | }; 46 | 47 | // Chat colors 48 | #define COLOR_BLACK std::string("§0") 49 | #define COLOR_DARK_BLUE std::string("§1") 50 | #define COLOR_DARK_GREEN std::string("§2") 51 | #define COLOR_DARK_CYAN std::string("§3") 52 | #define COLOR_DARK_RED std::string("§4") 53 | #define COLOR_DARK_MAGENTA std::string("§5") 54 | #define COLOR_DARK_ORANGE std::string("§6") 55 | #define COLOR_GREY std::string("§7") 56 | #define COLOR_DARK_GREY std::string("§8") 57 | #define COLOR_BLUE std::string("§9") 58 | #define COLOR_GREEN std::string("§a") 59 | #define COLOR_CYAN std::string("§b") 60 | #define COLOR_RED std::string("§c") 61 | #define COLOR_MAGENTA std::string("§d") 62 | #define COLOR_YELLOW std::string("§e") 63 | #define COLOR_WHITE std::string("§f") 64 | 65 | // Direction 66 | enum Direction 67 | { 68 | BLOCK_BOTTOM, BLOCK_NORTH, BLOCK_SOUTH, BLOCK_EAST, BLOCK_WEST, BLOCK_TOP 69 | }; 70 | 71 | // Blocks 72 | enum Block 73 | { 74 | BLOCK_AIR, BLOCK_STONE, BLOCK_GRASS, BLOCK_DIRT, BLOCK_COBBLESTONE, BLOCK_WOOD, 75 | BLOCK_SAPLING, BLOCK_BEDROCK, BLOCK_WATER, BLOCK_STATIONARY_WATER, BLOCK_LAVA, 76 | BLOCK_STATIONARY_LAVA, BLOCK_SAND, BLOCK_GRAVEL, BLOCK_GOLD_ORE, BLOCK_IRON_ORE, 77 | BLOCK_COAL_ORE, BLOCK_LOG, BLOCK_LEAVES, BLOCK_SPONGE, BLOCK_GLASS, BLOCK_RED_CLOTH, 78 | BLOCK_ORANGE_CLOTH, BLOCK_YELLOW_CLOTH, BLOCK_LIME_CLOTH, BLOCK_GREEN_CLOTH, 79 | BLOCK_AQUA_GREEN_CLOTH, BLOCK_CYAN_CLOTH, BLOCK_BLUE_CLOTH, BLOCK_PURPLE_CLOTH, 80 | BLOCK_INDIGO_CLOTH, BLOCK_VIOLET_CLOTH, BLOCK_MAGENTA_CLOTH, BLOCK_PINK_CLOTH, 81 | BLOCK_BLACK_CLOTH, BLOCK_GRAY_CLOTH, BLOCK_WHITE_CLOTH, BLOCK_YELLOW_FLOWER, 82 | BLOCK_RED_ROSE, BLOCK_BROWN_MUSHROOM, BLOCK_RED_MUSHROOM, BLOCK_GOLD_BLOCK, 83 | BLOCK_IRON_BLOCK, BLOCK_DOUBLE_STEP, BLOCK_STEP, BLOCK_BRICK, BLOCK_TNT, 84 | BLOCK_BOOKSHELF, BLOCK_MOSSY_COBBLESTONE, BLOCK_OBSIDIAN, BLOCK_TORCH, BLOCK_FIRE, 85 | BLOCK_MOB_SPAWNER, BLOCK_WOODEN_STAIRS, BLOCK_CHEST, BLOCK_REDSTONE_WIRE, 86 | BLOCK_DIAMOND_ORE, BLOCK_DIAMOND_BLOCK, BLOCK_WORKBENCH, BLOCK_CROPS, BLOCK_SOIL, 87 | BLOCK_FURNACE, BLOCK_BURNING_FURNACE, BLOCK_SIGN_POST, BLOCK_WOODEN_DOOR, 88 | BLOCK_LADDER, BLOCK_MINECART_TRACKS, BLOCK_COBBLESTONE_STAIRS, BLOCK_WALL_SIGN, 89 | BLOCK_LEVER, BLOCK_STONE_PRESSURE_PLATE, BLOCK_IRON_DOOR, BLOCK_WOODEN_PRESSURE_PLATE, 90 | BLOCK_REDSTONE_ORE, BLOCK_GLOWING_REDSTONE_ORE, BLOCK_REDSTONE_TORCH_OFF, 91 | BLOCK_REDSTONE_TORCH_ON, BLOCK_STONE_BUTTON, BLOCK_SNOW, BLOCK_ICE, BLOCK_SNOW_BLOCK, 92 | BLOCK_CACTUS, BLOCK_CLAY, BLOCK_REED, BLOCK_JUKEBOX, BLOCK_FENCE, BLOCK_PUMPKIN, 93 | BLOCK_NETHERSTONE, BLOCK_SLOW_SAND, BLOCK_LIGHTSTONE, BLOCK_PORTAL, BLOCK_JACK_O_LANTERN 94 | }; 95 | 96 | // Items 97 | enum 98 | { 99 | ITEM_IRON_SPADE = 256, ITEM_IRON_PICKAXE, ITEM_IRON_AXE, ITEM_FLINT_AND_STEEL, ITEM_APPLE, 100 | ITEM_BOW, ITEM_ARROW, ITEM_COAL, ITEM_DIAMOND, ITEM_IRON_INGOT, ITEM_GOLD_INGOT, ITEM_IRON_SWORD, 101 | ITEM_WOODEN_SWORD, ITEM_WOODEN_SPADE, ITEM_WOODEN_PICKAXE, ITEM_WOODEN_AXE, ITEM_STONE_SWORD, 102 | ITEM_STONE_SPADE, ITEM_STONE_PICKAXE, ITEM_STONE_AXE, ITEM_DIAMOND_SWORD, 103 | ITEM_DIAMOND_SPADE, ITEM_DIAMOND_PICKAXE, ITEM_DIAMOND_AXE, ITEM_STICK, ITEM_BOWL, 104 | ITEM_MUSHROOM_SOUP, ITEM_GOLD_SWORD, ITEM_GOLD_SPADE, ITEM_GOLD_PICKAXE, ITEM_GOLD_AXE, 105 | ITEM_STRING, ITEM_FEATHER, ITEM_GUNPOWDER, ITEM_WOODEN_HOE, ITEM_STONE_HOE, 106 | ITEM_IRON_HOE, ITEM_DIAMOND_HOE, ITEM_GOLD_HOE, ITEM_SEEDS, ITEM_WHEAT, ITEM_BREAD, 107 | ITEM_LEATHER_HELMET, ITEM_LEATHER_CHESTPLATE, ITEM_LEATHER_LEGGINGS, ITEM_LEATHER_BOOTS, 108 | ITEM_CHAINMAIL_HELMET, ITEM_CHAINMAIL_CHESTPLATE, ITEM_CHAINMAIL_LEGGINGS, 109 | ITEM_CHAINMAIL_BOOTS, ITEM_IRON_HELMET, ITEM_IRON_CHESTPLATE, ITEM_IRON_LEGGINGS, 110 | ITEM_IRON_BOOTS, ITEM_DIAMOND_HELMET, ITEM_DIAMOND_CHESTPLATE, ITEM_DIAMOND_LEGGINGS, 111 | ITEM_DIAMOND_BOOTS, ITEM_GOLD_HELMET, ITEM_GOLD_CHESTPLATE, ITEM_GOLD_LEGGINS, 112 | ITEM_GOLD_BOOTS, ITEM_FLINT, ITEM_PORK, ITEM_GRILLED_PORK, ITEM_PAINTINGS, 113 | ITEM_GOLDEN_APPLE, ITEM_SIGN, ITEM_WOODEN_DOOR, ITEM_BUCKET, ITEM_WATER_BUCKET, 114 | ITEM_LAVA_BUCKET, ITEM_MINECART, ITEM_SADDLE, ITEM_IRON_DOOR, ITEM_REDSTONE, 115 | ITEM_SNOWBALL, ITEM_BOAT, ITEM_LEATHER, ITEM_MILK_BUCKET, ITEM_CLAY_BRICK, 116 | ITEM_CLAY_BALLS, ITEM_REED, ITEM_PAPER, ITEM_BOOK, ITEM_SLIME_BALL, 117 | ITEM_STORAGE_MINECART, ITEM_POWERED_MINECART, ITEM_EGG, ITEM_COMPASS, ITEM_FISHING_ROD, 118 | ITEM_WATCH, ITEM_LIGHTSTONE_DUST, ITEM_RAW_FISH, ITEM_COOKED_FISH 119 | }; 120 | 121 | // Records 122 | enum 123 | { 124 | ITEM_GOLD_RECORD = 2256, ITEM_GREEN_RECORD 125 | }; 126 | 127 | const std::string VERSION = "0.1.12 (Alpha)"; 128 | 129 | const char COMMENTPREFIX = '#'; 130 | 131 | // Adminfile 132 | const std::string ADMIN_FILE = "admin.txt"; 133 | const std::string ADMIN_CONTENT = "# This is default admin file. Add nicknames here for admins, one per line."; 134 | 135 | // Banned users file 136 | const std::string BANNEDFILE = "banned.txt"; 137 | const std::string DEFAULTBANNEDFILE = 138 | "# This is default banned users file. Write nicks here one for each line"; 139 | 140 | // Whitelist users file 141 | const std::string WHITELISTFILE = "whitelist.txt"; 142 | const std::string DEFAULTWHITELISTFILE = 143 | "# This is default whitelist file. Write nicks to be whitelisted here one for each line"; 144 | 145 | // Motdfile 146 | const std::string MOTD_FILE = "motd.txt"; 147 | const std::string MOTD_CONTENT = "This is the default motd! Please edit motd.txt to change this message."; 148 | 149 | // Configuration 150 | const std::string CONFIG_FILE = "config.cfg"; 151 | 152 | // Item aliases 153 | const std::string ITEMS_FILE = "item_alias.cfg"; 154 | 155 | // Server rules 156 | const std::string RULES_FILE = "rules.txt"; 157 | const std::string RULES_CONTENT = "This is the default rules file. Please edit rules.txt to change this message."; 158 | 159 | // Default configuration 160 | extern std::map defaultConf; 161 | 162 | // 163 | // Blocks that drop special things! 164 | // 165 | struct Drop 166 | { 167 | uint16 item_id; 168 | sint32 probability; 169 | uint8 count; 170 | bool exclusive; 171 | 172 | Drop() {} 173 | 174 | Drop(uint16 item_id, uint32 probability, uint8 count, bool exclusive) 175 | { 176 | this->item_id = item_id; 177 | this->probability = probability; 178 | this->count = count; 179 | this->exclusive = exclusive; 180 | } 181 | }; 182 | 183 | extern std::map BLOCKDROPS; 184 | 185 | // Chat prefixes 186 | const char SERVERMSGPREFIX = '%'; 187 | const char CHATCMDPREFIX = '/'; 188 | const char ADMINCHATPREFIX = '&'; 189 | 190 | void initConstants(); 191 | 192 | const int ALLOCATE_NBTFILE = 200000; 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /src/chat.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #ifdef WIN32 37 | #include 38 | #else 39 | #include 40 | #include 41 | #endif 42 | 43 | #include "logger.h" 44 | #include "constants.h" 45 | 46 | #include "tools.h" 47 | #include "map.h" 48 | #include "user.h" 49 | #include "chat.h" 50 | #include "config.h" 51 | #include "physics.h" 52 | 53 | 54 | Chat &Chat::get() 55 | { 56 | static Chat instance; 57 | return instance; 58 | } 59 | 60 | Chat::Chat() 61 | { 62 | registerStandardCommands(); 63 | } 64 | 65 | void Chat::registerCommand(std::string name, ChatCommand command, bool adminOnly) 66 | { 67 | if(adminOnly) 68 | adminCommands[name] = command; 69 | else 70 | userCommands[name] = command; 71 | } 72 | 73 | bool Chat::checkMotd(std::string motdFile) 74 | { 75 | // 76 | // Create motdfile is it doesn't exist 77 | // 78 | std::ifstream ifs(motdFile.c_str()); 79 | 80 | // If file does not exist 81 | if(ifs.fail()) 82 | { 83 | std::cout << "> Warning: " << motdFile << " not found. Creating..." << std::endl; 84 | 85 | std::ofstream motdofs(motdFile.c_str()); 86 | motdofs << MOTD_CONTENT << std::endl; 87 | motdofs.close(); 88 | } 89 | 90 | ifs.close(); 91 | 92 | return true; 93 | } 94 | 95 | bool Chat::loadAdmins(std::string adminFile) 96 | { 97 | // Clear current admin-vector 98 | admins.clear(); 99 | 100 | // Read admins to deque 101 | std::ifstream ifs(adminFile.c_str()); 102 | 103 | // If file does not exist 104 | if(ifs.fail()) 105 | { 106 | std::cout << "> Warning: " << adminFile << " not found. Creating..." << std::endl; 107 | 108 | std::ofstream adminofs(adminFile.c_str()); 109 | adminofs << ADMIN_CONTENT << std::endl; 110 | adminofs.close(); 111 | 112 | return true; 113 | } 114 | 115 | std::string temp; 116 | while(getline(ifs, temp)) 117 | { 118 | // If not commentline 119 | if(temp[0] != COMMENTPREFIX) 120 | admins.push_back(temp); 121 | } 122 | ifs.close(); 123 | 124 | std::cout << "Loaded admins from " << adminFile << std::endl; 125 | 126 | return true; 127 | } 128 | 129 | bool Chat::loadBanned(std::string bannedFile) 130 | { 131 | // Clear current banned-vector 132 | banned.clear(); 133 | 134 | // Read banned to deque 135 | std::ifstream ifs(bannedFile.c_str()); 136 | 137 | // If file does not exist 138 | if(ifs.fail()) 139 | { 140 | std::cout << "> Warning: " << bannedFile << " not found. Creating..." << std::endl; 141 | 142 | std::ofstream bannedofs(bannedFile.c_str()); 143 | bannedofs << DEFAULTBANNEDFILE << std::endl; 144 | bannedofs.close(); 145 | 146 | return true; 147 | } 148 | 149 | std::string temp; 150 | while(getline(ifs, temp)) 151 | { 152 | // If not commentline 153 | if(temp[0] != COMMENTPREFIX) 154 | banned.push_back(temp); 155 | } 156 | ifs.close(); 157 | 158 | std::cout << "Loaded banned users from " << bannedFile << std::endl; 159 | 160 | return true; 161 | } 162 | 163 | bool Chat::loadWhitelist(std::string whitelistFile) 164 | { 165 | // Clear current whitelist-vector 166 | whitelist.clear(); 167 | 168 | // Read whitelist to deque 169 | std::ifstream ifs(whitelistFile.c_str()); 170 | 171 | // If file does not exist 172 | if(ifs.fail()) 173 | { 174 | std::cout << "> Warning: " << whitelistFile << " not found. Creating..." << std::endl; 175 | 176 | std::ofstream whitelistofs(whitelistFile.c_str()); 177 | whitelistofs << DEFAULTWHITELISTFILE << std::endl; 178 | whitelistofs.close(); 179 | 180 | return true; 181 | } 182 | 183 | std::string temp; 184 | while(getline(ifs, temp)) 185 | { 186 | // If not commentline 187 | if(temp[0] != COMMENTPREFIX) 188 | whitelist.push_back(temp); 189 | } 190 | ifs.close(); 191 | 192 | std::cout << "Loaded whitelisted users from " << whitelistFile << std::endl; 193 | 194 | return true; 195 | } 196 | 197 | bool Chat::sendUserlist(User *user) 198 | { 199 | this->sendMsg(user, COLOR_BLUE + "[ Players online ]", USER); 200 | 201 | for(unsigned int i = 0; i < Users.size(); i++) 202 | { 203 | this->sendMsg(user, "> " + Users[i]->nick, USER); 204 | } 205 | 206 | return true; 207 | } 208 | 209 | std::deque Chat::parseCmd(std::string cmd) 210 | { 211 | int del; 212 | std::deque temp; 213 | 214 | while(cmd.length() > 0) 215 | { 216 | while(cmd[0] == ' ') 217 | cmd = cmd.substr(1); 218 | 219 | del = cmd.find(' '); 220 | 221 | if(del > -1) 222 | { 223 | temp.push_back(cmd.substr(0, del)); 224 | cmd = cmd.substr(del+1); 225 | } 226 | else 227 | { 228 | temp.push_back(cmd); 229 | break; 230 | } 231 | } 232 | 233 | if(temp.empty()) 234 | temp.push_back("empty"); 235 | 236 | return temp; 237 | } 238 | 239 | bool Chat::handleMsg(User *user, std::string msg) 240 | { 241 | // Timestamp 242 | time_t rawTime = time(NULL); 243 | 244 | struct tm *Tm = localtime(&rawTime); 245 | 246 | std::string timeStamp (asctime(Tm)); 247 | timeStamp = timeStamp.substr(11, 5); 248 | 249 | // 250 | // Chat commands 251 | // 252 | 253 | // Servermsg (Admin-only) 254 | if(msg[0] == SERVERMSGPREFIX && user->admin) 255 | { 256 | // Decorate server message 257 | msg = COLOR_RED + "[!] " + COLOR_GREEN + msg.substr(1); 258 | this->sendMsg(user, msg, ALL); 259 | } 260 | 261 | // Adminchat 262 | else if(msg[0] == ADMINCHATPREFIX && user->admin) 263 | { 264 | msg = timeStamp + " @@ <"+ COLOR_DARK_MAGENTA + user->nick + COLOR_WHITE + "> " + msg.substr(1); 265 | this->sendMsg(user, msg, ADMINS); 266 | } 267 | 268 | // Command 269 | else if(msg[0] == CHATCMDPREFIX) 270 | { 271 | std::deque cmd = this->parseCmd(msg.substr(1)); 272 | 273 | std::string command = cmd[0]; 274 | cmd.pop_front(); 275 | 276 | // User commands 277 | CommandList::iterator iter; 278 | if((iter = userCommands.find(command)) != userCommands.end()) 279 | iter->second(user, command, cmd); 280 | else if(user->admin && (iter = adminCommands.find(command)) != adminCommands.end()) 281 | iter->second(user, command, cmd); 282 | } 283 | // Normal message 284 | else 285 | { 286 | if(user->admin) 287 | msg = timeStamp + " <"+ COLOR_DARK_MAGENTA + user->nick + COLOR_WHITE + "> " + msg; 288 | else 289 | msg = timeStamp + " <"+ user->nick + "> " + msg; 290 | 291 | LOG(msg); 292 | 293 | this->sendMsg(user, msg, ALL); 294 | } 295 | 296 | return true; 297 | } 298 | 299 | bool Chat::sendMsg(User *user, std::string msg, MessageTarget action) 300 | { 301 | size_t tmpArrayLen = msg.size()+3; 302 | uint8 *tmpArray = new uint8[tmpArrayLen]; 303 | 304 | tmpArray[0] = 0x03; 305 | tmpArray[1] = 0; 306 | tmpArray[2] = msg.size()&0xff; 307 | 308 | for(unsigned int i = 0; i < msg.size(); i++) 309 | tmpArray[i+3] = msg[i]; 310 | 311 | switch(action) 312 | { 313 | case ALL: 314 | user->sendAll(tmpArray, tmpArrayLen); 315 | break; 316 | 317 | case USER: 318 | user->buffer.addToWrite(tmpArray, tmpArrayLen); 319 | break; 320 | 321 | case ADMINS: 322 | user->sendAdmins(tmpArray, tmpArrayLen); 323 | break; 324 | 325 | case OTHERS: 326 | user->sendOthers(tmpArray, tmpArrayLen); 327 | break; 328 | } 329 | 330 | delete[] tmpArray; 331 | 332 | return true; 333 | } 334 | -------------------------------------------------------------------------------- /src/mineserver.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #ifdef WIN32 30 | #include 31 | #include 32 | #else 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #endif 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | #include "constants.h" 53 | #include "mineserver.h" 54 | 55 | #include "logger.h" 56 | 57 | #include "sockets.h" 58 | #include "tools.h" 59 | #include "map.h" 60 | #include "user.h" 61 | #include "chat.h" 62 | #include "mapgen.h" 63 | #include "config.h" 64 | #include "nbt.h" 65 | #include "packets.h" 66 | #include "physics.h" 67 | 68 | #ifdef WIN32 69 | static bool quit = false; 70 | #endif 71 | 72 | int setnonblock(int fd) 73 | { 74 | #ifdef WIN32 75 | u_long iMode = 1; 76 | ioctlsocket(fd, FIONBIO, &iMode); 77 | #else 78 | int flags; 79 | 80 | flags = fcntl(fd, F_GETFL); 81 | flags |= O_NONBLOCK; 82 | fcntl(fd, F_SETFL, flags); 83 | #endif 84 | 85 | return 1; 86 | } 87 | 88 | //Handle signals 89 | void sighandler(int sig_num) 90 | { 91 | Mineserver::Get().Stop(); 92 | } 93 | 94 | int main(int argc, char *argv[]) 95 | { 96 | signal(SIGTERM, sighandler); 97 | signal(SIGINT, sighandler); 98 | 99 | return Mineserver::Get().Run(argc, argv); 100 | } 101 | 102 | Mineserver::Mineserver() 103 | { 104 | } 105 | 106 | event_base *Mineserver::GetEventBase() 107 | { 108 | return m_eventBase; 109 | } 110 | 111 | int Mineserver::Run(int argc, char *argv[]) 112 | { 113 | uint32 starttime = (uint32)time(0); 114 | uint32 tick = (uint32)time(0); 115 | 116 | initConstants(); 117 | 118 | std::string file_config; 119 | file_config.assign(CONFIG_FILE); 120 | std::string file_admin; 121 | file_admin.assign(ADMIN_FILE); 122 | std::string file_items; 123 | file_items.assign(ITEMS_FILE); 124 | std::string file_motd; 125 | file_motd.assign(MOTD_FILE); 126 | std::string file_rules; 127 | file_rules.assign(RULES_FILE); 128 | 129 | if (argc > 1) 130 | file_config.assign(argv[1]); 131 | 132 | // Initialize conf 133 | Conf::get().load(file_config); 134 | 135 | // Load item aliases 136 | Conf::get().load(file_items); 137 | 138 | // Load admins 139 | Chat::get().loadAdmins(file_admin); 140 | // Load MOTD 141 | Chat::get().checkMotd(file_motd); 142 | 143 | Chat::get().loadBanned(BANNEDFILE); 144 | Chat::get().loadWhitelist(WHITELISTFILE); 145 | 146 | // Set physics enable state according to config 147 | Physics::get().enabled = (Conf::get().bValue("liquid_physics")); 148 | 149 | // Initialize map 150 | Map::get().initMap(); 151 | 152 | // Initialize packethandler 153 | PacketHandler::get().initPackets(); 154 | 155 | // Load ip from config 156 | std::string ip = Conf::get().sValue("ip"); 157 | 158 | // Load port from config 159 | int port = Conf::get().iValue("port"); 160 | 161 | #ifdef WIN32 162 | WSADATA wsaData; 163 | int iResult; 164 | // Initialize Winsock 165 | iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 166 | if(iResult != 0) 167 | { 168 | printf("WSAStartup failed with error: %d\n", iResult); 169 | return EXIT_FAILURE; 170 | } 171 | #endif 172 | 173 | struct sockaddr_in addresslisten; 174 | int reuse = 1; 175 | 176 | m_eventBase = (event_base *)event_init(); 177 | #ifdef WIN32 178 | m_socketlisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 179 | #else 180 | m_socketlisten = socket(AF_INET, SOCK_STREAM, 0); 181 | #endif 182 | 183 | if(m_socketlisten < 0) 184 | { 185 | std::cerr << "Failed to create listen socket" << std::endl; 186 | return 1; 187 | } 188 | 189 | memset(&addresslisten, 0, sizeof(addresslisten)); 190 | 191 | addresslisten.sin_family = AF_INET; 192 | addresslisten.sin_addr.s_addr = inet_addr(ip.c_str()); 193 | addresslisten.sin_port = htons(port); 194 | 195 | setsockopt(m_socketlisten, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)); 196 | 197 | //Bind to port 198 | if(bind(m_socketlisten, (struct sockaddr *)&addresslisten, sizeof(addresslisten)) < 0) 199 | { 200 | std::cerr << "Failed to bind" << std::endl; 201 | return 1; 202 | } 203 | 204 | if(listen(m_socketlisten, 5) < 0) 205 | { 206 | std::cerr << "Failed to listen to socket" << std::endl; 207 | return 1; 208 | } 209 | 210 | 211 | setnonblock(m_socketlisten); 212 | event_set(&m_listenEvent, m_socketlisten, EV_WRITE|EV_READ|EV_PERSIST, accept_callback, NULL); 213 | event_add(&m_listenEvent, NULL); 214 | 215 | std::cout << std::endl<< 216 | " _____ .__ "<< 217 | std::endl<< 218 | " / \\ |__| ____ ____ ______ ______________ __ ___________ "<< 219 | std::endl<< 220 | " / \\ / \\| |/ \\_/ __ \\ / ___// __ \\_ __ \\ \\/ // __ \\_ __ \\"<< 221 | std::endl<< 222 | "/ Y \\ | | \\ ___/ \\___ \\\\ ___/| | \\/\\ /\\ ___/| | \\/"<< 223 | std::endl<< 224 | "\\____|__ /__|___| /\\___ >____ >\\___ >__| \\_/ \\___ >__| "<< 225 | std::endl<< 226 | " \\/ \\/ \\/ \\/ \\/ \\/ "<< 227 | std::endl<< 228 | "Version " << VERSION <<" by Fador & Nredor"<< 229 | std::endl << std::endl; 230 | 231 | if(ip == "0.0.0.0") 232 | { 233 | std::cout << "Listening on port " << port << std::endl; 234 | // Print all local IPs 235 | char name[255]; 236 | gethostname ( name, sizeof(name)); 237 | struct hostent *hostinfo = gethostbyname(name); 238 | std::cout << "Server IP(s): "; 239 | int ipIndex = 0; 240 | while(hostinfo->h_addr_list[ipIndex]) { 241 | if(ipIndex > 0) { std::cout << ", "; } 242 | char *ip = inet_ntoa(*(struct in_addr *)hostinfo->h_addr_list[ipIndex++]); 243 | std::cout << ip; 244 | } 245 | std::cout << std::endl; 246 | } 247 | else 248 | { 249 | std::cout << "Listening on " << ip << ":" << port << std::endl; 250 | } 251 | 252 | timeval loopTime; 253 | loopTime.tv_sec = 0; 254 | loopTime.tv_usec = 200000; //200ms 255 | 256 | m_running=true; 257 | event_base_loopexit(m_eventBase, &loopTime); 258 | while(m_running && event_base_loop(m_eventBase, 0) == 0) 259 | { 260 | if(time(0)-starttime > 10) 261 | { 262 | starttime = (uint32)time(0); 263 | std::cout << "Currently " << Users.size() << " users in!" << std::endl; 264 | 265 | //If users, ping them 266 | if(Users.size() > 0) 267 | { 268 | //0x00 package 269 | uint8 data = 0; 270 | Users[0]->sendAll(&data, 1); 271 | 272 | //Send server time 273 | Packet pkt; 274 | pkt << (sint8)PACKET_TIME_UPDATE << (sint64)Map::get().mapTime; 275 | Users[0]->sendAll((uint8*)pkt.getWrite(), pkt.getWriteLen()); 276 | } 277 | 278 | //Try to load release time from config 279 | int map_release_time = Conf::get().iValue("map_release_time"); 280 | 281 | //Release chunks not used in seconds 282 | std::vector toRelease; 283 | for(std::map::const_iterator it = Map::get().mapLastused.begin(); 284 | it != Map::get().mapLastused.end(); 285 | ++it) 286 | { 287 | if(Map::get().mapLastused[it->first] <= time(0)-map_release_time) 288 | toRelease.push_back(it->first); 289 | } 290 | 291 | int x_temp, z_temp; 292 | for(unsigned i = 0; i < toRelease.size(); i++) 293 | { 294 | Map::get().idToPos(toRelease[i], &x_temp, &z_temp); 295 | Map::get().releaseMap(x_temp, z_temp); 296 | } 297 | } 298 | 299 | //Every second 300 | if(time(0)-tick > 0) 301 | { 302 | tick = (uint32)time(0); 303 | //Loop users 304 | for(unsigned int i = 0; i < Users.size(); i++) 305 | { 306 | Users[i]->pushMap(); 307 | Users[i]->popMap(); 308 | } 309 | Map::get().mapTime+=20; 310 | if(Map::get().mapTime>=24000) Map::get().mapTime=0; 311 | } 312 | 313 | //Physics simulation every 200ms 314 | Physics::get().update(); 315 | 316 | event_base_loopexit(m_eventBase, &loopTime); 317 | } 318 | 319 | Map::get().freeMap(); 320 | 321 | #ifdef WIN32 322 | closesocket(m_socketlisten); 323 | #else 324 | close(m_socketlisten); 325 | #endif 326 | 327 | return EXIT_SUCCESS; 328 | } 329 | 330 | bool Mineserver::Stop() 331 | { 332 | m_running=false; 333 | 334 | return true; 335 | }; 336 | -------------------------------------------------------------------------------- /src/physics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifdef WIN32 28 | #include 29 | #include 30 | #include 31 | typedef int socklen_t; 32 | #else 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #endif 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | #include "logger.h" 55 | #include "constants.h" 56 | #include "config.h" 57 | #include "user.h" 58 | #include "map.h" 59 | #include "vec.h" 60 | 61 | #include "physics.h" 62 | 63 | namespace 64 | { 65 | 66 | bool isWaterBlock(int id) 67 | { 68 | return id == BLOCK_WATER || 69 | id == BLOCK_STATIONARY_WATER; 70 | } 71 | 72 | bool isLavaBlock(int id) 73 | { 74 | return id == BLOCK_LAVA || 75 | id == BLOCK_STATIONARY_LAVA; 76 | } 77 | 78 | bool isLiquidBlock(int id) 79 | { 80 | return isWaterBlock(id) || isLavaBlock(id); 81 | } 82 | 83 | bool mayFallThrough(int id) 84 | { 85 | return id == BLOCK_AIR || 86 | id == BLOCK_WATER || 87 | id == BLOCK_STATIONARY_WATER || 88 | id == BLOCK_SNOW; 89 | } 90 | 91 | } 92 | 93 | Physics &Physics::get() 94 | { 95 | static Physics instance; 96 | return instance; 97 | } 98 | 99 | // Physics loop 100 | bool Physics::update() 101 | { 102 | if(!enabled) 103 | return true; 104 | 105 | // Check if needs to be updated 106 | if(simList.empty()) 107 | return true; 108 | 109 | clock_t starttime = clock(); 110 | 111 | std::vector toRemove; 112 | std::vector toAdd; 113 | 114 | std::cout << "Simulating " << simList.size() << " items!" << std::endl; 115 | uint32 listSize = simList.size(); 116 | // Iterate each simulation 117 | for(uint32 simIt = 0; simIt < listSize; simIt++) 118 | { 119 | vec pos = simList[simIt].blocks[0].pos; 120 | // Blocks 121 | uint8 block, meta; 122 | Map::get().getBlock(pos, &block, &meta); 123 | 124 | simList[simIt].blocks[0].id = block; 125 | simList[simIt].blocks[0].meta = meta; 126 | 127 | //Water simulation 128 | if(simList[simIt].type == TYPE_WATER) 129 | { 130 | if(isWaterBlock(block)) 131 | { 132 | 133 | sint32 it = 0; 134 | //for(sint32 it=simList[simIt].blocks.size()-1; it>=0; it--) 135 | { 136 | 137 | bool havesource = false; 138 | 139 | //Search for water source if this is not the source 140 | if(simList[simIt].blocks[it].id != BLOCK_STATIONARY_WATER) 141 | { 142 | for(int i = 0; i < 6; i++) 143 | { 144 | vec local(pos); 145 | switch(i) 146 | { 147 | case 0: local += vec( 0, 1, 0); break; //y++ 148 | case 1: local += vec( 1, 0, 0); break; //x++ 149 | case 2: local += vec(-1, 0, 0); break; //x-- 150 | case 3: local += vec( 0, 0, 1); break; //z++ 151 | case 4: local += vec( 0, 0, -1); break; //z-- 152 | case 5: local += vec( 0, -1, 0); break; //y-- 153 | } 154 | 155 | //Search neighboring water blocks for source current 156 | if(Map::get().getBlock(local, &block, &meta) && 157 | isWaterBlock(block)) 158 | { 159 | //is this the source block 160 | if(i != 5 && 161 | (block == BLOCK_STATIONARY_WATER || (meta&0x07) < 162 | (simList[simIt].blocks[it].meta&0x07) || i == 0)) 163 | havesource = true; 164 | //Else we have to search for source to this block also 165 | else if(i == 5 || (meta&0x07) > (simList[simIt].blocks[it].meta&0x07)) 166 | toAdd.push_back(local); 167 | } 168 | } 169 | } 170 | //Stationary water block is the source 171 | else 172 | havesource = true; 173 | 174 | //If no source, dry block away 175 | if(!havesource) 176 | { 177 | //This block will change so add surrounding blocks to simulation 178 | for(uint32 i = 0; i < toAdd.size(); i++) 179 | { 180 | addSimulation(toAdd[i]); 181 | } 182 | //If not dried out yet 183 | if(!(simList[simIt].blocks[it].meta&0x8) && (simList[simIt].blocks[it].meta&0x07) < M7) 184 | { 185 | // Set new water level 186 | block = BLOCK_WATER; 187 | meta = simList[simIt].blocks[it].meta+1; 188 | Map::get().setBlock(pos, block, meta); 189 | Map::get().sendBlockChange(pos, block, meta); 190 | 191 | toRemove.push_back(simIt); 192 | addSimulation(pos); 193 | // Update simulation meta information 194 | //simList[simIt].blocks[it].meta = meta; 195 | } 196 | //Else this block has dried out 197 | else 198 | { 199 | //Clear and remove simulation 200 | Map::get().setBlock(pos, BLOCK_AIR, 0); 201 | Map::get().sendBlockChange(pos, BLOCK_AIR, 0); 202 | toRemove.push_back(simIt); 203 | 204 | //If below this block has another waterblock, simulate it also 205 | if(Map::get().getBlock(pos - vec(0, 1, 0), &block, &meta) && 206 | isWaterBlock(block)) 207 | addSimulation(pos - vec(0, 1, 0)); 208 | 209 | } 210 | } 211 | //Have source! 212 | else 213 | { 214 | toAdd.clear(); 215 | vec belowPos(pos - vec(0, 1, 0)); 216 | // If below is free to fall 217 | if(Map::get().getBlock(belowPos, &block, &meta) && 218 | mayFallThrough(block)) 219 | { 220 | // Set new fallblock there 221 | block = BLOCK_WATER; 222 | meta = M_FALLING; 223 | Map::get().setBlock(belowPos, block, meta); 224 | Map::get().sendBlockChange(belowPos, block, meta); 225 | // Change simulation-block to current block 226 | toRemove.push_back(simIt); 227 | addSimulation(belowPos); 228 | } 229 | //Else if spreading to sides 230 | //If water level is at minimum, dont simulate anymore 231 | else if((simList[simIt].blocks[it].meta&M7) != M7) 232 | { 233 | for(int i = 0; i < 4; i++) 234 | { 235 | vec local(pos); 236 | switch(i) 237 | { 238 | case 0: local += vec( 1, 0, 0); break; 239 | 240 | case 1: local += vec(-1, 0, 0); break; 241 | 242 | case 2: local += vec( 0, 0, 1); break; 243 | 244 | case 3: local += vec( 0, 0, -1); break; 245 | } 246 | 247 | if(Map::get().getBlock(local, &block, &meta) && 248 | mayFallThrough(block)) 249 | { 250 | //Decrease water level each turn 251 | if(!isWaterBlock(block) || meta > (simList[simIt].blocks[it].meta&0x07)+1) 252 | { 253 | meta = (simList[simIt].blocks[it].meta&0x07)+1; 254 | Map::get().setBlock(local, BLOCK_WATER, meta); 255 | Map::get().sendBlockChange(local, BLOCK_WATER, meta); 256 | addSimulation(local); 257 | } 258 | } 259 | } // End for i=0:3 260 | 261 | //Remove this block from simulation 262 | toRemove.push_back(simIt); 263 | } 264 | //Water level at minimum 265 | else 266 | { 267 | //Remove this block from simulation 268 | toRemove.push_back(simIt); 269 | } 270 | } 271 | } 272 | } 273 | //Block has changes 274 | else 275 | { 276 | //Remove this block from simulation 277 | toRemove.push_back(simIt); 278 | } 279 | } 280 | } 281 | 282 | std::vector::reverse_iterator rit; 283 | for ( rit = toRemove.rbegin() ; rit < toRemove.rend(); ++rit ) 284 | { 285 | simList.erase(simList.begin()+*rit); 286 | } 287 | 288 | 289 | clock_t endtime = clock()-starttime; 290 | std::cout << "Exit simulation, took " << endtime*1000/CLOCKS_PER_SEC << " ms, " << simList.size() << " items left" << std::endl; 291 | return true; 292 | } 293 | 294 | // Add world simulation 295 | bool Physics::addSimulation(vec pos) 296 | { 297 | if(!enabled) 298 | return true; 299 | 300 | uint8 block; uint8 meta; 301 | Map::get().getBlock(pos, &block, &meta); 302 | SimBlock simulationBlock(block, pos, meta); 303 | 304 | // Simulating water 305 | if(isWaterBlock(block)) 306 | { 307 | simList.push_back(Sim(TYPE_WATER, simulationBlock)); 308 | return true; 309 | } 310 | // Simulating lava 311 | else if(isLavaBlock(block)) 312 | { 313 | simList.push_back(Sim(TYPE_LAVA, simulationBlock)); 314 | return true; 315 | } 316 | 317 | return false; 318 | } 319 | 320 | 321 | 322 | bool Physics::checkSurrounding(vec pos) 323 | { 324 | if(!enabled) 325 | return true; 326 | 327 | uint8 block; uint8 meta; 328 | 329 | for(int i = 0; i < 6; i++) 330 | { 331 | vec local(pos); 332 | switch(i) 333 | { 334 | case 0: local += vec( 0, 1, 0); break; 335 | 336 | case 1: local += vec( 1, 0, 0); break; 337 | 338 | case 2: local += vec(-1, 0, 0); break; 339 | 340 | case 3: local += vec( 0, 0, 1); break; 341 | 342 | case 4: local += vec( 0, 0, -1); break; 343 | 344 | case 5: local += vec( 0, -1, 0); break; 345 | } 346 | 347 | //Add liquid blocks to simulation if they are affected by breaking a block 348 | if(Map::get().getBlock(local, &block, &meta) && 349 | isLiquidBlock(block)) 350 | addSimulation(local); 351 | } 352 | 353 | return true; 354 | } 355 | -------------------------------------------------------------------------------- /src/packets.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef _PACKETS_H 29 | #define _PACKETS_H 30 | 31 | #include 32 | 33 | #define PACKET_NEED_MORE_DATA -3 34 | #define PACKET_DOES_NOT_EXIST -2 35 | #define PACKET_VARIABLE_LEN -1 36 | #define PACKET_OK 0 37 | 38 | class PacketHandler; 39 | class User; 40 | 41 | //Packet names 42 | enum 43 | { 44 | //Client to server 45 | PACKET_KEEP_ALIVE = 0x00, 46 | PACKET_LOGIN_REQUEST = 0x01, 47 | PACKET_HANDSHAKE = 0x02, 48 | PACKET_CHAT_MESSAGE = 0x03, 49 | PACKET_PLAYER_INVENTORY = 0x05, 50 | PACKET_RESPAWN = 0x09, 51 | PACKET_PLAYER = 0x0a, 52 | PACKET_PLAYER_POSITION = 0x0b, 53 | PACKET_PLAYER_LOOK = 0x0c, 54 | PACKET_PLAYER_POSITION_AND_LOOK = 0x0d, 55 | PACKET_PLAYER_DIGGING = 0x0e, 56 | PACKET_PLAYER_BLOCK_PLACEMENT = 0x0f, 57 | PACKET_HOLDING_CHANGE = 0x10, 58 | PACKET_ARM_ANIMATION = 0x12, 59 | PACKET_DISCONNECT = 0xff, 60 | //Server to client 61 | PACKET_LOGIN_RESPONSE = 0x01, 62 | PACKET_TIME_UPDATE = 0x04, 63 | PACKET_SPAWN_POSITION = 0x06, 64 | PACKET_UPDATE_HEALTH = 0x08, 65 | PACKET_ADD_TO_INVENTORY = 0x11, 66 | PACKET_NAMED_ENTITY_SPAWN = 0x14, 67 | PACKET_PICKUP_SPAWN = 0x15, 68 | PACKET_COLLECT_ITEM = 0x16, 69 | PACKET_ADD_OBJECT = 0x17, 70 | PACKET_MOB_SPAWN = 0x18, 71 | PACKET_DESTROY_ENTITY = 0x1d, 72 | PACKET_ENTITY = 0x1e, 73 | PACKET_ENTITY_RELATIVE_MOVE = 0x1f, 74 | PACKET_ENTITY_LOOK = 0x20, 75 | PACKET_ENTITY_LOOK_RELATIVE_MOVE = 0x21, 76 | PACKET_ENTITY_TELEPORT = 0x22, 77 | PACKET_DEATH_ANIMATION = 0x26, 78 | PACKET_PRE_CHUNK = 0x32, 79 | PACKET_MAP_CHUNK = 0x33, 80 | PACKET_MULTI_BLOCK_CHANGE = 0x34, 81 | PACKET_BLOCK_CHANGE = 0x35, 82 | PACKET_COMPLEX_ENTITIES = 0x3b, 83 | PACKET_KICK = 0xff, 84 | 85 | 86 | //v4 Packets 87 | PACKET_USE_ENTITY = 0x07, 88 | PACKET_ENTITY_VELOCITY = 0x1c, 89 | PACKET_ATTACH_ENTITY = 0x27, 90 | }; 91 | 92 | class Packet 93 | { 94 | private: 95 | typedef std::vector bufVector; 96 | bufVector m_readBuffer; 97 | bufVector::size_type m_readPos; 98 | bool m_isValid; 99 | 100 | bufVector m_writeBuffer; 101 | public: 102 | Packet() : m_readPos(0), m_isValid(true) {} 103 | 104 | bool haveData(int requiredBytes) 105 | { 106 | return m_isValid = m_isValid && ((m_readPos + requiredBytes) <= m_readBuffer.size()); 107 | } 108 | 109 | operator bool() const 110 | { 111 | return m_isValid; 112 | } 113 | 114 | void reset() 115 | { 116 | m_readPos = 0; 117 | m_isValid = true; 118 | } 119 | 120 | void addToRead(std::vector &buffer) 121 | { 122 | m_readBuffer.insert(m_readBuffer.end(), buffer.begin(), buffer.end()); 123 | } 124 | 125 | void addToRead(const void * data, bufVector::size_type dataSize) 126 | { 127 | bufVector::size_type start = m_readBuffer.size(); 128 | m_readBuffer.resize(start + dataSize); 129 | memcpy(&m_readBuffer[start], data, dataSize); 130 | } 131 | 132 | void addToWrite(const void * data, bufVector::size_type dataSize) 133 | { 134 | if(dataSize == 0) 135 | return; 136 | bufVector::size_type start = m_writeBuffer.size(); 137 | m_writeBuffer.resize(start + dataSize); 138 | memcpy(&m_writeBuffer[start], data, dataSize); 139 | } 140 | 141 | void removePacket() 142 | { 143 | m_readBuffer.erase(m_readBuffer.begin(), m_readBuffer.begin() + m_readPos); 144 | m_readPos = 0; 145 | } 146 | 147 | Packet & operator<<(sint8 val) 148 | { 149 | m_writeBuffer.push_back(val); 150 | return *this; 151 | } 152 | 153 | Packet & operator>>(sint8 &val) 154 | { 155 | if(haveData(1)) 156 | { 157 | val = *reinterpret_cast(&m_readBuffer[m_readPos]); 158 | m_readPos += 1; 159 | } 160 | return *this; 161 | } 162 | 163 | Packet & operator<<(sint16 val) 164 | { 165 | uint16 nval = htons(val); 166 | addToWrite(&nval, 2); 167 | return *this; 168 | } 169 | 170 | Packet & operator>>(sint16 &val) 171 | { 172 | if(haveData(2)) 173 | { 174 | val = ntohs(*reinterpret_cast(&m_readBuffer[m_readPos])); 175 | m_readPos += 2; 176 | } 177 | return *this; 178 | } 179 | 180 | Packet & operator<<(sint32 val) 181 | { 182 | uint32 nval = htonl(val); 183 | addToWrite(&nval, 4); 184 | return *this; 185 | } 186 | 187 | Packet & operator>>(sint32 &val) 188 | { 189 | if(haveData(4)) 190 | { 191 | val = ntohl(*reinterpret_cast(&m_readBuffer[m_readPos])); 192 | m_readPos += 4; 193 | } 194 | return *this; 195 | } 196 | 197 | Packet & operator<<(sint64 val) 198 | { 199 | uint64 nval = ntohll(val); 200 | addToWrite(&nval, 8); 201 | return *this; 202 | } 203 | 204 | Packet & operator>>(sint64 &val) 205 | { 206 | if(haveData(8)) 207 | { 208 | val = *reinterpret_cast(&m_readBuffer[m_readPos]); 209 | val = ntohll(val); 210 | m_readPos += 8; 211 | } 212 | return *this; 213 | } 214 | 215 | Packet & operator<<(float val) 216 | { 217 | uint32 nval; 218 | memcpy(&nval, &val , 4); 219 | nval = htonl(nval); 220 | addToWrite(&nval, 4); 221 | return *this; 222 | } 223 | 224 | Packet & operator>>(float &val) 225 | { 226 | if(haveData(4)) 227 | { 228 | sint32 ival = ntohl(*reinterpret_cast(&m_readBuffer[m_readPos])); 229 | memcpy(&val, &ival, 4); 230 | m_readPos += 4; 231 | } 232 | return *this; 233 | } 234 | 235 | Packet & operator<<(double val) 236 | { 237 | uint64 nval; 238 | memcpy(&nval, &val, 8); 239 | nval = ntohll(nval); 240 | addToWrite(&nval, 8); 241 | return *this; 242 | } 243 | 244 | 245 | Packet & operator>>(double &val) 246 | { 247 | if(haveData(8)) 248 | { 249 | uint64 ival = *reinterpret_cast(&m_readBuffer[m_readPos]); 250 | ival = ntohll(ival); 251 | memcpy((void*)&val, (void*)&ival, 8); 252 | m_readPos += 8; 253 | } 254 | return *this; 255 | } 256 | 257 | Packet & operator<<(const std::string &str) 258 | { 259 | uint16 lenval = htons(str.size()); 260 | addToWrite(&lenval, 2); 261 | 262 | addToWrite(&str[0], str.size()); 263 | return *this; 264 | } 265 | 266 | Packet & operator>>(std::string &str) 267 | { 268 | sint16 lenval; 269 | if(haveData(2)) 270 | { 271 | lenval = ntohs(*reinterpret_cast(&m_readBuffer[m_readPos])); 272 | m_readPos += 2; 273 | 274 | if(haveData(lenval)) 275 | { 276 | str.assign((char*)&m_readBuffer[m_readPos], lenval); 277 | m_readPos += lenval; 278 | } 279 | } 280 | return *this; 281 | } 282 | 283 | void operator<<(Packet &other) 284 | { 285 | int dataSize = other.getWriteLen(); 286 | if(dataSize == 0) 287 | return; 288 | bufVector::size_type start = m_writeBuffer.size(); 289 | m_writeBuffer.resize(start + dataSize); 290 | memcpy(&m_writeBuffer[start], other.getWrite(), dataSize); 291 | } 292 | 293 | void getData(void *buf, int count) 294 | { 295 | if(haveData(count)) 296 | { 297 | memcpy(buf, &m_readBuffer[m_readPos], count); 298 | m_readPos += count; 299 | } 300 | } 301 | 302 | void *getWrite() 303 | { 304 | return &m_writeBuffer[0]; 305 | } 306 | 307 | size_t getWriteLen() const 308 | { 309 | return m_writeBuffer.size(); 310 | } 311 | 312 | void clearWrite(int count) 313 | { 314 | m_writeBuffer.erase(m_writeBuffer.begin(), m_writeBuffer.begin() + count); 315 | } 316 | }; 317 | 318 | 319 | 320 | struct Packets 321 | { 322 | int len; 323 | int (PacketHandler::*function)(User *); 324 | 325 | //int (PacketHandler::*varLenFunction)(User *); 326 | 327 | Packets() 328 | { 329 | len = PACKET_DOES_NOT_EXIST; 330 | } 331 | Packets(int newlen) 332 | { 333 | len = newlen; 334 | } 335 | /* Packets(int newlen, void (PacketHandler::*newfunction)(uint *, User *)) 336 | { 337 | len = newlen; 338 | function = newfunction; 339 | } 340 | 341 | Packets(int newlen, void (PacketHandler::*newfunction)(User *)) 342 | { 343 | len = newlen; 344 | function = newfunction; 345 | } 346 | */ 347 | Packets(int newlen, int (PacketHandler::*newfunction)(User *)) 348 | { 349 | len = newlen; 350 | function = newfunction; 351 | } 352 | }; 353 | 354 | struct packet_login_request 355 | { 356 | int version; 357 | std::string Username; 358 | std::string Password; 359 | sint64 map_seed; 360 | uint8 dimension; 361 | }; 362 | 363 | struct packet_player_position 364 | { 365 | double x; 366 | double y; 367 | double stance; 368 | double z; 369 | char onground; 370 | }; 371 | 372 | struct packet_player_look 373 | { 374 | float yaw; 375 | float pitch; 376 | char onground; 377 | }; 378 | 379 | struct packet_player_position_and_look 380 | { 381 | double x; 382 | double y; 383 | double stance; 384 | double z; 385 | float yaw; 386 | float pitch; 387 | char onground; 388 | }; 389 | 390 | class PacketHandler 391 | { 392 | 393 | private: 394 | PacketHandler() 395 | { 396 | } 397 | ~PacketHandler() 398 | { 399 | } 400 | 401 | public: 402 | 403 | void initPackets(); 404 | 405 | 406 | 407 | static PacketHandler &get() 408 | { 409 | static PacketHandler instance; 410 | return instance; 411 | } 412 | //Information of all the packets 413 | //around 2kB of memory 414 | Packets packets[256]; 415 | 416 | //The packet functions 417 | int keep_alive(User *user); 418 | int login_request(User *user); 419 | int handshake(User *user); 420 | int chat_message(User *user); 421 | int player_inventory(User *user); 422 | int player(User *user); 423 | int player_position(User *user); 424 | int player_look(User *user); 425 | int player_position_and_look(User *user); 426 | int player_digging(User *user); 427 | int player_block_placement(User *user); 428 | int holding_change(User *user); 429 | int arm_animation(User *user); 430 | int pickup_spawn(User *user); 431 | int disconnect(User *user); 432 | int complex_entities(User *user); 433 | int use_entity(User *user); 434 | int respawn(User *user); 435 | 436 | }; 437 | 438 | 439 | #endif 440 | -------------------------------------------------------------------------------- /src/commands.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #ifdef WIN32 37 | #include 38 | #else 39 | #include 40 | #include 41 | #endif 42 | 43 | #include "logger.h" 44 | #include "constants.h" 45 | 46 | #include "tools.h" 47 | #include "map.h" 48 | #include "user.h" 49 | #include "chat.h" 50 | #include "config.h" 51 | #include "tools.h" 52 | #include "physics.h" 53 | 54 | namespace 55 | { 56 | 57 | void reportError(User *user, std::string message) 58 | { 59 | Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "Error! " + COLOR_RED + message, Chat::USER); 60 | } 61 | 62 | void playerList(User *user, std::string command, std::deque args) 63 | { 64 | Chat::get().sendUserlist(user); 65 | } 66 | 67 | void about(User *user, std::string command, std::deque args) 68 | { 69 | Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + Conf::get().sValue("servername")+ 70 | "Running Mineserver v." + VERSION, Chat::USER); 71 | } 72 | 73 | void rules(User *user, std::string command, std::deque args) 74 | { 75 | User *tUser = user; 76 | if(!args.empty() && user->admin) 77 | tUser = getUserByNick(args[0]); 78 | if(tUser != NULL) 79 | { 80 | // Send rules 81 | std::ifstream ifs(Conf::get().sValue("rules_file").c_str()); 82 | std::string temp; 83 | 84 | if(ifs.fail()) 85 | { 86 | std::cout << "> Warning: " << Conf::get().sValue("rules_file") << " not found." << std::endl; 87 | return; 88 | } 89 | else 90 | { 91 | while(getline(ifs, temp)) 92 | { 93 | // If not a comment 94 | if(!temp.empty() && temp[0] != COMMENTPREFIX) 95 | Chat::get().sendMsg(tUser, temp, Chat::USER); 96 | } 97 | ifs.close(); 98 | } 99 | } 100 | else 101 | reportError(user, "User " + args[0] + " not found (see /players)"); 102 | } 103 | } 104 | 105 | void home(User *user, std::string command, std::deque args) 106 | { 107 | Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "Teleported you home!", Chat::USER); 108 | user->teleport(Map::get().spawnPos.x(), Map::get().spawnPos.y() + 2, Map::get().spawnPos.z()); 109 | } 110 | 111 | void kit(User *user, std::string command, std::deque args) 112 | { 113 | if(!args.empty()) 114 | { 115 | std::vector kitItems = Conf::get().vValue("kit_" + args[0]); 116 | // If kit is found 117 | if(!kitItems.empty()) 118 | { 119 | for(uint32 i=0;i(user->pos.x*32 + (rand() % 30)); 127 | item.pos.y() = static_cast(user->pos.y*32); 128 | item.pos.z() = static_cast(user->pos.z*32 + (rand() % 30)); 129 | Map::get().sendPickupSpawn(item); 130 | } 131 | } 132 | else 133 | reportError(user, "Kit " + args[0] + " not found"); 134 | } 135 | } 136 | 137 | void saveMap(User *user, std::string command, std::deque args) 138 | { 139 | Map::get().saveWholeMap(); 140 | Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "SERVER:" + COLOR_RED + " Saved map to disc", 141 | Chat::USER); 142 | } 143 | 144 | void ban(User *user, std::string command, std::deque args) 145 | { 146 | std::string victim = args[0]; 147 | User *tUser = getUserByNick(victim); 148 | 149 | std::fstream bannedf; 150 | bannedf.open("banned.txt",std::fstream::app); 151 | bannedf << victim << std::endl; 152 | bannedf.close(); 153 | 154 | if(tUser != NULL) 155 | { 156 | args.pop_front(); 157 | std::string kickMsg; 158 | if(args.empty()) 159 | kickMsg = Conf::get().sValue("default_banned_message"); 160 | else 161 | { 162 | while(!args.empty()) 163 | { 164 | kickMsg += args[0] + " "; 165 | args.pop_front(); 166 | } 167 | } 168 | 169 | tUser->kick(kickMsg); 170 | } 171 | else 172 | Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + victim +" was banned in his absence!", Chat::USER); 173 | 174 | // Reload list with banned users 175 | Chat::get().loadBanned(BANNEDFILE); 176 | } 177 | 178 | void unban(User *user, std::string command, std::deque args) 179 | { 180 | std::string victim = args[0]; 181 | User *tUser = getUserByNick(victim); 182 | 183 | std::string line; 184 | std::ifstream in("banned.txt"); 185 | 186 | std::ofstream out("banned.tmp"); 187 | 188 | while( getline(in,line) ) 189 | { 190 | if(line != victim) 191 | out << line << "\n"; 192 | } 193 | in.close(); 194 | out.close(); 195 | 196 | remove("banned.txt"); 197 | rename("banned.tmp","banned.txt"); 198 | 199 | // Reload list with banned users 200 | Chat::get().loadBanned(BANNEDFILE); 201 | } 202 | 203 | void kick(User *user, std::string command, std::deque args) 204 | { 205 | if(!args.empty()) 206 | { 207 | std::string victim = args[0]; 208 | 209 | User *tUser = getUserByNick(victim); 210 | 211 | if(tUser != NULL) 212 | { 213 | args.pop_front(); 214 | std::string kickMsg; 215 | if(args.empty()) 216 | kickMsg = Conf::get().sValue("default_kick_message"); 217 | else 218 | { 219 | while(!args.empty()) 220 | { 221 | kickMsg += args[0] + " "; 222 | args.pop_front(); 223 | } 224 | } 225 | 226 | tUser->kick(kickMsg); 227 | } 228 | else 229 | reportError(user, "User " + victim + " not found (see /players)"); 230 | } 231 | else 232 | reportError(user, "Usage: /kick user [reason]"); 233 | } 234 | 235 | void setTime(User *user, std::string command, std::deque args) 236 | { 237 | if(args.size() == 1) 238 | { 239 | Map::get().mapTime = (sint64)atoi(args[0].c_str()); 240 | Packet pkt; 241 | pkt << (sint8)PACKET_TIME_UPDATE << (sint64)Map::get().mapTime; 242 | if(Users.size()) 243 | Users[0]->sendAll((uint8*)pkt.getWrite(), pkt.getWriteLen()); 244 | Chat::get().sendMsg(user, COLOR_MAGENTA + "Time set to " + args[0], Chat::USER); 245 | } 246 | else 247 | reportError(user, "Usage: /settime time (time = 0-24000)"); 248 | } 249 | 250 | void coordinateTeleport(User *user, std::string command, std::deque args) 251 | { 252 | if(args.size() > 2) 253 | { 254 | LOG(user->nick + " teleport to: " + args[0] + " " + args[1] + " " + args[2]); 255 | double x = atof(args[0].c_str()); 256 | double y = atof(args[1].c_str()); 257 | double z = atof(args[2].c_str()); 258 | user->teleport(x, y, z); 259 | } 260 | } 261 | 262 | void userTeleport(User *user, std::string command, std::deque args) 263 | { 264 | if(args.size() == 1) 265 | { 266 | LOG(user->nick + " teleport to: " + args[0]); 267 | User *tUser = getUserByNick(args[0]); 268 | if(tUser != NULL) 269 | user->teleport(tUser->pos.x, tUser->pos.y + 2, tUser->pos.z); 270 | else 271 | reportError(user, "User " + args[0] + " not found (see /players)"); 272 | } 273 | else if(args.size() == 2) 274 | { 275 | LOG(user->nick + ": teleport " + args[0] + " to " + args[1]); 276 | 277 | User *whoUser = getUserByNick(args[0]); 278 | User *toUser = getUserByNick(args[1]); 279 | 280 | if(whoUser != NULL && toUser != NULL) 281 | { 282 | whoUser->teleport(toUser->pos.x, toUser->pos.y + 2, toUser->pos.z); 283 | Chat::get().sendMsg(user, COLOR_MAGENTA + "Teleported!", Chat::USER); 284 | } 285 | else 286 | { 287 | reportError(user, "User " + (whoUser == NULL ? args[0] : args[1])+ 288 | " not found (see /players"); 289 | } 290 | } 291 | } 292 | 293 | void showPosition(User *user, std::string command, std::deque args) 294 | { 295 | if(args.size() == 1) 296 | { 297 | User *tUser = getUserByNick(args[0]); 298 | if(tUser != NULL) 299 | Chat::get().sendMsg(user, COLOR_MAGENTA + args[0] + " is at: " + dtos(tUser->pos.x) 300 | + " " 301 | + dtos(tUser->pos.y) 302 | + " " 303 | + dtos(tUser->pos.z), Chat::USER); 304 | else 305 | reportError(user, "User " + args[0] + " not found (see /players)"); 306 | } 307 | else 308 | { 309 | Chat::get().sendMsg(user, COLOR_MAGENTA + "You are at: " + dtos(user->pos.x) 310 | + " " 311 | + dtos(user->pos.y) 312 | + " " 313 | + dtos(user->pos.z), Chat::USER); 314 | } 315 | } 316 | 317 | void regenerateLighting(User *user, std::string command, std::deque args) 318 | { 319 | printf("Regenerating lighting for chunk %d,%d\n", blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z)); 320 | //First load the map 321 | if(Map::get().loadMap(blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z))) 322 | { 323 | //Then regenerate lighting 324 | Map::get().generateLight(blockToChunk((sint32)user->pos.x), blockToChunk((sint32)user->pos.z)); 325 | } 326 | } 327 | 328 | void reloadConfiguration(User *user, std::string command, std::deque args) 329 | { 330 | Chat::get().loadAdmins(Conf::get().sValue("admin_file")); 331 | Chat::get().loadBanned(BANNEDFILE); 332 | Chat::get().loadWhitelist(WHITELISTFILE); 333 | Conf::get().load(CONFIG_FILE); 334 | 335 | // Set physics enable state based on config 336 | Physics::get().enabled = (Conf::get().bValue("liquid_physics")); 337 | 338 | Chat::get().sendMsg(user, COLOR_DARK_MAGENTA + "SERVER: "+COLOR_RED+"Reloaded admins and config", Chat::USER); 339 | 340 | // Note that the MOTD is loaded on-demand each time it is requested 341 | } 342 | 343 | bool isValidItem(int id) 344 | { 345 | if(id < 1) // zero or negative items are all invalid 346 | return false; 347 | 348 | if(id > 91 && id < 256) // these are undefined blocks and items 349 | return false; 350 | 351 | if(id == 2256 || id == 2257) // records are special cased 352 | return true; 353 | 354 | if(id > 350) // high items are invalid 355 | return false; 356 | 357 | if(id >= BLOCK_RED_CLOTH && id <= BLOCK_GRAY_CLOTH) // coloured cloth causes client crashes 358 | return false; 359 | 360 | return true; 361 | } 362 | 363 | int roundUpTo(int x, int nearest) 364 | { 365 | x += (nearest - 1); 366 | x /= nearest; 367 | x *= nearest; 368 | return x; 369 | } 370 | 371 | void giveItems(User *user, std::string command, std::deque args) 372 | { 373 | User *tUser = NULL; 374 | int itemId = 0, itemCount = 1, itemStacks = 1; 375 | 376 | if(args.size() > 1) 377 | { 378 | tUser = getUserByNick(args[0]); 379 | 380 | //First check if item is a number 381 | itemId = atoi(args[1].c_str()); 382 | 383 | //If item was not a number, search the name from config 384 | if(itemId == 0) 385 | itemId = Conf::get().iValue(args[1]); 386 | 387 | // Check item validity 388 | if(!isValidItem(itemId)) 389 | { 390 | reportError(user, "Item " + args[1] + " not found."); 391 | return; 392 | } 393 | 394 | if(args.size() > 2) 395 | { 396 | itemCount = atoi(args[2].c_str()); 397 | // If multiple stacks 398 | itemStacks = roundUpTo(itemCount, 64) / 64; 399 | itemCount -= (itemStacks-1) * 64; 400 | } 401 | } 402 | else 403 | { 404 | reportError(user, "Too few parameters."); 405 | return; 406 | } 407 | 408 | if(tUser) 409 | { 410 | int amount = 64; 411 | for(int i = 0; i < itemStacks; i++) 412 | { 413 | // if last stack 414 | if(i == itemStacks - 1) 415 | amount = itemCount; 416 | 417 | spawnedItem item; 418 | item.EID = generateEID(); 419 | item.item = itemId; 420 | item.health = 0; 421 | item.count = amount; 422 | item.pos.x() = static_cast(tUser->pos.x * 32); 423 | item.pos.y() = static_cast(tUser->pos.y * 32); 424 | item.pos.z() = static_cast(tUser->pos.z * 32); 425 | 426 | Map::get().sendPickupSpawn(item); 427 | } 428 | 429 | Chat::get().sendMsg(user, COLOR_RED + user->nick + " spawned " + args[1], Chat::ADMINS); 430 | } 431 | else 432 | reportError(user, "User " + args[0] + " not found (see /players)"); 433 | } 434 | 435 | void Chat::registerStandardCommands() 436 | { 437 | registerCommand("players", playerList, false); 438 | registerCommand("about", about, false); 439 | registerCommand("rules", rules, false); 440 | registerCommand("home", home, false); 441 | registerCommand("ban", ban, true); 442 | registerCommand("unban", unban, true); 443 | registerCommand("kit", kit, false); 444 | registerCommand("save", saveMap, true); 445 | registerCommand("kick", kick, true); 446 | registerCommand("ctp", coordinateTeleport, true); 447 | registerCommand("tp", userTeleport, true); 448 | registerCommand("reload", reloadConfiguration, true); 449 | registerCommand("give", giveItems, true); 450 | registerCommand("gps", showPosition, true); 451 | registerCommand("settime", setTime, true); registerCommand("regen", regenerateLighting, true); 452 | } 453 | -------------------------------------------------------------------------------- /src/nbt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010, The Mineserver Project 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the The Mineserver Project nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #ifdef WIN32 34 | #include 35 | #else 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #endif 48 | 49 | #include 50 | 51 | #include "tools.h" 52 | #include "nbt.h" 53 | #include "map.h" 54 | 55 | 56 | //NBT level file reading 57 | //More info: http://www.minecraft.net/docs/NBT.txt 58 | 59 | NBT_Value::NBT_Value(eTAG_Type type, eTAG_Type listType) : m_type(type) 60 | { 61 | memset(&m_value, 0, sizeof(m_value)); 62 | if(type == TAG_LIST) 63 | m_value.listVal.type = listType; 64 | } 65 | 66 | NBT_Value::NBT_Value(sint8 value) : m_type(TAG_BYTE) 67 | { 68 | m_value.byteVal = value; 69 | } 70 | 71 | NBT_Value::NBT_Value(sint16 value) : m_type(TAG_SHORT) 72 | { 73 | m_value.shortVal = value; 74 | } 75 | 76 | NBT_Value::NBT_Value(sint32 value) : m_type(TAG_INT) 77 | { 78 | m_value.intVal = value; 79 | } 80 | 81 | NBT_Value::NBT_Value(sint64 value) : m_type(TAG_LONG) 82 | { 83 | m_value.longVal = value; 84 | } 85 | 86 | NBT_Value::NBT_Value(float value) : m_type(TAG_FLOAT) 87 | { 88 | m_value.floatVal = value; 89 | } 90 | 91 | NBT_Value::NBT_Value(double value) : m_type(TAG_DOUBLE) 92 | { 93 | m_value.doubleVal = value; 94 | } 95 | 96 | NBT_Value::NBT_Value(uint8 *buf, sint32 len) : m_type(TAG_BYTE_ARRAY) 97 | { 98 | m_value.byteArrayVal = new std::vector(buf, buf + len); 99 | } 100 | 101 | NBT_Value::NBT_Value(const std::string &str) : m_type(TAG_STRING) 102 | { 103 | m_value.stringVal = new std::string(str); 104 | } 105 | 106 | NBT_Value::NBT_Value(eTAG_Type type, uint8 **buf, int &remaining) : m_type(type) 107 | { 108 | switch(m_type) 109 | { 110 | case TAG_BYTE: 111 | remaining--; 112 | if(remaining >= 0) 113 | { 114 | m_value.byteVal = **buf; 115 | (*buf)++; 116 | } 117 | break; 118 | case TAG_SHORT: 119 | remaining-=2; 120 | if(remaining >= 0) 121 | { 122 | m_value.shortVal = getSint16(*buf); 123 | *buf += 2; 124 | } 125 | break; 126 | case TAG_INT: 127 | remaining-=4; 128 | if(remaining >= 0) 129 | { 130 | m_value.intVal = getSint32(*buf); 131 | *buf += 4; 132 | } 133 | break; 134 | case TAG_LONG: 135 | remaining -= 8; 136 | if(remaining >= 0) 137 | { 138 | m_value.longVal = getSint64(*buf); 139 | *buf += 8; 140 | } 141 | break; 142 | case TAG_FLOAT: 143 | remaining -= 4; 144 | if(remaining >= 0) 145 | { 146 | m_value.floatVal = getFloat(*buf); 147 | *buf += 4; 148 | } 149 | break; 150 | case TAG_DOUBLE: 151 | remaining -= 8; 152 | if(remaining >= 0) 153 | { 154 | m_value.doubleVal = getDouble(*buf); 155 | *buf += 8; 156 | } 157 | break; 158 | case TAG_BYTE_ARRAY: 159 | remaining -= 4; 160 | if(remaining >= 0) 161 | { 162 | sint32 bufLen = getSint32(*buf); 163 | remaining -= bufLen; 164 | *buf += 4; 165 | if(remaining >= 0) 166 | { 167 | m_value.byteArrayVal = new std::vector(); 168 | m_value.byteArrayVal->assign(*buf, (*buf)+bufLen); 169 | *buf += bufLen; 170 | } 171 | } 172 | break; 173 | case TAG_STRING: 174 | remaining -= 2; 175 | if(remaining >= 0) 176 | { 177 | sint16 stringLen = getSint16(*buf); 178 | remaining -= stringLen; 179 | *buf += 2; 180 | if(remaining >= 0) 181 | { 182 | m_value.stringVal = new std::string((char*)*buf, stringLen); 183 | *buf += stringLen; 184 | } 185 | } 186 | break; 187 | case TAG_LIST: 188 | remaining -= 5; 189 | if(remaining >= 0) 190 | { 191 | sint8 type = **buf; 192 | (*buf)++; 193 | m_value.listVal.type = (eTAG_Type)type; 194 | sint32 count = getSint32(*buf); 195 | *buf += 4; 196 | m_value.listVal.data = new std::vector(); 197 | if(count) 198 | m_value.listVal.data->resize(count); 199 | 200 | for(int i=0;i(); 208 | while(remaining > 0) 209 | { 210 | remaining--; 211 | sint8 type = **buf; 212 | (*buf)++; 213 | if(type == TAG_END) 214 | break; 215 | 216 | remaining -= 2; 217 | if(remaining <= 0) 218 | break; 219 | 220 | sint16 stringLen = getSint16(*buf); 221 | *buf += 2; 222 | 223 | remaining -= stringLen; 224 | 225 | if(remaining <= 0) 226 | break; 227 | 228 | std::string key((char*)*buf, stringLen); 229 | *buf += stringLen; 230 | 231 | (*m_value.compoundVal)[key] = new NBT_Value((eTAG_Type)type, buf, remaining); 232 | } 233 | break; 234 | case TAG_END: 235 | break; 236 | } 237 | } 238 | 239 | NBT_Value::~NBT_Value() 240 | { 241 | cleanup(); 242 | } 243 | 244 | NBT_Value * NBT_Value::operator[](const std::string &index) 245 | { 246 | if(m_type != TAG_COMPOUND) 247 | return NULL; 248 | 249 | if(!m_value.compoundVal->count(index)) 250 | return NULL; 251 | 252 | return (*m_value.compoundVal)[index]; 253 | } 254 | 255 | 256 | NBT_Value * NBT_Value::operator[](const char *index) 257 | { 258 | if(m_type != TAG_COMPOUND) 259 | return NULL; 260 | 261 | std::string stdIndex(index, strlen(index)); 262 | 263 | if(!m_value.compoundVal->count(stdIndex)) 264 | return NULL; 265 | 266 | return (*m_value.compoundVal)[stdIndex]; 267 | } 268 | 269 | void NBT_Value::Insert(const std::string &str, NBT_Value *val) 270 | { 271 | if(m_type != NBT_Value::TAG_COMPOUND) 272 | return; 273 | 274 | if(m_value.compoundVal == 0) 275 | m_value.compoundVal = new std::map(); 276 | 277 | (*m_value.compoundVal)[str] = val; 278 | } 279 | 280 | NBT_Value::operator sint8() 281 | { 282 | if(m_type != TAG_BYTE) 283 | return 0; 284 | 285 | return m_value.byteVal; 286 | } 287 | 288 | NBT_Value::operator sint16() 289 | { 290 | if(m_type != TAG_SHORT) 291 | return 0; 292 | 293 | return m_value.shortVal; 294 | } 295 | 296 | NBT_Value::operator sint32() 297 | { 298 | if(m_type != TAG_INT) 299 | return 0; 300 | 301 | return m_value.intVal; 302 | } 303 | 304 | NBT_Value::operator sint64() 305 | { 306 | if(m_type != TAG_LONG) 307 | return 0; 308 | 309 | return m_value.longVal; 310 | } 311 | 312 | NBT_Value::operator float() 313 | { 314 | if(m_type != TAG_FLOAT) 315 | return 0; 316 | 317 | return m_value.floatVal; 318 | } 319 | 320 | NBT_Value::operator double() 321 | { 322 | if(m_type != TAG_DOUBLE) 323 | return 0; 324 | 325 | return m_value.doubleVal; 326 | } 327 | 328 | NBT_Value & NBT_Value::operator =(sint8 val) 329 | { 330 | cleanup(); 331 | m_type = TAG_BYTE; 332 | m_value.byteVal = val; 333 | return *this; 334 | } 335 | 336 | NBT_Value & NBT_Value::operator =(sint16 val) 337 | { 338 | cleanup(); 339 | m_type = TAG_SHORT; 340 | m_value.shortVal = val; 341 | return *this; 342 | } 343 | 344 | NBT_Value & NBT_Value::operator =(sint32 val) 345 | { 346 | cleanup(); 347 | m_type = TAG_INT; 348 | m_value.intVal = val; 349 | return *this; 350 | } 351 | 352 | NBT_Value & NBT_Value::operator =(sint64 val) 353 | { 354 | cleanup(); 355 | m_type = TAG_LONG; 356 | m_value.longVal = val; 357 | return *this; 358 | } 359 | 360 | NBT_Value & NBT_Value::operator =(float val) 361 | { 362 | cleanup(); 363 | m_type = TAG_FLOAT; 364 | m_value.floatVal = val; 365 | return *this; 366 | } 367 | 368 | NBT_Value & NBT_Value::operator =(double val) 369 | { 370 | cleanup(); 371 | m_type = TAG_DOUBLE; 372 | m_value.doubleVal = val; 373 | return *this; 374 | } 375 | 376 | std::vector *NBT_Value::GetByteArray() 377 | { 378 | if(m_type != TAG_BYTE_ARRAY) 379 | return NULL; 380 | if(m_value.byteArrayVal == NULL) 381 | m_value.byteArrayVal = new std::vector(); 382 | return m_value.byteArrayVal; 383 | } 384 | 385 | 386 | std::string *NBT_Value::GetString() 387 | { 388 | if(m_type != TAG_STRING) 389 | return NULL; 390 | if(m_value.stringVal == NULL) 391 | m_value.stringVal = new std::string(); 392 | return m_value.stringVal; 393 | } 394 | 395 | NBT_Value::eTAG_Type NBT_Value::GetListType() 396 | { 397 | if(m_type != TAG_LIST) 398 | return TAG_END; 399 | return m_value.listVal.type; 400 | } 401 | 402 | std::vector *NBT_Value::GetList() 403 | { 404 | if(m_type != TAG_LIST) 405 | return NULL; 406 | if(m_value.listVal.data == NULL) 407 | m_value.listVal.data = new std::vector(); 408 | return m_value.listVal.data; 409 | } 410 | 411 | 412 | void NBT_Value::SetType(eTAG_Type type, eTAG_Type listType) 413 | { 414 | cleanup(); 415 | m_type = type; 416 | 417 | if(m_type == TAG_LIST) 418 | m_value.listVal.type = listType; 419 | } 420 | 421 | NBT_Value::eTAG_Type NBT_Value::GetType() 422 | { 423 | return m_type; 424 | } 425 | 426 | void NBT_Value::cleanup() 427 | { 428 | if(m_type == TAG_STRING) 429 | delete m_value.stringVal; 430 | if(m_type == TAG_BYTE_ARRAY) 431 | delete m_value.byteArrayVal; 432 | if(m_type == TAG_LIST) 433 | { 434 | if(m_value.listVal.data != NULL) 435 | { 436 | std::vector::iterator iter = m_value.listVal.data->begin(), end = m_value.listVal.data->end(); 437 | for( ; iter != end ; iter++) 438 | delete *iter; 439 | delete m_value.listVal.data; 440 | } 441 | } 442 | if(m_type == TAG_COMPOUND) 443 | { 444 | if(m_value.compoundVal != NULL) 445 | { 446 | std::map::iterator iter = m_value.compoundVal->begin(), end = m_value.compoundVal->end(); 447 | for( ; iter != end ; iter++ ) 448 | delete iter->second; 449 | 450 | delete m_value.compoundVal; 451 | } 452 | } 453 | 454 | memset(&m_value, 0, sizeof(m_value)); 455 | m_type = TAG_END; 456 | } 457 | 458 | NBT_Value * NBT_Value::LoadFromFile(const std::string &filename) 459 | { 460 | FILE *fp = fopen(filename.c_str(), "rb"); 461 | if(fp == NULL) 462 | return NULL; 463 | fseek(fp, -4, SEEK_END); 464 | uint32 uncompressedSize = 0; 465 | fread(&uncompressedSize, 4, 1, fp); 466 | fclose(fp); 467 | 468 | uint8 *uncompressedData = new uint8[uncompressedSize]; 469 | gzFile nbtFile = gzopen(filename.c_str(), "rb"); 470 | if(nbtFile == NULL) 471 | { 472 | delete[] uncompressedData; 473 | return NULL; 474 | } 475 | gzread(nbtFile, uncompressedData, uncompressedSize); 476 | gzclose(nbtFile); 477 | 478 | uint8 *ptr = uncompressedData+3; // Jump blank compound 479 | int remaining = uncompressedSize; 480 | 481 | NBT_Value *root = new NBT_Value(TAG_COMPOUND, &ptr, remaining); 482 | 483 | delete[] uncompressedData; 484 | 485 | return root; 486 | } 487 | 488 | void NBT_Value::SaveToFile(const std::string &filename) 489 | { 490 | std::vector buffer; 491 | 492 | // Blank compound tag 493 | buffer.push_back(TAG_COMPOUND); 494 | buffer.push_back(0); 495 | buffer.push_back(0); 496 | 497 | Write(buffer); 498 | 499 | buffer.push_back(0); 500 | buffer.push_back(0); 501 | buffer.push_back(0); 502 | 503 | gzFile nbtFile = gzopen(filename.c_str(), "wb"); 504 | gzwrite(nbtFile, &buffer[0], buffer.size()); 505 | gzclose(nbtFile); 506 | } 507 | 508 | void NBT_Value::Write(std::vector &buffer) 509 | { 510 | int storeAt = buffer.size();; 511 | switch(m_type) 512 | { 513 | case TAG_BYTE: 514 | buffer.push_back(m_value.byteVal); 515 | break; 516 | case TAG_SHORT: 517 | buffer.resize(storeAt + 2); 518 | putSint16(&buffer[storeAt], m_value.shortVal); 519 | break; 520 | case TAG_INT: 521 | buffer.resize(storeAt + 4); 522 | putSint32(&buffer[storeAt], m_value.intVal); 523 | break; 524 | case TAG_LONG: 525 | buffer.resize(storeAt + 8); 526 | putSint64(&buffer[storeAt], m_value.longVal); 527 | break; 528 | case TAG_FLOAT: 529 | buffer.resize(storeAt + 4); 530 | putFloat(&buffer[storeAt], m_value.floatVal); 531 | break; 532 | case TAG_DOUBLE: 533 | buffer.resize(storeAt + 8); 534 | putDouble(&buffer[storeAt], m_value.doubleVal); 535 | break; 536 | case TAG_BYTE_ARRAY: 537 | { 538 | int arraySize = m_value.byteArrayVal ? m_value.byteArrayVal->size() : 0; 539 | buffer.resize(storeAt + 4 + arraySize); 540 | putSint32(&buffer[storeAt], arraySize); 541 | storeAt += 4; 542 | if(arraySize) 543 | memcpy(&buffer[storeAt], &(*m_value.byteArrayVal)[0], arraySize); 544 | break; 545 | } 546 | case TAG_STRING: 547 | { 548 | int stringLen = m_value.stringVal ? m_value.stringVal->size() : 0; 549 | buffer.resize(storeAt + 2 + stringLen); 550 | putSint16(&buffer[storeAt], (sint16)stringLen); 551 | storeAt += 2; 552 | if(stringLen>0) 553 | memcpy(&buffer[storeAt], m_value.stringVal->c_str(), stringLen); 554 | break; 555 | } 556 | case TAG_LIST: 557 | { 558 | buffer.resize(storeAt + 5); 559 | int listCount = m_value.listVal.data ? m_value.listVal.data->size() : 0; 560 | buffer[storeAt] = m_value.listVal.type; 561 | storeAt++; 562 | putSint32(&buffer[storeAt], listCount); 563 | for(int i=0;iWrite(buffer); 565 | break; 566 | } 567 | case TAG_COMPOUND: 568 | { 569 | int compoundCount = m_value.compoundVal ? m_value.compoundVal->size() : 0; 570 | if(compoundCount) 571 | { 572 | std::map::iterator iter = m_value.compoundVal->begin(), end = m_value.compoundVal->end(); 573 | for( ; iter != end; iter++) 574 | { 575 | const std::string &key = iter->first; 576 | int keySize = key.size(); 577 | NBT_Value *val = iter->second; 578 | int curPos = buffer.size(); 579 | buffer.resize(curPos + 3 + keySize); 580 | buffer[curPos] = (uint8)val->GetType(); 581 | curPos++; 582 | putSint16(&buffer[curPos], keySize); 583 | curPos += 2; 584 | if(keySize) 585 | memcpy(&buffer[curPos], key.c_str(), keySize); 586 | val->Write(buffer); 587 | } 588 | } 589 | buffer.push_back(TAG_END); 590 | break; 591 | } 592 | case TAG_END: 593 | break; //for completeness 594 | } 595 | } 596 | 597 | void NBT_Value::Print(const std::string &name, int tabs) 598 | { 599 | for(int i=0;isize() << " bytes" << std::endl; 628 | else 629 | std::cout << "0 bytes" << std::endl; 630 | break; 631 | case TAG_STRING: 632 | std::cout << "TAG_String(\"" << name << "\"): "; 633 | if(m_value.stringVal != NULL) 634 | std::cout << *m_value.stringVal << std::endl; 635 | else 636 | std::cout << std::endl; 637 | break; 638 | case TAG_LIST: 639 | std::cout << "TAG_List(\"" << name << "\"): Type " << m_value.listVal.type << std::endl; 640 | if(m_value.listVal.data != NULL) 641 | { 642 | std::vector::iterator iter = m_value.listVal.data->begin(), end = m_value.listVal.data->end(); 643 | for( ; iter != end ; iter++ ) 644 | (*iter)->Print(std::string(""), tabs+1); 645 | } 646 | break; 647 | case TAG_COMPOUND: 648 | std::cout << "TAG_Compound(\"" << name << "\"):" << std::endl; 649 | if(m_value.compoundVal != NULL) 650 | { 651 | std::map::iterator iter = m_value.compoundVal->begin(), end = m_value.compoundVal->end(); 652 | for( ; iter != end; iter++) 653 | iter->second->Print(iter->first, tabs+1); 654 | } 655 | break; 656 | default: 657 | std::cout << "Invalid TAG:" << m_type << std::endl; 658 | } 659 | } 660 | 661 | -------------------------------------------------------------------------------- /src/mapgen.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2010 Drew Gottlieb - with code from fragmer and TkTech 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | // This code is modified from MySMP C# server by Drew Gottlieb 24 | // Thanks! 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "logger.h" 35 | #include "constants.h" 36 | 37 | #include "config.h" 38 | #include "nbt.h" 39 | #include "map.h" 40 | 41 | // libnoise 42 | #ifdef WIN32 43 | #include 44 | #else 45 | #include 46 | #endif 47 | #include "noiseutils.h" 48 | 49 | #include "mersenne.h" 50 | 51 | #include "mapgen.h" 52 | 53 | MapGen::MapGen(int seed) 54 | { 55 | blocks = new uint8[16*16*128]; 56 | blockdata = new uint8[16*16*128/2]; 57 | skylight = new uint8[16*16*128/2]; 58 | blocklight = new uint8[16*16*128/2]; 59 | heightmap = new uint8[16*16]; 60 | 61 | // 62 | // libnoise 63 | // 64 | perlinNoise.SetSeed(seed); 65 | perlinNoise.SetOctaveCount(3); 66 | perlinNoise.SetFrequency(1.0); // 1-16 67 | perlinNoise.SetPersistence(0.25); // 0-1 68 | 69 | perlinScale = 0.7f; 70 | 71 | terrainType.SetFrequency (0.5); 72 | terrainType.SetPersistence (0.15); 73 | 74 | baseFlatTerrain.SetFrequency(1.50); 75 | flatTerrain.SetSourceModule(0, baseFlatTerrain); 76 | flatTerrain.SetScale (0.125); 77 | flatTerrain.SetBias (0); 78 | 79 | 80 | finalTerrain.SetSourceModule(0, flatTerrain); 81 | finalTerrain.SetSourceModule(1, perlinNoise); 82 | finalTerrain.SetControlModule(terrainType); 83 | finalTerrain.SetBounds(0.0, 1000.0); 84 | finalTerrain.SetEdgeFalloff(0.125); 85 | 86 | // Generate heightmap 87 | heightMapBuilder.SetSourceModule(finalTerrain); 88 | heightMapBuilder.SetDestNoiseMap(heightMap); 89 | heightMapBuilder.SetDestSize(16, 16); 90 | 91 | oreDensity = Conf::get().iValue("oreDensity"); 92 | seaLevel = Conf::get().iValue("seaLevel"); 93 | 94 | m_seed = seed; 95 | } 96 | 97 | MapGen::~MapGen() 98 | { 99 | delete [] blocks; 100 | delete [] blockdata; 101 | delete [] skylight; 102 | delete [] blocklight; 103 | delete [] heightmap; 104 | } 105 | 106 | 107 | /*void MapGen::calculateHeightmap() 108 | { 109 | // uint8 block; uint8 meta; 110 | int index; 111 | 112 | for(char x = 0; x < 16; x++) 113 | { 114 | for(char z = 0; z < 16; z++) 115 | { 116 | for (char y = 127; y >= 0; y--) 117 | { 118 | index = y + (z * 128) + (x * 128 * 16); 119 | if(blocks[index] == BLOCK_AIR) 120 | continue; 121 | heightmap[getHeightmapIndex(x, z)] = (char)(y + 1); 122 | break; 123 | } 124 | } 125 | } 126 | } 127 | 128 | int MapGen::getHeightmapIndex(char x, char z) 129 | { 130 | return z + (x * 16); 131 | }*/ 132 | 133 | void MapGen::loadFlatgrass() 134 | { 135 | for (uint8 bX = 0; bX < 16; bX++) 136 | { 137 | for (uint8 bY = 0; bY < 128; bY++) 138 | { 139 | for (uint8 bZ = 0; bZ < 16; bZ++) 140 | { 141 | if (bY == 0) 142 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_BEDROCK; 143 | else if (bY < 64) 144 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_DIRT; 145 | else if (bY == 64) 146 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_GRASS; 147 | else 148 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_AIR; 149 | } 150 | } 151 | } 152 | //CalculateHeightmap(); 153 | } 154 | 155 | void MapGen::generateChunk(int x, int z) 156 | { 157 | NBT_Value *main = new NBT_Value(NBT_Value::TAG_COMPOUND); 158 | NBT_Value *val = new NBT_Value(NBT_Value::TAG_COMPOUND); 159 | 160 | if(Conf::get().bValue("map_flatland")) 161 | loadFlatgrass(); 162 | else 163 | generateWithNoise(x, z); 164 | 165 | val->Insert("Blocks", new NBT_Value(blocks, 16*16*128)); 166 | val->Insert("Data", new NBT_Value(blockdata, 16*16*128/2)); 167 | val->Insert("SkyLight", new NBT_Value(skylight, 16*16*128/2)); 168 | val->Insert("BlockLight", new NBT_Value(blocklight, 16*16*128/2)); 169 | val->Insert("HeightMap", new NBT_Value(heightmap, 16*16)); 170 | val->Insert("Entities", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND)); 171 | val->Insert("TileEntities", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND)); 172 | val->Insert("LastUpdate", new NBT_Value((sint64)time(NULL))); 173 | val->Insert("xPos", new NBT_Value(x)); 174 | val->Insert("zPos", new NBT_Value(z)); 175 | val->Insert("TerrainPopulated", new NBT_Value((char)1)); 176 | 177 | main->Insert("Level", val); 178 | 179 | uint32 chunkid; 180 | Map::get().posToId(x, z, &chunkid); 181 | 182 | Map::get().maps[chunkid].x = x; 183 | Map::get().maps[chunkid].z = z; 184 | 185 | std::vector *t_blocks = (*val)["Blocks"]->GetByteArray(); 186 | std::vector *t_data = (*val)["Data"]->GetByteArray(); 187 | std::vector *t_blocklight = (*val)["BlockLight"]->GetByteArray(); 188 | std::vector *t_skylight = (*val)["SkyLight"]->GetByteArray(); 189 | std::vector *heightmap = (*val)["HeightMap"]->GetByteArray(); 190 | 191 | Map::get().maps[chunkid].blocks = &((*t_blocks)[0]); 192 | Map::get().maps[chunkid].data = &((*t_data)[0]); 193 | Map::get().maps[chunkid].blocklight = &((*t_blocklight)[0]); 194 | Map::get().maps[chunkid].skylight = &((*t_skylight)[0]); 195 | Map::get().maps[chunkid].heightmap = &((*heightmap)[0]); 196 | 197 | // Update last used time 198 | Map::get().mapLastused[chunkid] = (int)time(0); 199 | 200 | // Not changed 201 | Map::get().mapChanged[chunkid] = 0; 202 | 203 | Map::get().maps[chunkid].nbt = main; 204 | } 205 | 206 | void MapGen::generateWithNoise(int x, int z) 207 | { 208 | // Ore arrays 209 | //uint8* oreX; 210 | //uint8* oreY; 211 | //uint8* oreZ; 212 | //uint8* oreType; 213 | 214 | heightMapBuilder.SetBounds(1000 + x*perlinScale, 1000 + (x+1)*perlinScale, 1000 + z*perlinScale, 1000 + (z+1)*perlinScale); 215 | heightMapBuilder.Build(); 216 | 217 | // Image render 218 | /*noise::utils::RendererImage renderer; 219 | noise::utils::Image image; 220 | renderer.SetSourceNoiseMap (heightMap); 221 | renderer.SetDestImage (image); 222 | renderer.Render (); 223 | 224 | noise::utils::WriterBMP writer; 225 | writer.SetSourceImage (image); 226 | writer.SetDestFilename ("tutorial.bmp"); 227 | writer.WriteDestFile ();*/ 228 | 229 | 230 | 231 | // Get cave heightmaps for upper caves (top & bottom) 232 | /*Noise caveTopNoise; 233 | Random rnd(randomSeed); 234 | caveTopNoise.init(randomSeed + rnd.uniform(RAND_MAX), caveTopNoise.Spline); 235 | caveTopNoise.PerlinNoiseMap(caveTop, 0, 4, 0.4f, x, z); 236 | caveTopNoise.Invert(caveTop); 237 | caveTopNoise.Marble(caveTop); 238 | 239 | Noise caveBottomNoise; 240 | Random rndBot(rnd.uniform(RAND_MAX)); 241 | caveBottomNoise.init(randomSeed + rndBot.uniform(RAND_MAX), caveBottomNoise.Spline); 242 | caveBottomNoise.PerlinNoiseMap(caveBottom, 0, 4, 0.2f, x, z); 243 | caveBottomNoise.Invert(caveBottom); 244 | caveBottomNoise.Marble(caveBottom); 245 | 246 | // Get cave heightmaps for lower caves (top & bottom) 247 | Noise caveTopNoise2; 248 | Random rnd2(randomSeed + 1); 249 | caveTopNoise2.init(randomSeed + rnd2.uniform(RAND_MAX), caveTopNoise2.Spline); 250 | caveTopNoise2.PerlinNoiseMap(caveTop2, 0, 4, 0.4f, x, z); 251 | caveTopNoise2.Invert(caveTop2); 252 | caveTopNoise2.Marble(caveTop2); 253 | 254 | Noise caveBottomNoise2; 255 | Random rnd3(randomSeed + 2); 256 | Random rnd4(rnd3.uniform(RAND_MAX) + 1); 257 | caveBottomNoise2.init(randomSeed + rnd4.uniform(RAND_MAX), caveBottomNoise2.Spline); 258 | caveBottomNoise2.PerlinNoiseMap(caveBottom2, 0, 4, 0.2f, x, z); 259 | caveBottomNoise2.Invert(caveBottom2); 260 | caveBottomNoise2.Marble(caveBottom2); 261 | 262 | // Determine whether there should be ore (random, not seed-related) and where it should be and what type 263 | int oreChance = rand()%9 + 1; // 1-10 264 | int numOre = 0; 265 | if (oreDensity >= 18) 266 | { 267 | if (oreChance <= 2) 268 | numOre = oreDensity; 269 | else if (oreChance <= 4) 270 | numOre = oreDensity - 4; 271 | else if (oreChance <= 8) 272 | numOre = oreDensity - 8; 273 | else if (oreChance <= 10) 274 | numOre = oreDensity - 12; 275 | } 276 | else 277 | numOre = oreDensity; 278 | 279 | oreX = new uint8[numOre]; 280 | oreY = new uint8[numOre]; 281 | oreZ = new uint8[numOre]; 282 | oreType = new uint8[numOre]; 283 | 284 | for(int i = 0; i < numOre; i++) 285 | { 286 | oreX[i] = (char)rand()%14 + 1; // 1-15 287 | oreY[i] = (char)rand()%63 + 1; // 1-64 288 | oreZ[i] = (char)rand()%14 + 1; // 1-15 289 | int oreTypeRand = rand()%19 + 1; // 1-20 290 | if(oreY[i] < 14) 291 | { 292 | if (oreTypeRand < 10) 293 | oreType[i] = BLOCK_REDSTONE_ORE; 294 | else 295 | oreType[i] = BLOCK_DIAMOND_ORE; 296 | } 297 | else 298 | { 299 | if (oreTypeRand <= 5 && oreY[i] < 30) 300 | oreType[i] = BLOCK_GOLD_ORE; 301 | else if (oreTypeRand <= 9) 302 | oreType[i] = BLOCK_IRON_ORE; 303 | else if (oreTypeRand <= 20) 304 | oreType[i] = BLOCK_COAL_ORE; 305 | } 306 | } 307 | */ 308 | // Populate blocks in chunk 309 | int currentHeight;//, caveTopHeight, caveBottomHeight, caveTopHeight2, caveBottomHeight2; 310 | for (uint8 bX = 0; bX < 16; bX++) 311 | { 312 | for (uint8 bY = 0; bY < 128; bY++) 313 | { 314 | for (uint8 bZ = 0; bZ < 16; bZ++) 315 | { 316 | currentHeight = (int)((heightMap.GetValue(bX,bZ) * 7.49674) + 64.15371); 317 | 318 | //currentHeight = (int)((heightMap[bX][bZ] * 2.49674) + 82.15371); 319 | 320 | /*caveTopHeight = (int)((caveTop[bX][bZ] * 4.29674) + 36.15371); 321 | caveBottomHeight = (int)((caveBottom[bX][bZ] * 2.29674) + 40.15371); 322 | caveTopHeight += (int)((float)currentHeight / 128.0 * 90.0) - 40; 323 | caveBottomHeight += (int)((float)currentHeight / 128.0 * 90.0) - 45; 324 | 325 | caveTopHeight2 = (int)((caveTop2[bX][bZ] * 4.29674) + 36.15371); 326 | caveBottomHeight2 = (int)((caveBottom2[bX][bZ] * 2.29674) + 40.15371); 327 | caveTopHeight2 += (int)((float)currentHeight / 128.0 * 100.0) - 70; 328 | caveBottomHeight2 += (int)((float)currentHeight / 128.0 * 100.0) - 75;*/ 329 | 330 | if(bY == 0) 331 | { 332 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_BEDROCK; 333 | } 334 | else 335 | { 336 | if(bY < currentHeight) 337 | { 338 | if (bY < (int)(currentHeight * 0.94)) 339 | { 340 | /*if(bY >= caveBottomHeight && bY <= caveTopHeight) 341 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_AIR; 342 | else if (bY >= caveBottomHeight2 && bY <= caveTopHeight2) 343 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_AIR; 344 | else 345 | { 346 | int veinDir = rand()%7 + 1; // 1-8 347 | */Block blockToPlace = BLOCK_STONE; 348 | 349 | /*for(int i = 0; i < numOre; i++) 350 | { 351 | if(oreType[i] == BLOCK_DIAMOND_ORE || oreType[i] == BLOCK_GOLD_ORE) { // Smaller deposits 352 | if (veinDir <= 2) 353 | { // Cube (2x2) 354 | if (oreX[i] < bX - 0) 355 | continue; 356 | if (oreX[i] > bX + 1) 357 | continue; 358 | if (oreY[i] < bY - 0) 359 | continue; 360 | if (oreY[i] > bY + 1) 361 | continue; 362 | if (oreZ[i] < bZ - 0) 363 | continue; 364 | if (oreZ[i] > bZ + 1) 365 | continue; 366 | } 367 | else if (veinDir <= 4) 368 | { // Long across X 369 | if (oreX[i] < bX - 0) 370 | continue; 371 | if (oreX[i] > bX + 2) 372 | continue; 373 | if (oreY[i] < bY - 0) 374 | continue; 375 | if (oreY[i] > bY + 1) 376 | continue; 377 | if (oreZ[i] < bZ - 0) 378 | continue; 379 | if (oreZ[i] > bZ + 1) 380 | continue; 381 | } 382 | else if (veinDir <= 6) 383 | { // Long across Z 384 | if (oreX[i] < bX - 0) 385 | continue; 386 | if (oreX[i] > bX + 1) 387 | continue; 388 | if (oreY[i] < bY - 0) 389 | continue; 390 | if (oreY[i] > bY + 1) 391 | continue; 392 | if (oreZ[i] < bZ - 0) 393 | continue; 394 | if (oreZ[i] > bZ + 2) 395 | continue; 396 | } 397 | else if (veinDir <= 8) 398 | { // Tall 399 | if (oreX[i] < bX - 0) 400 | continue; 401 | if (oreX[i] > bX + 1) 402 | continue; 403 | if (oreY[i] < bY - 0) 404 | continue; 405 | if (oreY[i] > bY + 2) 406 | continue; 407 | if (oreZ[i] < bZ - 0) 408 | continue; 409 | if (oreZ[i] > bZ + 1) 410 | continue; 411 | } 412 | } 413 | else 414 | { 415 | // Larger deposits 416 | if (veinDir <= 2) 417 | { // Cube (2x2) 418 | if (oreX[i] < bX - 0) 419 | continue; 420 | if (oreX[i] > bX + 1) 421 | continue; 422 | if (oreY[i] < bY - 0) 423 | continue; 424 | if (oreY[i] > bY + 1) 425 | continue; 426 | if (oreZ[i] < bZ - 0) 427 | continue; 428 | if (oreZ[i] > bZ + 1) 429 | continue; 430 | } 431 | else if (veinDir <= 4) 432 | { // Long across X 433 | if (oreX[i] < bX - 1) 434 | continue; 435 | if (oreX[i] > bX + 2) 436 | continue; 437 | if (oreY[i] < bY - 0) 438 | continue; 439 | if (oreY[i] > bY + 1) 440 | continue; 441 | if (oreZ[i] < bZ - 0) 442 | continue; 443 | if (oreZ[i] > bZ + 1) 444 | continue; 445 | } 446 | else if (veinDir <= 6) 447 | { // Long across Z 448 | if (oreX[i] < bX - 0) 449 | continue; 450 | if (oreX[i] > bX + 1) 451 | continue; 452 | if (oreY[i] < bY - 0) 453 | continue; 454 | if (oreY[i] > bY + 1) 455 | continue; 456 | if (oreZ[i] < bZ - 1) 457 | continue; 458 | if (oreZ[i] > bZ + 2) 459 | continue; 460 | } 461 | else if (veinDir <= 8) 462 | { // Tall 463 | if (oreX[i] < bX - 0) 464 | continue; 465 | if (oreX[i] > bX + 1) 466 | continue; 467 | if (oreY[i] < bY - 1) 468 | continue; 469 | if (oreY[i] > bY + 2) 470 | continue; 471 | if (oreZ[i] < bZ - 0) 472 | continue; 473 | if (oreZ[i] > bZ + 1) 474 | continue; 475 | } 476 | }*/ 477 | //blockToPlace = (Block)oreType[i]; 478 | //break; 479 | //} 480 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = blockToPlace; 481 | //} 482 | } 483 | else 484 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_DIRT; 485 | } 486 | else if (currentHeight == bY) 487 | { 488 | if (bY == seaLevel || bY == seaLevel - 1 || bY == seaLevel - 2) 489 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_SAND; // FF 490 | else if (bY < seaLevel - 1) 491 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_GRAVEL; // FF 492 | else 493 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_GRASS; // FF 494 | } 495 | else 496 | { 497 | if (bY <= seaLevel) 498 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_STATIONARY_WATER; // FF 499 | else 500 | blocks[bY + (bZ * 128 + (bX * 128 * 16))] = BLOCK_AIR; // FF 501 | } 502 | } 503 | } 504 | } 505 | } 506 | //CalculateHeightmap(); 507 | /*delete [] oreX; 508 | delete [] oreY; 509 | delete [] oreZ; 510 | delete [] oreType;*/ 511 | } 512 | --------------------------------------------------------------------------------