[
  {
    "path": ".gitignore",
    "content": "# ignore kate temp files\n*~\n\n# ignore cmake crap\nCMakeFiles\nCMakeCache.txt\nsrc/configure.h\ninclude/configure.h\n\n# ignore our compile directory\nbin\n\n# qmake .pro(ject) per platform config file\nsrc/mineserver.pro.user"
  },
  {
    "path": "CMakeLists.txt",
    "content": "CMAKE_MINIMUM_REQUIRED(VERSION 2.6)\nPROJECT(mineserver)\nCMAKE_POLICY(SET CMP0003 NEW)\n\n#\n# project version\n#\n\n# Justasic: Get the git revision location for the branch we're on\nif(EXISTS \"${${PROJECT_NAME}_SOURCE_DIR}/.git/HEAD\")\n  file(STRINGS ${${PROJECT_NAME}_SOURCE_DIR}/.git/HEAD GIT_HEAD_LOC REGEX \".*\")\n  #file(GIT_HEAD_LOC ${${PROJECT_NAME}_SOURCE_DIR}/.git/HEAD REGEX \".*\")\n  string(LENGTH ${GIT_HEAD_LOC} HEAD_LEN)\n  math(EXPR LEN \"${HEAD_LEN} - 5\")\n  string(SUBSTRING ${GIT_HEAD_LOC} 5 ${LEN} GIT_HEAD)\nendif(EXISTS \"${${PROJECT_NAME}_SOURCE_DIR}/.git/HEAD\")\n\n# Justasic: Get the git revision we're on for the version string\nif(EXISTS \"${${PROJECT_NAME}_SOURCE_DIR}/.git/${GIT_HEAD}\")\n  # Justasic: read_from_file(${${PROJECT_NAME}_SOURCE_DIR}/.git/${GIT_HEAD} \".*\" VERSION_STR)\n  file(STRINGS ${${PROJECT_NAME}_SOURCE_DIR}/.git/${GIT_HEAD} VERSION_STR REGEX \".*\")\n  # Justasic: Get the length of the string\n  string(LENGTH ${VERSION_STR} VERSION_LEN)\n  # Justasic: Subtract 7 from the string's length\n  math(EXPR VERSION_NUM_LEN \"${VERSION_LEN} - ${VERSION_LEN} + 7\")\n  # Justasic: Extract the value from the string\n  string(SUBSTRING ${VERSION_STR} 0 ${VERSION_NUM_LEN} VERSION_GIT)\nendif(EXISTS \"${${PROJECT_NAME}_SOURCE_DIR}/.git/${GIT_HEAD}\")\n\n# Set the actual version strings, these are used inside the program later\nSET(${PROJECT_NAME}_MAJOR_VERSION 0)\nSET(${PROJECT_NAME}_MINOR_VERSION 2)\nSET(${PROJECT_NAME}_PATCH_LEVEL 0)\n\n# Justasic: the rest is automatic\nSET(${PROJECT_NAME}_VERSION_SIMPLE \"${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}.${${PROJECT_NAME}_PATCH_LEVEL}\")\n# Justasic: Get the git revision as well, really only useful for locating what revision we're on\nSET(${PROJECT_NAME}_VERSION_COMPLETE \"${${PROJECT_NAME}_VERSION_SIMPLE}-${VERSION_GIT}\")\n\n# set default build to Debug\nIF(NOT CMAKE_BUILD_TYPE)\n  SET(CMAKE_BUILD_TYPE Debug\n    CACHE STRING \"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel.\"\n    FORCE\n  )\nENDIF(NOT CMAKE_BUILD_TYPE)\n\nSET(CMAKE_MODULE_PATH \"${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}\")\n\n#\n# Configure paths\n#\nSET(CONFIG_DIR_BIN   bin/)\nSET(CONFIG_DIR_ETC   etc/${PROJECT_NAME}/)\nSET(CONFIG_DIR_LIB   lib/${PROJECT_NAME}/)\nSET(CONFIG_DIR_SHARE ./)\nIF(WIN32)\n  MESSAGE(STATUS \"CONFIG_LOCAL is set -- assuming local build\")\n  SET(CONFIG_DIR_BIN   bin/)\n  SET(CONFIG_DIR_ETC   bin/)\n  SET(CONFIG_DIR_LIB   bin/)\n  SET(CONFIG_DIR_SHARE ./)\n  SET(CONFIG_PREFIX    ${CMAKE_INSTALL_PREFIX})\nENDIF()\n\n# The DISTSOURCE parameter tells the executable where to find the factory defaults.\n# It is used by Mineserver::configDirectoryPrepare() to install the factory defaults.\n# In the Release build, this should eventually be overridden by a central location\n# like $PREFIX/share/mineserver/files, I suppose.\nSET(CONFIG_DIR_DISTSOURCE files)\n\n#\n# Include directories\n#\nINCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src)\n\n# CMake crap to include\ninclude(CheckFunctionExists)\ninclude(CheckIncludeFile)\ninclude(CheckTypeSize)\ninclude(CheckLibraryExists)\ninclude(CheckCXXCompilerFlag)\n\n# functions/includes needed during compile\ncheck_function_exists(backtrace HAVE_BACKTRACE)\ncheck_include_file(sys/utsname.h HAVE_SYS_UTSNAME_H)\n\n# Output paths\nSET(EXECUTABLE_OUTPUT_PATH bin)\nSET(LIBRARY_OUTPUT_PATH bin)\n\n\n# Set compiler specific build flags\nIF(CMAKE_COMPILER_IS_GNUCXX)\n  SET(CMAKE_CXX_FLAGS \"-W -Wall -Wno-unused-variable -Wno-unused-parameter -pedantic -std=c++11\")\n  SET(CMAKE_CXX_FLAGS_DEBUG \"-DDEBUG -g -O0\")\n  SET(CMAKE_CXX_FLAGS_PROFILE \"-DDEBUG -g -pg\")\n  SET(CMAKE_CXX_FLAGS_RELEASE \"-O4 -s -DNDEBUG\")\nENDIF()\n\n\nIF(MSVC_IDE)\n  SET(CMAKE_CXX_FLAGS \"/DWIN32 /D_CONSOLE /DZLIB_WINAPI /fp:fast /EHsc\")\n  SET(CMAKE_CXX_FLAGS_DEBUG \"/DDEBUG /D_DEBUG /MTd /Zi\")\n  SET(CMAKE_CXX_FLAGS_RELEASE \"/MT /D_SECURE_SCL=0\")\nENDIF(MSVC_IDE)\n\n#\n# dependencies\n#\n\nSET(TARGET ${PROJECT_NAME})\nSET(mineserver_depends -lpthread)\n\n# Note that on Ubuntu systems, CMake's FindOpenSSL.cmake file does not define\n# all the proper defines, therefore our old and generic library finder does not\n# work like it should :< - Justasic\nFind_package(OpenSSL REQUIRED)\nFind_package(Event REQUIRED)\nFind_package(Noise REQUIRED)\nFind_package(ZLIB REQUIRED)\n\ninclude_directories(${ZLIB_INCLUDE_DIR} ${NOISE_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${EVENT_INCLUDE_DIR})\nLIST(APPEND mineserver_depends \"${ZLIB_LIBRARY};${NOISE_LIBRARY};${OPENSSL_LIBRARIES};${EVENT_LIBRARY}\")\n\n# preprocess configuration file\nCONFIGURE_FILE(${PROJECT_SOURCE_DIR}/src/configure.h.in ${PROJECT_BINARY_DIR}/src/configure.h)\n\n\n#\n# platform-specific tweaks\n#\nIF(WIN32)\n  # this requires WinMain() entry, disabled until console/GUI option is added\n  #set(exe \"WIN32\")\n\n  # this shouldn't be here, but can cmake find these .lib's?\n  # do we really need winmm?\n  FOREACH(lib ws2_32 winmm)\n    STRING(TOUPPER ${lib} LIB)\n    LIST(APPEND mineserver_depends \"${lib}\")\n    SET(${LIB}_LIBRARY \"${lib}\")\n  ENDFOREACH()\nELSE()\n  IF(NOISE_DIR_IS_LIBNOISE)\n    ADD_DEFINITIONS(-DLIBNOISE)\n  ENDIF()\nENDIF()\n\n#\n# Create some directories we need\n#\nFILE(MAKE_DIRECTORY \"${CONFIG_DIR_BIN}/plugins\")\n\n#\n# subdirectories to build\n#\nADD_SUBDIRECTORY(src)\nADD_SUBDIRECTORY(plugins)\nADD_SUBDIRECTORY(files)\n\n# In the Debug build, we provide a local config file.\n#IF(CMAKE_BUILD_TYPE MATCHES Debug)\n    #CONFIGURE_FILE(files/config.cfg \"${EXECUTABLE_OUTPUT_PATH}/config.cfg\" COPYONLY)\n    #CONFIGURE_FILE(files/item_alias.cfg \"${EXECUTABLE_OUTPUT_PATH}/item_alias.cfg\" COPYONLY)\n#ENDIF()\n\n#\n# install\n#\ninstall(FILES ${mineserver_configs}\n  DESTINATION ${CONFIG_DIR_ETC}/\n)\ninstall(DIRECTORY ${mineserver_dirs}\n  DESTINATION ${CONFIG_DIR_SHARE}/\n)\n\n\n#\n# cpack\n#\nset(CPACK_PACKAGE_VENDOR \"The Mineserver Project\")\nset(CPACK_DEBIAN_PACKAGE_MAINTAINER \"Mineserver Developers <developers@mineserver.be>\")\nset(CPACK_PACKAGE_DESCRIPTION_SUMMARY \"Mineserver - C++ Minecraft server software\")\nset(CPACK_PACKAGE_VERSION ${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}.${${PROJECT_NAME}_PATCH_LEVEL})\nset(CPACK_PACKAGE_VERSION_MAJOR ${${PROJECT_NAME}_MAJOR_VERSION})\nset(CPACK_PACKAGE_VERSION_MINOR ${${PROJECT_NAME}_MINOR_VERSION})\nset(CPACK_PACKAGE_VERSION_PATCH ${${PROJECT_NAME}_PATCH_LEVEL})\nset(CPACK_PACKAGE_INSTALL_DIRECTORY \"/usr/local/bin\")\n\ninclude(CPack)\n"
  },
  {
    "path": "CMakeModules/FindEvent.cmake",
    "content": "# This module defines\n# EVENT_LIBRARY\n# EVENT_FOUND, if false, libevent wasn't found \n# EVENT_INCLUDE_DIR, where to find the headers\n\nFIND_PATH(EVENT_INCLUDE_DIR event.h\n    $ENV{EVENT_DIR}/include\n    $ENV{EVENT_DIR}\n    ~/Library/Frameworks\n    /Library/Frameworks\n    /usr/local/include\n    /usr/include\n    /sw/include # Fink\n    /opt/local/include # DarwinPorts\n    /opt/csw/include # Blastwave\n    /opt/include\n    /usr/freeware/include\n)\n\nFIND_LIBRARY(EVENT_LIBRARY \n    NAMES event libevent\n    PATHS\n    $ENV{EVENT_DIR}/lib\n    $ENV{EVENT_DIR}\n    ~/Library/Frameworks\n    /Library/Frameworks\n    /usr/local/lib\n    /usr/lib\n    /sw/lib\n    /opt/local/lib\n    /opt/csw/lib\n    /opt/lib\n    /usr/freeware/lib64\n)\n\n\n# handle the QUIETLY and REQUIRED arguments and set EVENT_FOUND to TRUE if \n# all listed variables are TRUE\nINCLUDE(\"FindPackageHandleStandardArgs\")\nFIND_PACKAGE_HANDLE_STANDARD_ARGS(EVENT REQUIRED_VARS EVENT_LIBRARY EVENT_INCLUDE_DIR)\n"
  },
  {
    "path": "CMakeModules/FindNoise.cmake",
    "content": "# NOISE_LIBRARY\n# NOISE_FOUND, if false, libnoise wasn't found\n# NOISE_INCLUDE_DIR, where to find the headers\n# NOISE_DIR_IS_LIBNOISE, if true, include as libnoise/noise.h (Debian)\n\nforeach(header noise/noise.h libnoise/noise.h)\n    FIND_PATH(NOISE_INCLUDE_DIR ${header}\n        $ENV{NOISE_DIR}/include\n        $ENV{NOISE_DIR}\n        ~/Library/Frameworks\n        /Library/Frameworks\n        /usr/local/include\n        /usr/include\n        /sw/include # Fink\n        /opt/local/include # DarwinPorts\n        /opt/csw/include # Blastwave\n        /opt/include\n        /usr/freeware/include\n    )\n    if(NOISE_INCLUDE_DIR)\n      break()\n    endif()\nendforeach()\n\nif(EXISTS ${NOISE_INCLUDE_DIR}/libnoise/noise.h)\n  set(NOISE_DIR_IS_LIBNOISE True)\nendif()\n\nIF(CMAKE_SYSTEM_NAME MATCHES FreeBSD)\n set(CMAKE_FIND_LIBRARY_SUFFIXES_ORIG ${CMAKE_FIND_LIBRARY_SUFFIXES})\n set(CMAKE_FIND_LIBRARY_SUFFIXES \".so.0\")\nENDIF()\n\nFIND_LIBRARY(NOISE_LIBRARY \n    NAMES noise libnoise\n    PATHS\n    $ENV{NOISE_DIR}/lib\n    $ENV{NOISE_DIR}\n    ~/Library/Frameworks\n    /Library/Frameworks\n    /usr/local/lib\n    /usr/lib\n    /sw/lib\n    /opt/local/lib\n    /opt/csw/lib\n    /opt/lib\n    /usr/freeware/lib64\n)\n\nIF(CMAKE_SYSTEM_NAME MATCHES FreeBSD)\n set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_ORIG})\nENDIF()\n\n# handle the QUIETLY and REQUIRED arguments and set NOISE_FOUND to TRUE if \n# all listed variables are TRUE\nINCLUDE(\"FindPackageHandleStandardArgs\")\nFIND_PACKAGE_HANDLE_STANDARD_ARGS(NOISE REQUIRED_VARS NOISE_LIBRARY NOISE_INCLUDE_DIR)\n\n"
  },
  {
    "path": "CMakeModules/toolchain-i686-w64-mingw32.cmake",
    "content": "# the name of the target operating system\nset(CMAKE_SYSTEM_NAME Windows)\n\n# which compilers to use for C and C++\nset(CMAKE_C_COMPILER i686-w64-mingw32-gcc)\nset(CMAKE_CXX_COMPILER i686-w64-mingw32-g++)\nset(CMAKE_RC_COMPILER i686-w64-mingw32-windres)\n\n# here is the target environment located\nset(CMAKE_FIND_ROOT_PATH\n  /usr/i686-w64-mingw32\n  ~/i686-w64-mingw32\n)\n\n# adjust the default behaviour of the FIND_XXX() commands:\n# search headers and libraries in the target environment, search\n# programs in the host environment\nset(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)\nset(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)\nset(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM debian:jessie\n\nMAINTAINER Marko Viitanen <fador@iki.fi>\n\n    ENV PACKAGES libssl1.0.0 libevent-2.0 zlib1g systemd-sysv sysv-rc debconf passwd dpkg gnupg libnoise0\n    ENV TEMP_PACKAGES build-essential cmake git  libssl-dev libevent-dev zlib1g-dev libnoise-dev ca-certificates \n    ENV DEBIAN_FRONTEND=noninteractive\n    RUN apt-get update \\\n    && apt-get install -y --fix-missing --no-install-recommends --no-install-suggests $PACKAGES $TEMP_PACKAGES \\\n    && git clone --depth=1 git://github.com/fador/mineserver.git; \\\n        cd mineserver; \\\n        cmake .; \\        \n        make all;\\\n        make install; \\\n        make clean; \\\n    AUTO_PACKAGES=`apt-mark showauto`; \\\n    apt-get remove --purge --force-yes -y $TEMP_PACKAGES $AUTO_PACKAGES; \\\n        apt-get clean autoclean; \\\n        apt-get autoremove -y; \\\n        rm -rf /var/lib/{apt,dpkg,cache,log}/ ;\\\n        mkdir /var/mineserver; \\\n        cp -rf files/* /var/mineserver/; \\\n        cp -rf bin/* /var/mineserver/\n\nEXPOSE 25565\nENV PATH /usr/local/bin:$PATH\nVOLUME [\"/var/mineserver\"]\n\nWORKDIR /var/mineserver\nENTRYPOINT [\"mineserver\"]\nCMD [\"/etc/mineserver/config.cfg\",\"+system.path.home=\\\"/var/mineserver\\\"\",\"+system.path.plugins=\\\"/usr/local/bin/plugins\\\"\"]"
  },
  {
    "path": "LICENSE",
    "content": "   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n * Neither the name of the The Mineserver Project nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# Mineserver\n*by Fador & Nredor and others*\n\nCustom Minecraft server software written in C++.\n\nYou can find the core team from [#mineserver](https://web.libera.chat/#mineserver) in [Libera.Chat](https://libera.chat/) IRC network. Also mail to developers@mineserver.be will reach us.\n\n    Copyright (c) 2010-2016, The Mineserver Project\n\n**NOTICE:** Server still lacks features compared to original minecraft server.\n\n\n**Supported platforms**\n\n * Linux (CMake)\n * Windows (VS2013 project included, CMake not tested)\n \nServer has also been tested to build on Mac OS X and FreeBSD/PCBSD but we do not officially support those.\n\nWe are trying to minimize memory and CPU usage compared to original Java server.\n\n*Important:* The language is C++11, so you will need a reasonably modern\nC++ compiler. MS Visual C++ 12 and GCC 4.8 should be sufficient. The build system requires [cmake](http://www.cmake.org/).\n\n\n### Supported Minecraft version\n\n * Working with 1.8.9 client (protocol 47)\n\n### Features\n\n * Plugins (chatcommands, filelog, nether, passivemobs, etc..)\n * NBT parsing/saving\n * Lightmap generation\n * Config file\n * Normal mining/item spawning/item pickups\n * Basic physics for gravel and sand\n * Physics for water (currently revising this)\n * Flatland and terrain map generation (Also biomegen!)\n * Working chests, furnaces & signs\n * User validation from minecraft.net\n * Protocol Encryption\n\n### Configuration Notes\n\nAn example `config.cfg` file is located in the `files` subdirectory.\n\nThe config file sets three path names and one file name which are relevant to the server; with their example values they are:\n\n    system.path.data    = \"files\";\n    system.path.plugins = \"plugins\";\n    system.path.home    = \".\";\n    system.pid_file     = \"mineserver.pid\";\n\nThese paths may be either absolute or relative. The server requires a set of configuration files which are located in the `files` subdirectory\nof the distribution. \n\nThe plugin binaries must be manually placed in the appropriate location for the server to find them.\n\n\n### Bug Tracker / To Do / Roadmap\n\nWe use GitHub issue tracker and milestones.\nPlease check the wiki pages for details about the project status and development plans.\nCheck the [fork network](https://github.com/fador/mineserver/network) for the latest development status.\n\n### Compiling\n\nMineserver requires the following libraries:\n\n * [zlib 1.2.5](http://www.zlib.org)\n * [libevent 2.0.x](http://libevent.org/)\n * [libnoise 1.0](http://libnoise.sourceforge.net/)\n * [openssl/libssl](http://www.openssl.org/)\n * [pthread](http://en.wikipedia.org/wiki/POSIX_Threads)\n\n * Installing on Debian and Ubuntu:\n\n    `sudo apt-get install libssl libssl-dev libevent-2.0 libevent-dev zlib1g zlib1g-dev libnoise-dev`\n\n * Installing on CentOS and RHEL\n\n    `# Install EPEL (Extra Packages for Enterprise Linux)`\n    `sudo su -c 'rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm'`\n    `sudo yum install git libevent libevent-devel zlib zlib-devel libnoise-dev`\n\n * Installing on FreeBSD / PCBSD\n\n    `sudo pkg_add -r libevent`\n\n * Installing on Mac OS X\n    * Install libevent using your favourite tool, e.g., homebrew, fink or macports.\n    * Installing libnoise can be painful. Howerver, there is a homebrew formular\n      on [krono's homebrew fork](http://github.com/krono/homebrew).\n\n    So for homebrew do\n\n    `brew install libevent libnoise`\n\n\n**Compiling using Linux (cmake & make & g++):**\n\n * Download and extract source or use `git clone git://github.com/fador/mineserver.git`\n * Go to mineserver directory\n * Run `cmake .`\n * Run `make all`\n * Run server with `cd bin && ./mineserver`\n\n**Compiling using FreeBSD / PCBSD (cmake & gmake & g++):**\n\n * Download and extract source or use `git clone git://github.com/fador/mineserver.git`\n * Go to mineserver directory\n * Run `cmake .`\n * Run `gmake all`\n * Run server with `cd bin && ./mineserver`\n\n**Compiling using Windows (VS2013): (Might be outdated)**\n\n * Download and compile [zlib](http://www.zlib.org) or use [pre-built binaries](http://www.winimage.com/zLibDll/index.html)\n * Add zlib libraries to project (zlibstat.lib or zlibwapi.lib which requires also zlibwapi.dll in the same dir with the executable)\n * Download and compile [libevent 2.0.x](http://monkey.org/~provos/libevent/)\n * Download [libnoise 1.0](http://libnoise.sourceforge.net/) and add header/library files to project\n * Add libevent library to project (libevent2.lib)\n * Build\n * Run mineserver.exe\n \n * [Build Pack](http://mineserver.be/downloads/mineserver-VS2013_build_pack.zip) also available for easy compiling\n\n 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.\n\n    call \"%VS120COMNTOOLS%vsvars32.bat\"\n    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 libevent2.lib Ws2_32.lib /link /OUT:mineserver.exe /LIBPATH:\"ZLIB_LIB_DIR;LIBEVENT_LIB_DIR\"\n\n\n"
  },
  {
    "path": "files/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 2.6)\n# forbid running cmake from this subdir\nif(PROJECT_NAME STREQUAL \"Project\")\n  message(FATAL_ERROR \"\\nplease run cmake from the project's parent directory\\n\")\nendif()\n\n# Get all the current config files and such from the current directory\nFILE(GLOB mineserver_configs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.txt *.cfg)\nLIST(REMOVE_ITEM mineserver_configs \"CMakeLists.txt\")\nLIST(REMOVE_DUPLICATES mineserver_configs)\n\n# Install all the Recipes\nFILE(GLOB_RECURSE mineserver_recipes RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} \"recipes/*\")\nLIST(REMOVE_DUPLICATES mineserver_recipes)\n\n# copy configs for local usage\nFOREACH(path ${mineserver_configs} ${mineserver_recipes})\n  SET(dest \"${PROJECT_SOURCE_DIR}/bin/${path}\")\n  IF(NOT EXISTS ${dest})\n    MESSAGE(STATUS \"Configuring: ${dest}\")\n    CONFIGURE_FILE(${path} ${dest} COPYONLY)\n  ENDIF()\nENDFOREACH()"
  },
  {
    "path": "files/ENABLED_RECIPES.cfg",
    "content": "#Armour\narmour/helmet_leather\narmour/helmet_iron\narmour/helmet_gold\narmour/helmet_diamond\narmour/helmet_chain\narmour/chestplate_leather\narmour/chestplate_gold\narmour/chestplate_iron\narmour/chestplate_diamond\narmour/chestplate_chain\narmour/legging_leather\narmour/legging_gold\narmour/legging_iron\narmour/legging_diamond\narmour/legging_chain\narmour/boots_leather\narmour/boots_gold\narmour/boots_iron\narmour/boots_diamond\narmour/boots_chain\n\n#Food\nfood/bowls\nfood/mushroomstew\nfood/bread\nfood/apple_golden\nfood/cake\nfood/sugar\n\n#Materials\nmaterials/sticks\nmaterials/block_iron\nmaterials/block_gold\nmaterials/block_diamond\nmaterials/block_glowstone\nmaterials/block_wool\nmaterials/block_snow\nmaterials/block_clay\nmaterials/block_sandstone\nmaterials/ingots_diamond\nmaterials/ingots_iron\nmaterials/ingots_gold\nmaterials/block_brick\nmaterials/wood_planks_acacia\nmaterials/wood_planks_birch\nmaterials/wood_planks_dark_oak\nmaterials/wood_planks_jungle\nmaterials/wood_planks_oak\nmaterials/wood_planks_spruce\nmaterials/tnt\nmaterials/clay\n\n#Mechanism\nmechanism/door_wood\nmechanism/door_iron\nmechanism/pressure_wood\nmechanism/pressure_stone\nmechanism/button_stone\nmechanism/torch_redstone\nmechanism/lever\nmechanism/dispenser\nmechanism/note_block\n\n#Misc\nmisc/stairs_wood\nmisc/stairs_stone\nmisc/chest\nmisc/fence_acacia\nmisc/fence_birch\nmisc/fence_dark_oak\nmisc/fence_jungle\nmisc/fence_oak\nmisc/fence_spruce\nmisc/furnace\nmisc/ladder\nmisc/sign\nmisc/torch\nmisc/workbench\nmisc/bookshelf\nmisc/jukebox\nmisc/jackolantern\nmisc/painting\nmisc/paper\nmisc/book\nmisc/bed\n\n#Tools\ntools/axe_stone\ntools/axe_wood\ntools/pickaxe_wood\ntools/shovel_stone\ntools/shovel_wood\ntools/pickaxe_stone\ntools/axe_iron\ntools/axe_gold\ntools/axe_diamond\ntools/pickaxe_iron\ntools/pickaxe_gold\ntools/pickaxe_diamond\ntools/shears\ntools/shovel_iron\ntools/shovel_gold\ntools/shovel_diamond\ntools/hoe_wood\ntools/hoe_stone\ntools/hoe_iron\ntools/hoe_gold\ntools/hoe_diamond\ntools/flintsteel\ntools/bucket\ntools/compass\ntools/clock\ntools/fishingrod\n\n#Weapons\nweapons/sword_wood\nweapons/sword_stone\nweapons/sword_iron\nweapons/sword_gold\nweapons/sword_diamond\nweapons/bow\nweapons/arrows\n\n#Transport\ntransport/minecart\ntransport/minecart_powered\ntransport/minecart_storage\ntransport/minecart_tracks\ntransport/boat\n\n#Dyes\ndyes/red\ndyes/yellow\ndyes/orange\ndyes/cyan\ndyes/lightgrey\ndyes/grey\ndyes/lime\ndyes/pink\ndyes/white\ndyes/lightblue\ndyes/magenta\ndyes/purple\ndyes/yellow\n\n#Cloth\ncloth/black\ncloth/darkgreen\ncloth/lightgrey\ncloth/purple\ncloth/blue\ncloth/grey\ncloth/magenta\ncloth/red\ncloth/brown\ncloth/lightblue\ncloth/orange\ncloth/white\ncloth/cyan\ncloth/lightgreen\ncloth/pink\ncloth/yellow\n\n#block\nblock/sand_hslab\nblock/smooth_hslab\nblock/stone_hslab\nblock/wood_hslab\n\n"
  },
  {
    "path": "files/banned.txt",
    "content": "# This is default banfile. Write nicks to be banned here one for each line\n"
  },
  {
    "path": "files/commands.cfg",
    "content": "# command permissions\n# the order is: guest < member < op < admin\n# e.g. \"kick\" is allowed for op & above (ops & admins)\n\nload         = admin\nunload       = admin\nreload       = admin\nsave         = admin\nsettime      = admin\nregen        = admin\nadminonlymsg = admin\n\nkick         = op\ntp           = op\nctp          = op\nban          = op\nunban        = op\ngive         = op\nigive        = op\nmute         = op\nunmute       = op\nsethealth    = op\nservermsg    = op\n\nkit          = member\nwhisper      = member\ngps          = member\n\nabout        = guest\nmotd         = guest\nhelp         = guest\nwho          = guest\nhome         = guest\nrules        = guest\ndnd          = guest\nemote        = guest\n"
  },
  {
    "path": "files/config.cfg",
    "content": "#\n# Mineserver configuration\n#\n\n# Search paths\n# Note: leading tilde '~' is treated as $HOME\nsystem.path.data    = \".\";\nsystem.path.plugins = \"plugins\";\nsystem.path.home    = \".\";\nsystem.pid_file     = \"mineserver.pid\";\n\n# Include item alias config file\ninclude \"item_alias.cfg\";\n\n# Interface.\nsystem.interface.use_cli = true;\n\n# Server name\nsystem.server_name = \"Mineserver testserver\";\n\n# Validate usernames against minecraft.net\n# false means \"offline\" mode\nsystem.user_validation = true;\n\n# Encryption required for validation\n# will encrypt the whole protocol with AES/CFB8\n# Offline mode will work with encryption\n# Recommendation: DONT CHANGE\nsystem.protocol_encryption = true;\n\n# Disclose Software Version\nsystem.show_version = true; \n\n# Userlimit\nsystem.user_limit = 50;\n\n# IP\nnet.ip = \"0.0.0.0\";\n\n# Port\nnet.port = 25565;\n\n\n# Server administrator authentication password\n# Used for core commands like shutdown and loadplugin\n# using \"/auth password\" will make you an admin\n# NOTE: default \"CHANGEME\" is ignored, so change this only if you want to use it.\nsystem.admin.password = \"CHANGEME\";\n\n# 0 = Normal Map\n# 1 = Nether Map\n# ...\n# Map directory : Generator\nmap.storage.nbt.directories= ();\n# WORLD ARE LOADED ALPHABETICALLY. you have been warned ;P\n\n# Generators: \n# 0 - old generator\n# 1 - nether generator\n# 2 - heaven generator\n# 3 - new (biome) generator\n# 4 - mapgen by Eximius\n\n#map.storage.nbt.directories += (\"B-nether\":1);\n#map.storage.nbt.directories += (\"Cheaven\":2);\nmap.storage.nbt.directories += (\"A-world\":3);\n\n# Localization strings\nstrings.wrong_protocol = \"Wrong protocol version\";\nstrings.server_full = \"Server is currently full\";\n\n# Physics options (water/lava)\nsystem.physics.enabled = false;\n\n# Redstone options (EXPERIMENTAL)\nsystem.redstone.enabled = true;\n\n# Enable PvP ?\nsystem.pvp.enabled = true;\n\n# Enable area damage?\nsystem.damage.enabled = true;\n\n# true = Only helmets in helmet slot, false = any block in helmet slot (fun!)\nsystem.armour.helmet_strict = true;\n\nfurnace.items.stone = (\"in\":4, \"out\":1, \"meta\":0, \"count\":1);\nfurnace.items.gold = (\"in\":14, \"out\":266, \"meta\":0, \"count\":1);\nfurnace.items.iron = (\"in\":15, \"out\":265, \"meta\":0, \"count\":1);\nfurnace.items.charcoal = (\"in\":17, \"out\":263, \"meta\":1, \"count\":1);\nfurnace.items.diamond = (\"in\":56, \"out\":264, \"meta\":0, \"count\":1);\nfurnace.items.lapiz = (\"in\":21, \"out\":351, \"meta\":4, \"count\":6);\nfurnace.items.glass = (\"in\":12, \"out\":20, \"meta\":0, \"count\":1);\nfurnace.items.pork = (\"in\":319, \"out\":320, \"meta\":0, \"count\":1);\nfurnace.items.clay = (\"in\":337, \"out\":336, \"meta\":0, \"count\":1);\nfurnace.items.fish = (\"in\":349, \"out\":350, \"meta\":0, \"count\":1);\nfurnace.items.cactus = (\"in\": 81, \"out\":351, \"meta\":2, \"count\":1);\n\n# Save generated chunks which are not changed?\n#  Will generate the chunks again if false.\nmap.save_unchanged_chunks = true;\n\n# Map save interval in seconds, 0 = off\nmap.save_interval = 1800;\n\n#\n# Map generator parameters\n#\n\n\n# Generate spawn area in advance\nmap.generate_spawn.enabled = true;\nmap.generate_spawn.size = 5;\nmap.generate_spawn.show_progress = true;\n\n# Threading (how many concurrent generators running) !!NOT IN USE!!\nmapgen.threads = 2;\n\n# Time that grass takes to spread to the next block, in seconds\n# Please note that zero is a VERY bad idea.\nmapgen.grassrate = 10;\nmapgen.croprate = 10;\nmapgen.cactusrate = 10;\nmapgen.reedrate = 10;\n# Max height\nmapgen.cactusmax = 4; \nmapgen.reedmax = 5;\n\n\n# Generate flatgrass map instead of normal map\nmapgen.flatgrass = false;\n\n# Snow instead of grass\nmapgen.winter.enabled = false;\n\n# Sea level\nmapgen.sea.level = 62;\n\n# Add Ore\nmapgen.addore = true;\n\n# Generate trees\nmapgen.trees.enabled = true;\n\n# Generate caves\nmapgen.caves.enabled = false;\n\n# Smaller number = smaller caves\nmapgen.caves.size = 15;\n\n# Do not modify if not sure what this is\n# Used in: if(caveNoise.GetValue(x,y,z) < caveTreshold)\nmapgen.caves.treshold = 0.05;\n\nmapgen.caves.lava = true;\n\n# Expand beaches (Experimental)\nmapgen.beaches.expand = false;\nmapgen.beaches.extent = 10;\nmapgen.beaches.height = 2;\n\n# Plugin loading\n#\n# The syntax is as follows:\n#   system.plugins += (\"<name>\");\n#   system.plugins += (\"<alias>\" : \"<name>\");\n# Alternatively you can do this:\n#   system.plugins.<alias> = \"<name>\";\n#\n# Plugins are to be found under 'system.path.plugins' path\n#\n# If you use the second syntax, you're limited to [a-zA-Z0-9_]+ for the alias.\n# It's probably not a great idea to use any characters other than that anyway.\n#\n# <alias>\n# The plugin alias is whatever you like, it will be passed to the plugin so it\n# can use it as a sort of instance name. For example if you have two different\n# ban lists (for some reason), you could have them both operating at once by\n# giving them unique identifiers.\n#\n# <name>\n# Plugin name. If it starts with underscore '_' character, mineserver tries to\n# load it from within the main binary. Instructions on how to compile plugins\n# into mineserver are pending, but it basically involves just compiling the\n# plugin to an object file then linking it to the mineserver binary when it's\n# built.\n#\n# More information on this topic will be covered on the wiki Soon (tm).\n\nsystem.plugins = ();\n#system.plugins += (\"binlog\");\n#system.plugins += (\"banlist\");\nsystem.plugins += (\"commands\");\n#system.plugins += (\"crapMobs\");\n#system.plugins += (\"cursesui\");\nsystem.plugins += (\"filelog\");\nsystem.plugins += (\"flatpermissions\");\nsystem.plugins += (\"nBreak\");\nsystem.plugins += (\"nether\");\nsystem.plugins += (\"passiveMobs\");\n#system.plugins += (\"whitelist\");\n"
  },
  {
    "path": "files/item_alias.cfg",
    "content": "#\n# Aliases for /give and other labels\n#\n\nstone = 1\ngrass = 2\ndirt = 3\ncobblestone = 4\nwoodenplank = 5\nsapling = 6\nbedrock = 7\nwater = 8\nstatwater = 9\nlava = 10\nstatlava = 11\nsand = 12\ngravel = 13\ngoldore = 14\nironore = 15\ncoalore = 16\nwood = 17\nleaves = 18\nsponge = 19\nglass = 20\nlapisore = 21\nlapisblock = 22\ndispenser = 23\nsandstone = 24\nnoteblock = 25\nbed = 26\nwool = 35\nyellowflower = 37\nredrose = 38\nbrownmushroom = 39\nredmushroom = 40\ngoldblock = 41\nironblock = 42\ndoublestoneslab = 43\nstoneslab = 44\nbrickblock = 45\ntnt = 46\nbookshelf = 47\nmossstone = 48\nobsidian = 49\ntorch = 50\nfire = 51\nmonsterspawner = 52\nwoodenstairs = 53\nchest = 54\nredstonewire = 55\ndiamondore = 56\ndiamondblock = 57\nworkbench = 58\ncrops = 59\nfarmland = 60\nfurnace = 61\nladder = 65\ntracks = 66\ncobblestonestairs = 67\nlever = 69\nstonepressureplate = 70\nwoodenpressureplate = 72\nredstoneore = 73\nredstonetorch = 75\nstonebutton = 77\nsnow = 78\nice = 79\nsnowblock = 80\ncactus = 81\nclay = 82\nsugarcane = 83\njukebox = 84\nfence = 85\npumpkin = 86\nnetherrack = 87\nsoulsand = 88\nglowstone = 89\njackolantern = 91\ncakeblock = 92\n\n# items\nironshovel = 256\nironpickaxe = 257\nironaxe = 258\nflintandsteel = 259\napple = 260\nbow = 261\narrow = 262\ncoal = 263\ndiamond = 264\nironingot = 265\ngoldingot = 266\nironsword = 267\nwoodensword = 268\nwoodenshovel = 269\nwoodenpickaxe = 270\nwoodenaxe = 271\nstonesword = 272\nstoneshovel = 273\nstonepickaxe = 274\nstoneaxe = 275\ndiamondsword = 276\ndiamondshovel = 277\ndiamondpickaxe = 278\ndiamondaxe = 279\nstick = 280\nbowl = 281\nmushroomsoup = 282\ngoldsword = 283\ngoldshovel = 284\ngoldpickaxe = 285\ngoldaxe = 286\nstring = 287\nfeather = 288\nsulphur = 289\nwoodenhoe = 290\nstonehoe = 291\nironhoe = 292\ndiamondhoe = 293\ngoldhoe = 294\nseeds = 295\nwheat = 296\nbread = 297\nleatherhelmet = 298\nleatherchestplate = 299\nleatherleggings = 300\nleatherboots = 301\nchainmailhelmet = 302\nchainmailchestplate = 303\nchainmailaleggings = 304\nchainmailboots = 305\nironhelmet = 306\nironchestplate = 307\nironleggings = 308\nironboots = 309\ndiamondhelmet = 310\ndiamondchestplate = 311\ndiamondleggings = 312\ndiamondboots = 313\ngoldhelmet = 314\ngoldchestplate = 315\ngoldleggings = 316\ngoldboots = 317\nflint = 318\nrawporkchop = 319\ngrilledporkchop = 320\npaintings = 312\ngoldenapple = 322\nsign = 323\nwoodendoor = 324\nbucket = 325\nwaterbucket = 326\nlavabucket = 327\nminecart = 328\nsaddle = 329\nirondoor = 330\nredstone = 331\nsnowball = 332\nboat = 333\nleather = 334\nmilk = 335\nclaybrick = 336\nclayballs = 337\nsugarcane = 338\npaper = 339\nbook = 340\nslimeball = 341\nstorageminecart = 342\npoweredminecart = 343\negg = 344\ncompass = 345\nfishingrod = 346\nclock = 347\nglowstonedust = 348\nrawfish = 349\ncookedfish = 350\ninksac = 351\nbone = 352\nsugar = 353\ncake = 354\nbed = 355\nbrewingstand = 379\ngoldrecord = 2256\ngreenrecord = 2257\n"
  },
  {
    "path": "files/motd.txt",
    "content": "#\n# Write message of the day here. \n# Lines beginning with # are commentlines and will not be sent to player\n#\n> §aWelcome to Mineserver!\n> §bThis is MOTD\n> §fThis is third line of MOTD :E"
  },
  {
    "path": "files/permissions.txt",
    "content": "someMemberName:Member\nsomeOpName:Op\nsomeAdminName:Admin\n"
  },
  {
    "path": "files/recipes/armour/boots_chain.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n51 -1 51\n51 -1 51\n->\n\n# Output\noutputcount 1\noutputtype 305\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/boots_diamond.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n264 -1 264\n264 -1 264\n->\n\n# Output\noutputcount 1\noutputtype 313\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/boots_gold.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n266 -1 266\n266 -1 266\n->\n\n# Output\noutputcount 1\noutputtype 317\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/boots_iron.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n265 -1 265\n265 -1 265\n->\n\n# Output\noutputcount 1\noutputtype 309\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/boots_leather.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n334 -1 334\n334 -1 334\n->\n\n# Output\noutputcount 1\noutputtype 301\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/chestplate_chain.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n51 -1 51\n51 51 51\n51 51 51\n->\n\n# Output\noutputcount 1\noutputtype 303\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/chestplate_diamond.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n264 -1 264\n264 264 264\n264 264 264\n->\n\n# Output\noutputcount 1\noutputtype 311\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/chestplate_gold.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n266 -1 266\n266 266 266\n266 266 266\n->\n\n# Output\noutputcount 1\noutputtype 315\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/chestplate_iron.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n265 -1 265\n265 265 265\n265 265 265\n->\n\n# Output\noutputcount 1\noutputtype 307\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/chestplate_leather.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n334 -1 334\n334 334 334\n334 334 334\n->\n\n# Output\noutputcount 1\noutputtype 299\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/helmet_chain.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n51 51 51\n51 -1 51\n->\n\n# Output\noutputcount 1\noutputtype 302\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/helmet_diamond.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n264 264 264\n264 -1 264\n->\n\n# Output\noutputcount 1\noutputtype 310\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/helmet_gold.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n266 266 266\n266 -1 266\n->\n\n# Output\noutputcount 1\noutputtype 314\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/helmet_iron.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n265 265 265\n265 -1 265\n->\n\n# Output\noutputcount 1\noutputtype 306\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/helmet_leather.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n334 334 334\n334 -1 334\n->\n\n# Output\noutputcount 1\noutputtype 298\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/legging_chain.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n51 51 51\n51 -1 51\n51 -1 51\n->\n\n# Output\noutputcount 1\noutputtype 304\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/legging_diamond.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n264 264 264\n264 -1 264\n264 -1 264\n->\n\n# Output\noutputcount 1\noutputtype 312\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/legging_gold.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n266 266 266\n266 -1 266\n266 -1 266\n->\n\n# Output\noutputcount 1\noutputtype 316\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/legging_iron.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n265 265 265\n265 -1 265\n265 -1 265\n->\n\n# Output\noutputcount 1\noutputtype 308\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/armour/legging_leather.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n334 334 334\n334 -1 334\n334 -1 334\n->\n\n# Output\noutputcount 1\noutputtype 300\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/block/sand_hslab.recipe",
    "content": "# Input\nwidth 3\nheight 1\n<-\n24  24  24\n->\n\n# Output\noutputcount 3\noutputtype 44\noutputhealth 1\n"
  },
  {
    "path": "files/recipes/block/smooth_hslab.recipe",
    "content": "# Input\nwidth 3\nheight 1\n<-\n1  1  1\n->\n\n# Output\noutputcount 3\noutputtype 44\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/block/stone_hslab.recipe",
    "content": "# Input\nwidth 3\nheight 1\n<-\n4  4  4\n->\n\n# Output\noutputcount 3\noutputtype 44\noutputhealth 3\n"
  },
  {
    "path": "files/recipes/block/wood_hslab.recipe",
    "content": "# Input\nwidth 3\nheight 1\n<-\n5  5  5\n->\n\n# Output\noutputcount 3\noutputtype 44\noutputhealth 2\n"
  },
  {
    "path": "files/recipes/cloth/black.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:0\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 15\n"
  },
  {
    "path": "files/recipes/cloth/blue.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:4\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 11\n"
  },
  {
    "path": "files/recipes/cloth/brown.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:3\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 12\n"
  },
  {
    "path": "files/recipes/cloth/cyan.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:6\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 9\n"
  },
  {
    "path": "files/recipes/cloth/darkgreen.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:2\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 13\n"
  },
  {
    "path": "files/recipes/cloth/grey.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:8\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 7\n"
  },
  {
    "path": "files/recipes/cloth/lightblue.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:12\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 3\n"
  },
  {
    "path": "files/recipes/cloth/lightgreen.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:10\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 5\n"
  },
  {
    "path": "files/recipes/cloth/lightgrey.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:7\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 8\n"
  },
  {
    "path": "files/recipes/cloth/magenta.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:13\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 2\n"
  },
  {
    "path": "files/recipes/cloth/orange.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:14\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 1\n"
  },
  {
    "path": "files/recipes/cloth/pink.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:9\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 6\n"
  },
  {
    "path": "files/recipes/cloth/purple.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:5\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 10\n"
  },
  {
    "path": "files/recipes/cloth/red.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:1\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 14\n"
  },
  {
    "path": "files/recipes/cloth/white.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:15\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/cloth/yellow.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n35 351:11\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 4\n"
  },
  {
    "path": "files/recipes/dyes/cyan.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:4 351:2\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 6\n"
  },
  {
    "path": "files/recipes/dyes/grey.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:0 351:15\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 8\n"
  },
  {
    "path": "files/recipes/dyes/lightblue.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:4 351:15\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 12\n"
  },
  {
    "path": "files/recipes/dyes/lightgrey.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:8 351:15\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 7\n"
  },
  {
    "path": "files/recipes/dyes/lime.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:2 351:15\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 10\n"
  },
  {
    "path": "files/recipes/dyes/magenta.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:5 351:9\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 13\n"
  },
  {
    "path": "files/recipes/dyes/orange.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:1 351:11\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 14\n"
  },
  {
    "path": "files/recipes/dyes/pink.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:1 351:15\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 9\n"
  },
  {
    "path": "files/recipes/dyes/purple.recipe",
    "content": "# Input\nwidth 2\nheight 1\n\n<-\n351:4 351:1\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 5\n"
  },
  {
    "path": "files/recipes/dyes/red.recipe",
    "content": "# Input\nwidth 1\nheight 1\n\n<-\n38\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 1\n"
  },
  {
    "path": "files/recipes/dyes/white.recipe",
    "content": "# Input\nwidth 1\nheight 1\n\n<-\n352\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 15\n"
  },
  {
    "path": "files/recipes/dyes/yellow.recipe",
    "content": "# Input\nwidth 1\nheight 1\n\n<-\n37\n->\n\n# Output\noutputcount 2\noutputtype 351\noutputhealth 11\n"
  },
  {
    "path": "files/recipes/food/apple_golden.recipe",
    "content": "# Input\nwidth 3\nheight 3\n\n<-\n41 41 41\n41 260 41\n41 41 41\n->\n\n# Output\noutputcount 1\noutputtype 322\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/food/bowls.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5 -1 5\n-1 5 -1\n->\n\n# Output\noutputcount 4\noutputtype 281\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/food/bread.recipe",
    "content": "# Input\nwidth 3\nheight 1\n\n<-\n296 296 296\n->\n\n# Output\noutputcount 1\noutputtype 297\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/food/cake.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n335 335 335\n353 344 353\n296 296 296\n->\n\n# Output\noutputcount 1\noutputtype 354\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/food/mushroomstew.recipe",
    "content": "# Input\nwidth 1\nheight 3\n\n<-\n40\n39\n281\n->\n\n# Output\noutputcount 1\noutputtype 282\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/food/sugar.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n338\n->\n\n# Output\noutputcount 1\noutputtype 353\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_brick.recipe",
    "content": "# Input\nwidth 2\nheight 2\n\n<-\n336 336\n336 336\n->\n\n# Output\noutputcount 1\noutputtype 45\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_clay.recipe",
    "content": "# Input\nwidth 2\nheight 2\n\n<-\n337 337\n337 337\n->\n\n# Output\noutputcount 1\noutputtype 82\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_diamond.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n264 264 264\n264 264 264\n264 264 264\n->\n\n# Output\noutputcount 1\noutputtype 57\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_glowstone.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n348 348 348\n348 348 348\n348 348 348\n->\n\n# Output\noutputcount 1\noutputtype 89\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_gold.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n266 266 266\n266 266 266\n266 266 266\n->\n\n# Output\noutputcount 1\noutputtype 41\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_iron.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n265 265 265\n265 265 265\n265 265 265\n->\n\n# Output\noutputcount 1\noutputtype 42\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_sandstone.recipe",
    "content": "# Input\nwidth 2\nheight 2\n<-\n12 12\n12 12\n->\n\n# Output\noutputcount 1\noutputtype 24\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_snow.recipe",
    "content": "# Input\nwidth 2\nheight 2\n\n<-\n332 332\n332 332\n->\n\n# Output\noutputcount 1\noutputtype 80\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/block_wool.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n287 287 287\n287 287 287\n287 287 287\n->\n\n# Output\noutputcount 1\noutputtype 23\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/clay.recipe",
    "content": "# Input\nwidth 1\nheight 1\n\n<-\n82\n->\n\n# Output\noutputcount 4\noutputtype 337\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/ingots_diamond.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n57\n->\n\n# Output\noutputcount 9\noutputtype 264\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/ingots_gold.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n41\n->\n\n# Output\noutputcount 9\noutputtype 266\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/ingots_iron.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n42\n->\n\n# Output\noutputcount 9\noutputtype 265\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/sticks.recipe",
    "content": "# Input\nwidth 1\nheight 2\n<-\n5\n5\n->\n\n# Output\noutputcount 4\noutputtype 280\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/tnt.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n289 12 289\n12 289 12\n289 12 289\n->\n\n# Output\noutputcount 1\noutputtype 46\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/wood_planks_acacia.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n162:0\n->\n\n# Output\noutputcount 4\noutputtype 5\noutputhealth 4\n"
  },
  {
    "path": "files/recipes/materials/wood_planks_birch.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n17:2\n->\n\n# Output\noutputcount 4\noutputtype 5\noutputhealth 2\n"
  },
  {
    "path": "files/recipes/materials/wood_planks_dark_oak.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n162:1\n->\n\n# Output\noutputcount 4\noutputtype 5\noutputhealth 5\n"
  },
  {
    "path": "files/recipes/materials/wood_planks_jungle.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n17:3\n->\n\n# Output\noutputcount 4\noutputtype 5\noutputhealth 3\n"
  },
  {
    "path": "files/recipes/materials/wood_planks_oak.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n17:0\n->\n\n# Output\noutputcount 4\noutputtype 5\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/materials/wood_planks_spruce.recipe",
    "content": "# Input\nwidth 1\nheight 1\n<-\n17:1\n->\n\n# Output\noutputcount 4\noutputtype 5\noutputhealth 1\n"
  },
  {
    "path": "files/recipes/mechanism/button_stone.recipe",
    "content": "# Input\nwidth 1\nheight 2\n<-\n1\n1\n->\n\n# Output\noutputcount 1\noutputtype 77\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/dispenser.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n4 4 4\n4 261 4\n4 55 4\n->\n\n# Output\noutputcount 1\noutputtype 23\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/door_iron.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n265 265\n265 265\n265 265\n->\n\n# Output\noutputcount 1\noutputtype 330\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/door_wood.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n5 5\n5 5\n5 5\n->\n\n# Output\noutputcount 1\noutputtype 324\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/lever.recipe",
    "content": "# Input\nwidth 1\nheight 2\n<-\n280\n4\n->\n\n# Output\noutputcount 1\noutputtype 69\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/note_block.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n5 5 5\n5 55 5\n5 5 5\n->\n\n# Output\noutputcount 1\noutputtype 25\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/pressure_stone.recipe",
    "content": "# Input\nwidth 2\nheight 1\n<-\n1 1\n->\n\n# Output\noutputcount 1\noutputtype 70\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/pressure_wood.recipe",
    "content": "# Input\nwidth 2\nheight 1\n<-\n5 5\n->\n\n# Output\noutputcount 1\noutputtype 72\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/mechanism/torch_redstone.recipe",
    "content": "# Input\nwidth 1\nheight 2\n<-\n331\n280\n->\n\n# Output\noutputcount 1\noutputtype 76\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/bed.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n35 35 35\n5 5 5\n->\n\n# Output\noutputcount 1\noutputtype 355\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/book.recipe",
    "content": "# Input\nwidth 1\nheight 3\n\n<-\n339 339 339\n->\n\n# Output\noutputcount 1\noutputtype 340\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/bookshelf.recipe",
    "content": "# Input\nwidth 3\nheight 3\n\n<-\n5 5 5\n340 340 340\n5 5 5\n->\n\n# Output\noutputcount 1\noutputtype 47\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/chest.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n5 5 5\n5 -1 5\n5 5 5\n->\n\n# Output\noutputcount 1\noutputtype 54\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/fence_acacia.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5:4 280 5:4\n5:4 280 5:4\n->\n\n# Output\noutputcount 3\noutputtype 192\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/fence_birch.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5:2 280 5:2\n5:2 280 5:2\n->\n\n# Output\noutputcount 3\noutputtype 189\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/fence_dark_oak.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5:5 280 5:5\n5:5 280 5:5\n->\n\n# Output\noutputcount 3\noutputtype 191\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/fence_jungle.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5:3 280 5:3\n5:3 280 5:3\n->\n\n# Output\noutputcount 3\noutputtype 190\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/fence_oak.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5:0 280 5:0\n5:0 280 5:0\n->\n\n# Output\noutputcount 3\noutputtype 85\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/fence_spruce.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5:1 280 5:1\n5:1 280 5:1\n->\n\n# Output\noutputcount 3\noutputtype 188\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/furnace.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n4 4 4\n4 -1 4\n4 4 4\n->\n\n# Output\noutputcount 1\noutputtype 61\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/jackolantern.recipe",
    "content": "# Input\nwidth 1\nheight 2\n\n<-\n86\n50\n->\n\n# Output\noutputcount 1\noutputtype 91\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/jukebox.recipe",
    "content": "# Input\nwidth 3\nheight 3\n\n<-\n5 5 5\n5 264 5\n5 5 5\n->\n\n# Output\noutputcount 1\noutputtype 84\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/ladder.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n280 -1 280\n280 280 280\n280 -1 280\n->\n\n# Output\noutputcount 2\noutputtype 65\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/painting.recipe",
    "content": "# Input\nwidth 3\nheight 3\n\n<-\n280 280 280\n280 26 280\n280 280 280\n->\n\n# Output\noutputcount 1\noutputtype 321\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/paper.recipe",
    "content": "# Input\nwidth 3\nheight 1\n\n<-\n338 338 338\n->\n\n# Output\noutputcount 3\noutputtype 339\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/sign.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n 5   5  5\n 5   5  5\n-1 280 -1\n->\n\n# Output\noutputcount 1\noutputtype 323\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/stairs_stone.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n4 -1 -1\n4  4 -1\n4  4  4\n->\n\n# Output\noutputcount 4\noutputtype 67\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/stairs_wood.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n5 -1 -1\n5  5 -1\n5  5  5\n->\n\n# Output\noutputcount 4\noutputtype 53\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/torch.recipe",
    "content": "# Input\nwidth 1\nheight 2\n<-\n263\n280\n->\n\n# Output\noutputcount 4\noutputtype 50\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/misc/workbench.recipe",
    "content": "# Input\nwidth 2\nheight 2\n<-\n5 5\n5 5\n->\n\n# Output\noutputcount 1\noutputtype 58\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/axe_diamond.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n264 264\n264 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 279\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/axe_gold.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n266 266\n266 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 286\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/axe_iron.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n265 265\n265 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 258\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/axe_stone.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n4 4\n4 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 275\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/axe_wood.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n5 5\n5 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 271\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/bucket.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n265 -1 265\n-1 265 -1\n->\n\n# Output\noutputcount 1\noutputtype 325\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/clock.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n-1 266 -1\n266 331 266\n-1 266 -1\n->\n\n# Output\noutputcount 1\noutputtype 347\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/compass.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n-1 265 -1\n265 331 265\n-1 265 -1\n->\n\n# Output\noutputcount 1\noutputtype 345\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/fishingrod.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n-1 -1 280\n-1 280 287\n280 -1 286\n->\n\n# Output\noutputcount 1\noutputtype 346\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/flintsteel.recipe",
    "content": "# Input\nwidth 2\nheight 2\n<-\n265 -1\n-1 318 \n->\n\n# Output\noutputcount 1\noutputtype 259\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/hoe_diamond.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n264 264\n-1 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 293\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/hoe_gold.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n266 266\n-1 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 294\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/hoe_iron.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n265 265\n-1 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 292\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/hoe_stone.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n4 4\n-1 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 291\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/hoe_wood.recipe",
    "content": "# Input\nwidth 2\nheight 3\n<-\n5 5\n-1 280\n-1 280\n->\n\n# Output\noutputcount 1\noutputtype 290\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/pickaxe_diamond.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n264 264 264\n-1 280 -1\n-1 280 -1\n->\n\n# Output\noutputcount 1\noutputtype 278\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/pickaxe_gold.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n266 266 266\n-1 280 -1\n-1 280 -1\n->\n\n# Output\noutputcount 1\noutputtype 285\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/pickaxe_iron.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n265 265 265\n-1 280 -1\n-1 280 -1\n->\n\n# Output\noutputcount 1\noutputtype 257\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/pickaxe_stone.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n4 4 4\n-1 280 -1\n-1 280 -1\n->\n\n# Output\noutputcount 1\noutputtype 274\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/pickaxe_wood.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n5 5 5\n-1 280 -1\n-1 280 -1\n->\n\n# Output\noutputcount 1\noutputtype 270\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/shears.recipe",
    "content": "# Input\nwidth 2\nheight 2\n<-\n-1 265\n265 -1\n->\n\n# Output\noutputcount 1\noutputtype 359\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/shovel_diamond.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n264\n280\n280\n->\n\n# Output\noutputcount 1\noutputtype 277\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/shovel_gold.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n266\n280\n280\n->\n\n# Output\noutputcount 1\noutputtype 284\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/shovel_iron.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n265\n280\n280\n->\n\n# Output\noutputcount 1\noutputtype 256\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/shovel_stone.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n4\n280\n280\n->\n\n# Output\noutputcount 1\noutputtype 273\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/tools/shovel_wood.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n5\n280\n280\n->\n\n# Output\noutputcount 1\noutputtype 269\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/transport/boat.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n5 -1 5\n5 5 5\n->\n\n# Output\noutputcount 1\noutputtype 333\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/transport/minecart.recipe",
    "content": "# Input\nwidth 3\nheight 2\n<-\n265 -1 265\n265 265 265\n->\n\n# Output\noutputcount 1\noutputtype 328\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/transport/minecart_powered.recipe",
    "content": "# Input\nwidth 1\nheight 2\n<-\n61\n328\n->\n\n# Output\noutputcount 1\noutputtype 343\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/transport/minecart_storage.recipe",
    "content": "# Input\nwidth 1\nheight 2\n<-\n54\n328\n->\n\n# Output\noutputcount 1\noutputtype 342\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/transport/minecart_tracks.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n265 -1 265\n265 280 265\n265 -1 265\n->\n\n# Output\noutputcount 16\noutputtype 66\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/weapons/arrows.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n318\n280\n288\n->\n\n# Output\noutputcount 4\noutputtype 262\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/weapons/bow.recipe",
    "content": "# Input\nwidth 3\nheight 3\n<-\n287 280 -1\n287 -1 280\n287 280 -1\n->\n\n# Output\noutputcount 1\noutputtype 261\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/weapons/sword_diamond.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n264\n264\n280\n->\n\n# Output\noutputcount 1\noutputtype 276\noutputhealth 1562\n"
  },
  {
    "path": "files/recipes/weapons/sword_gold.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n266\n266\n280\n->\n\n# Output\noutputcount 1\noutputtype 283\noutputhealth 33\n"
  },
  {
    "path": "files/recipes/weapons/sword_iron.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n265\n265\n280\n->\n\n# Output\noutputcount 1\noutputtype 267\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/weapons/sword_stone.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n4\n4\n280\n->\n\n# Output\noutputcount 1\noutputtype 272\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/weapons/sword_wood.recipe",
    "content": "# Input\nwidth 1\nheight 3\n<-\n5\n5\n280\n->\n\n# Output\noutputcount 1\noutputtype 268\noutputhealth 0\n"
  },
  {
    "path": "files/recipes/white.recipe",
    "content": "# Input\nwidth 1\nheight 1\n\n<-\n35 351:15\n->\n\n# Output\noutputcount 1\noutputtype 35\noutputhealth 0\n"
  },
  {
    "path": "files/roles.txt",
    "content": "# admins\n[Server]\n\n# ops\n\n# members\n"
  },
  {
    "path": "files/rules.txt",
    "content": "﻿# Server rules here\n§4Server rules\n1. Do not whine\n2. Whine\n3. Whining is required\n4. ^__________^"
  },
  {
    "path": "files/test.lua",
    "content": "print (\"Hi, enjoy hacking with Lua\");\nfunction timer200()\n  calltest(\"test1\", \"test2\");\nend;\n"
  },
  {
    "path": "files/whitelist.txt",
    "content": "# This is default whitelist file. Write nicks to be whitelisted here one for each line\n"
  },
  {
    "path": "init.d/mineserver.centos",
    "content": "#!/bin/bash\n#\n# mineserver        Startup script for the Mineserver\n#\n# chkconfig: - 85 15\n# description: Mineserver is a FOSS implementation of the Minecraft server from minecraft.net\n# processname: mineserver\n# pidfile: /usr/local/mineserver/mineserver.pid\n\nBASEDIR=/usr/local/mineserver\npidfile=$BASEDIR/mineserver.pid\nlockfile=/var/lock/subsys/mineserver\nprog=mineserver\n\n# Source function library.\n. /etc/rc.d/init.d/functions\n\nstart() {\n  echo -n $\"Starting $prog: \"\n  cd $BASEDIR\n  #this doesn't seem to work\n  ./$prog ./config.cfg &> /dev/null\n  RETVAL=$?\n  echo\n  [ $RETVAL = 0 ] && touch ${lockfile}\n  return $RETVAL\n}\n\nstop() {\n  echo -n $\"Stopping $prog: \"\n  killproc -p ${pidfile} -d 10 $BASEDIR/$prog 2\n  RETVAL=$?\n  echo\n  [ $RETVAL = 0 ] && rm -f ${lockfile}\n  return $RETVAL\n}\n\nrestart() {\n  stop\n  start\n}\n\n# See how we were called.\ncase \"$1\" in\n  start)\n    start\n     ;;\n  stop)\n    stop\n    ;;\n  restart)\n    restart\n    ;;\n  status)\n    status -p ${pidfile} $prog\n    ;;\n  *)\n    echo $\"Usage: $prog {start|stop|restart|status}\"\n    ;;  \nesac\n"
  },
  {
    "path": "plugins/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 2.6)\n# forbid running cmake from this subdir\nif(PROJECT_NAME STREQUAL \"Project\")\n  message(FATAL_ERROR \"\\nplease run cmake from the project's parent directory\\n\")\nendif()\n\n#\n# plugin sources\n# RULES: each unique subdirectory is plugin name\n#\nset(plugins_source\n  commands/commands.cpp\n  filelog/filelog.cpp\n  nBreak/nBreak.cpp\n  nether/nether.cpp\n  binlog/binlog.cpp\n  crapMobs/crapMobs.cpp\n  cursesui/screen.cpp\n  flatpermissions/flatpermissions.cpp\n  passiveMobs/passiveMobs.cpp\n)\n\n\n#\n# custom defines\n#\nadd_definitions(-DFADOR_PLUGIN=1)\n\n\n#\n# dependencies\n#\nset(cursesui_depends\n  Curses\n)\n\n\n###############################################################################\n\n\n#\n# make lists from plugins_source\n#\nforeach(src ${plugins_source})\n  string(REGEX REPLACE \"/.*$\" \"\" p \"${src}\")\n  list(APPEND plugins ${p})\n  list(APPEND ${p}_source ${src})\nendforeach()\nlist(REMOVE_DUPLICATES plugins)\n\n\n#\n# dependency check\n#\nset(TARGETS \"\")\nforeach(p ${plugins})\n  message(STATUS \"Dependency check: ${p}\")\n  foreach(lib ${${p}_depends})\n    find_package(${lib})\n    string(TOUPPER ${lib} LIB)\n    if (NOT ${LIB}_FOUND)\n      set(${p}_error True)\n      break()\n    endif()\n  endforeach()\n\n  if(NOT ${p}_error)\n    list(APPEND TARGETS ${p})\n  else()\n    message(\"\\t-- DISABLED: ${p}\")\n  endif()\nendforeach()\n\n# override the build location again.\nSET(CMAKE_LIBRARY_OUTPUT_DIRECTORY \"../${CONFIG_DIR_BIN}/plugins\")\n\n#\n# build targets\n#\nforeach(p ${TARGETS})\n  message(STATUS \"Target: ${p}\")\n  add_library(${p} SHARED ${${p}_source})\n  set_target_properties(${p} PROPERTIES PREFIX \"\")\n\n  foreach(lib ${${p}_depends})\n    string(TOUPPER ${lib} LIB)\n    include_directories(${${LIB}_INCLUDE_DIR})\n    target_link_libraries(${p} ${${LIB}_LIBRARY})\n  endforeach()\nendforeach()\n\n\n#\n# install\n#\ninstall(TARGETS ${TARGETS} DESTINATION ${CONFIG_DIR_BIN}/plugins)\n"
  },
  {
    "path": "plugins/binlog/binlog.cfg",
    "content": "system.plugins += (\"binlog\":\"./binlog\");\n\n# Enable Transaction Logging?\nenable_binary_logging = true\nbinary_log = \"minserver.bin\"\n\n"
  },
  {
    "path": "plugins/binlog/binlog.cpp",
    "content": "/*\n   Copyright (c) 2010, The Mineserver Project\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n * Neither the name of the The Mineserver Project nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n//\n// Mineserver binlog.cpp\n//\n\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <string>\n#include <cstring>\n#include <ctime>\n#include <vector>\n\n#include \"plugin_api.h\"\n#include \"binlog.h\"\n\nBinlog::Binlog (std::string filename) \n{\n  log_stream.open(filename.c_str(), std::fstream::in | std::fstream::out | std::fstream::binary );\n  if (!log_stream.is_open()) {\n    return;\n  } \n}\n\nBinlog &Binlog::get(std::string filename)\n{\n  static Binlog instance(filename);\n  return instance;\n}\n \n// Log action to binary log \nvoid Binlog::log (event_t event)\n{\n  if(!log_stream.bad()) {\n    event.timestamp = time (NULL);\n    event.nsize = strlen(event.nick);\n\n    log_stream.seekp(0, std::ios::end);\n    log_stream.write((char *) &event.timestamp, sizeof(time_t));\n    log_stream.write((char *) &event.x, sizeof(int));\n    log_stream.write((char *) &event.y, sizeof(int));\n    log_stream.write((char *) &event.z, sizeof(int));\n    log_stream.write((char *) &event.otype, sizeof(unsigned char));\n    log_stream.write((char *) &event.ntype, sizeof(unsigned char));\n    log_stream.write((char *) &event.ometa, sizeof(unsigned char));\n    log_stream.write((char *) &event.nmeta, sizeof(unsigned char));\n    log_stream.write((char *) &event.nsize, sizeof(int));\n    log_stream.write((char *) &event.nick, event.nsize+1);\n  }\n}\n\n// Get logs based on nick and timestamp\nbool Binlog::getLogs (time_t t, std::string &nick, std::vector<event_t> *logs) \n{\n  event_t event; \n\n  log_stream.flush();\n  log_stream.seekg(0, std::ios::beg);\n  while(this->getEvent(&event)) {\n    if(event.timestamp > t && (strcmp(event.nick, nick.c_str()) == 0)) {\n      logs->push_back(event);\n    }\n  }\n  return true;\n}\n\n// Get logs based on timestamp\nbool Binlog::getLogs (time_t t, std::vector<event_t> *logs) \n{\n  event_t event;\n\n  log_stream.flush();\n  log_stream.seekg(0, std::ios::beg);\n  while(this->getEvent(&event)) {\n    if(event.timestamp > t) {\n      logs->push_back(event);\n    }\n  }\n  return true;\n}\n\n// Get all logs\nbool Binlog::getLogs (std::vector<event_t> *logs) \n{\n  event_t event;\n\n  log_stream.flush();\n  log_stream.seekg(0, std::ios::beg);\n  while(this->getEvent(&event)) {\n    logs->push_back(event);\n  }\n  return true;\n}\n\n// Get event from log\nbool Binlog::getEvent (event_t *event) \n{\n  if(!log_stream.eof()) {\n    log_stream.read((char *) &event->timestamp, sizeof(time_t));\n    log_stream.read((char *) &event->x, sizeof(int));\n    log_stream.read((char *) &event->y, sizeof(int));\n    log_stream.read((char *) &event->z, sizeof(int));\n    log_stream.read((char *) &event->otype, sizeof(unsigned char));\n    log_stream.read((char *) &event->ntype, sizeof(unsigned char));\n    log_stream.read((char *) &event->ometa, sizeof(unsigned char));\n    log_stream.read((char *) &event->nmeta, sizeof(unsigned char));\n    log_stream.read((char *) &event->nsize, sizeof(int));\n    log_stream.read((char *) &event->nick, event->nsize+1);\n    return true;\n  }\n  log_stream.clear(); \n  return false;\n}\n\nBinlog::~Binlog() \n{\n  log_stream.close();\n}\n\nmineserver_pointer_struct* mineserver;\nstd::string pluginName = \"binlog\";\nstd::string filename;\nbool enabled;\n\n// Rollback Transaction Logs\nvoid rollBack (const char* user, int argc, const char** args)\n{\n  std::vector<event_t> logs;                                                         \n  time_t timestamp;\n\n  if(argc > 0) {\n    std::stringstream ss (std::stringstream::in | std::stringstream::out);\n    ss << args[0];\n    ss >> timestamp;\n  }\n\n  if(argc == 2 ) {\n    std::string victim = args[1];\n    Binlog::get(filename).getLogs(timestamp, victim, &logs);\n  } else if (argc == 1) {\n    Binlog::get(filename).getLogs(timestamp, &logs);\n  } else {\n    Binlog::get(filename).getLogs(&logs);\n  }\n\n  std::vector<event_t>::reverse_iterator event;\n  if(logs.size() > 0) {\n    mineserver->chat.sendmsgTo(user, \"Rolling back map...\");\n    for(event = logs.rbegin(); event != logs.rend(); event++) {\n      mineserver->map.setBlock(event->x, event->y, event->z, event->otype, event->ometa);\n    }\n    mineserver->chat.sendmsgTo(user, \"Map roll back completed!\");\n  } else {\n    mineserver->chat.sendmsgTo(user, \"No binary logs found!\");\n  }\n}\n\n// Playback Transaction Logs\nvoid playBack (const char* user, int argc, const char** args)\n{\n  return;\n  std::vector<event_t> logs;                                                         \n  time_t timestamp;\n\n  if(argc > 0) {\n    std::stringstream ss (std::stringstream::in | std::stringstream::out);\n    ss << args[0];\n    ss >> timestamp;\n  }\n\n  if(argc == 2 ) {\n    std::string victim = args[1];\n    Binlog::get(filename).getLogs(timestamp, victim, &logs);\n  } else if (argc == 1) {\n    Binlog::get(filename).getLogs(timestamp, &logs);\n  } else {\n    Binlog::get(filename).getLogs(&logs);\n  }\n\n  std::vector<event_t>::reverse_iterator event;\n  if(logs.size() > 0) {\n    mineserver->chat.sendmsgTo(user, \"Playing back binary log...\");\n    for(event = logs.rbegin(); event != logs.rend(); event++) {\n      mineserver->map.setBlock(event->x, event->y, event->z, event->otype, event->ometa);\n    }\n    mineserver->chat.sendmsgTo(user, \"Binary log playback completed!\");\n  } else {\n    mineserver->chat.sendmsgTo(user, \"No binary logs found!\");\n  }\n}\n\n// Block Break Callback\nbool callbackBlockBreakPre (const char* user,int x,int y,int z) \n{\n  event_t event;\n  strcpy(event.nick, user);\n  event.x = x;\n  event.y = y;\n  event.z = z;\n  event.ntype = 0;\n  event.nmeta = 0;\n\n  mineserver->map.getBlock(x,y,z,&event.otype, &event.ometa);\n  Binlog::get(filename).log(event);\n\n  return true;\n}\n\nbool translateDirection(int32_t *x, int8_t *y, int32_t *z, int8_t direction)\n{\n    switch(direction)\n    {\n      case BLOCK_BOTTOM: (*y)--;  break;\n      case BLOCK_TOP:    (*y)++;  break;\n      case BLOCK_NORTH:  (*x)++;  break;\n      case BLOCK_SOUTH:  (*x)--;  break;\n      case BLOCK_EAST:   (*z)++;  break;\n      case BLOCK_WEST:   (*z)--;  break;\n      default:                    break;\n    }\n  return true;\n}\n\n// Block Place Callback\nbool callbackBlockPlacePre (const char* user,int32_t x,int8_t y,int32_t z, unsigned char type, unsigned char meta) \n{\n  event_t event;\n  translateDirection(&x,&y,&z,meta);\n\n  strcpy(event.nick, user);\n  event.x = x;\n  event.y = y;\n  event.z = z;\n  event.ntype = type;\n  event.nmeta = meta;\n  \n  mineserver->map.getBlock(x,y,z,&event.otype, &event.ometa);\n  Binlog::get(filename).log(event);\n\n  return true;\n}\n\n// Command Registration\nbool callbackPlayerChatCommand (const char* user, const char* command, int argc, const char** args) \n{\n  if(strcmp(command, \"rollback\") == 0) {\n    rollBack(user, argc, args);\n    return true;\n  } else if (strcmp(command, \"playback\") == 0) {\n    playBack(user, argc, args);\n    return true;\n  }\n  return false;\n}\n\nstd::string dtos( double n )\n{\n  std::ostringstream result;\n  result << n;\n  return result.str();\n}\n\n#define LOG_INFO 6\nPLUGIN_API_EXPORT void CALLCONVERSION binlog_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n  enabled = mineserver->config.bData(\"enable_binary_logging\");\n  filename = mineserver->config.sData(\"binary_log\");\n\n  if (mineserver->plugin.getPluginVersion(\"binlog\") > 0)\n  {\n    std::string msg = \"binlog is already loaded v.\"+dtos(mineserver->plugin.getPluginVersion(pluginName.c_str()));\n    mineserver->logger.log(LOG_INFO, \"plugin.binlog\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(LOG_INFO, \"plugin.binlog\", msg.c_str());\n  mineserver->plugin.setPluginVersion(\"binlog\", PLUGIN_VERSION);\n  if(enabled) \n  {\n    mineserver->plugin.addCallback(\"BlockPlacePre\", reinterpret_cast<voidF>(callbackBlockPlacePre));\n    mineserver->plugin.addCallback(\"BlockBreakPre\", reinterpret_cast<voidF>(callbackBlockBreakPre));\n  }\n  mineserver->plugin.addCallback(\"PlayerChatCommand\", reinterpret_cast<voidF>(callbackPlayerChatCommand));\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION binlog_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(\"binlog\") <= 0)\n  {\n    mineserver->logger.log(LOG_INFO, \"plugin.binlog\", \"binlog is not loaded!\");\n    return;\n  }\n}\n"
  },
  {
    "path": "plugins/binlog/binlog.h",
    "content": "/*\n   Copyright (c) 2010, The Mineserver Project\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n * Neither the name of the The Mineserver Project nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n//\n// Mineserver trxlogger.h\n//\n\n#include <string>\n#include <fstream>\n#include <time.h>\n\n#include \"plugin_api.h\"\n\n#ifndef _BINLOG_H\n#define _BINLOG_H\n#define PLUGIN_VERSION 0.1\n#endif\n\nstruct event_t {\n  time_t timestamp;\n  int x;\n  int y;\n  int z;\n  unsigned char otype, ntype;\n  unsigned char ometa, nmeta;\n  int nsize;\n  char nick[17];\n};\n\nclass Binlog \n{\n\npublic:\n  void log(event_t event);\n  static Binlog &get(std::string filename);\n  bool getLogs(time_t t, std::string &nick, std::vector<event_t> *logs);\n  bool getLogs(time_t t, std::vector<event_t> *logs);\n  bool getLogs(std::vector<event_t> *logs);\n  bool getEvent(event_t *event);\n\nprivate:\n  std::fstream log_stream;\n  Binlog(std::string filename);\n  ~Binlog();\n};\n"
  },
  {
    "path": "plugins/binlog/binlogdump.cpp",
    "content": "/*\n   Copyright (c) 2010, The Mineserver Project\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n * Neither the name of the The Mineserver Project nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n//\n// Mineserver binlogdump.cpp\n//\n\n#include <vector>\n#include <stdio.h>\n\n#include \"binlog.h\"\n\nint main (int argc, const char* argv[] ) \n{\n  if(argc != 2) {\n    printf(\"Usage: %s <filename>\\n\", argv[0]);\n    return 1;\n  }\n  std::vector<event_t> logs;\n  Binlog::get(argv[1]).getLogs(&logs);\n  std::vector<event_t>::iterator event;\n  for(event = logs.begin(); event != logs.end(); event++) \n  {\n    printf(\"{timestamp:%d, nick:%s, x:%i, y:%i, z:%i, old_type:%#x, old_meta:%#x, new_type:%#x, new_meta:%#x}\\n\", \n      event->timestamp, event->nick, event->x, event->y, event->z, \n      (int) event->otype, (int) event->ometa, (int) event->ntype, (int) event->nmeta );\n  }\n  return 0;\n}\n"
  },
  {
    "path": "plugins/commands/commands.cpp",
    "content": "/*\n  Copyright (c) 2013, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <iostream>\n#include <sstream>\n#include <fstream> // Added for MOTD\n#include <string>\n#include <deque>\n#include <stdint.h>\n#include <cstdlib>\n#include <ctime>\n\n#include <memory>\n#include <unordered_map>\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\n#include \"commands.h\"\n\nenum { PLANE,REPLACE };\n\nint _atoi(const std::string& str, bool* ok = 0){\n    if(ok){\n        *ok =true;\n        for(int i=0;i<str.size();i++)\n            if(str[i] < 48 || str[i] > 57){\n               *ok = false;\n                return 0;\n            }\n    }\n    return atoi(str.c_str());\n}\n\n#define PLUGIN_COMMANDS_VERSION 1.1\nconst char CHATCMDPREFIX   = '/';\nmineserver_pointer_struct* mineserver;\n\nstruct cuboidStruct\n{\n  int x;\n  char y;\n  int z;\n  unsigned char block;\n  bool active;\n  int state;\n  int action;\n  int fromBlock;\n  int toBlock;\n};\n\nstd::unordered_map<std::string, cuboidStruct> cuboidMap;\n\nstd::string dtos(double n)\n{\n  std::ostringstream result;\n  result << n;\n  return result.str();\n}\n\ntypedef void (*CommandCallback)(std::string nick, std::string, std::deque<std::string>);\n\nstruct Command\n{\n  Command(std::deque<std::string> _names, std::string _arguments, std::string _description, CommandCallback _callback,\n          bool _needAdmin = false, bool _needOp = false, bool _needMember = false)\n    : names(_names),\n      arguments(_arguments),\n      description(_description),\n      callback(_callback),\n      needAdmin(_needAdmin),\n      needOp(_needOp),\n      needMember(_needMember)\n  {}\n  std::deque<std::string> names;\n  std::string arguments;\n  std::string description;\n  bool needAdmin;\n  bool needOp;\n  bool needMember;\n  CommandCallback callback;  \n};\n\ntypedef std::shared_ptr<Command> ComPtr;\ntypedef std::unordered_map<std::string, ComPtr> CommandList;\nCommandList m_Commands;\n\nvoid registerCommand(ComPtr command)\n{\n  // Loop thru all the words for this command\n  std::string currentWord;\n  std::deque<std::string> words = command->names;\n  while(!words.empty())\n  {\n    currentWord = words.front();\n    words.pop_front();\n    m_Commands[currentWord] = command;\n  }\n}\n\nbool chatCommandFunction(const char* userIn,const char* cmdIn, int argc, char** argv)\n{\n  std::string user(userIn);\n  std::string command(cmdIn);\n  std::deque<std::string> cmd(argv, argv+argc);\n\n  if(command.size() == 0)\n  {\n    return false;\n  }\n\n\n  std::string logMsg = user + \": \" + command;\n  mineserver->logger.log(LOG_INFO, \"plugin.commands\", logMsg.c_str());\n\n  // User commands\n  CommandList::iterator iter;\n  if((iter = m_Commands.find(command)) != m_Commands.end())\n  {\n    if(iter->second->needAdmin)\n    {\n      if(!mineserver->permissions.isAdmin(user.c_str()))\n      {\n        mineserver->chat.sendmsgTo(user.c_str(),  \"Need Admin rights\");\n        return true;\n      }\n    }\n    if(iter->second->needOp)\n    {\n      if(!mineserver->permissions.isOp(user.c_str()))\n      {\n        mineserver->chat.sendmsgTo(user.c_str(),  \"Need Operator rights\");\n        return true;\n      }\n    }\n    if(iter->second->needMember)\n    {\n      if(!mineserver->permissions.isMember(user.c_str()))\n      {\n        mineserver->chat.sendmsgTo(user.c_str(),  \"Need Member rights\");\n        return true;\n      }\n    }\n    \n    iter->second->callback(user, command, cmd);\n    return true;\n  }\n  return false;\n}\n\nbool isValidItem(int id)\n{\n  if (id < 1)  // zero or negative items are all invalid\n  {\n    return false;\n  }\n\n  if (id > 136 && id < 256)  // these are undefined blocks and items\n  {\n    return false;\n  }\n\n  if (id >= 2256 && id <= 2266)  // records are special cased\n  {\n    return true;\n  }\n\n  if (id > 388)  // high items are invalid\n  {\n    return false;\n  }\n\n  return true;\n}\n\nint roundUpTo(int x, int nearest)\n{\n  return (((x + (nearest - 1)) / nearest) * nearest );\n}\n\nvoid giveItemsName(std::string userIn, int id, int count, int health)\n{\n  if (isValidItem(id))\n  {\n    int itemCount = 1, itemStacks = 1;\n\n    if(count != 1)\n    {\n      itemCount = count;\n      if(itemCount>1024) itemCount=1024;\n      // If multiple stacks\n      itemStacks = roundUpTo(itemCount, 64) / 64;\n      itemCount  -= (itemStacks-1) * 64;\n    }\n    int amount = 64;\n    for(int i = 0; i < itemStacks; i++)\n    {\n      // if last stack\n      if(i == itemStacks - 1)\n      {\n        amount = itemCount;\n      }\n      mineserver->user.addItem(userIn.c_str(), id, amount, health);\n    }\n  }\n  else\n  {\n    mineserver->chat.sendmsgTo(userIn.c_str(),  \"Not a valid item\");\n  }\n}\n\nvoid giveItems(std::string userIn, std::string command, std::deque<std::string> args)\n{\n  if (args.size() == 2 || args.size() == 3)\n  {\n    std::string user = args[0];\n    int itemId = 0;\n\n    //First check if item is a number\n    itemId = atoi(args[1].c_str());\n\n    //If item was not a number, search the name from config\n    if (itemId == 0)\n    {\n      itemId = mineserver->config.iData(args[1].c_str());\n    }\n    if(args.size()==2)\n    {\n      giveItemsName(user, itemId, 1,0);\n    }\n    else\n    {\n      giveItemsName(user, itemId, atoi(args[2].c_str()),0);\n    }\n\n  }\n  else\n  {\n    mineserver->chat.sendmsgTo(userIn.c_str(),\"Usage: /give player item [count]\");\n  }\n}\n\nvoid giveItemsSelf(std::string user, std::string command, std::deque<std::string> args)\n{\n  if (args.size() == 1 || args.size() == 2)\n  {\n    int itemId = 0;\n\n    //First check if item is a number\n    itemId = atoi(args[0].c_str());\n\n    //If item was not a number, search the name from config\n    if (itemId == 0)\n    {\n      itemId = mineserver->config.iData(args[0].c_str());\n    }\n    if(args.size()==1)\n    {\n      giveItemsName(user, itemId, 1,0);\n    }\n    else\n    {\n      giveItemsName(user, itemId, atoi(args[1].c_str()),0);\n    }\n\n\n  }\n  else\n  {\n    mineserver->chat.sendmsgTo(user.c_str(),\"Usage: /igive item [count]\");\n  }\n}\n\nvoid home(std::string user, std::string command, std::deque<std::string> args)\n{\n  mineserver->chat.sendmsgTo(user.c_str(),\"Teleported you home!\");\n  int x,y,z;\n  mineserver->map.getSpawn(&x,&y,&z);\n  mineserver->user.teleport(user.c_str(),x, y + 2, z);\n}\n\nvoid setSpawn(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(args.size() == 0) {\n    double x,y,z;\n    mineserver->user.getPosition(user.c_str(), &x,&y,&z,NULL,NULL,NULL);\n    \n    mineserver->chat.sendmsgTo(user.c_str(),\"Set spawn!\");\n    mineserver->map.setSpawn(x,y,z);\n    mineserver->user.teleport(user.c_str(),x, y + 2, z);\n  }\n}\n\nvoid userWorld(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(args.size() == 1)\n  {\n     double x,y,z;\n     mineserver->user.getPosition(user.c_str(), &x,&y,&z,NULL,NULL,NULL);\n     mineserver->logger.log(LOG_INFO, \"plugin.commands\", (user + args[0]).c_str());\n     mineserver->user.teleportMap(user.c_str(), x,y+2,z,atoi(args[0].c_str()));\n  }\n\n}\n\nvoid coordinateTeleport(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(args.size() == 3)\n  {\n    double x = atof(args[0].c_str());\n    double y = atof(args[1].c_str());\n    double z = atof(args[2].c_str());\n    mineserver->user.teleport(user.c_str(), x, y, z);\n  }\n  else\n  {\n    mineserver->chat.sendmsgTo(user.c_str(),\"Usage: /ctp x y z\");\n  }\n}\n\nvoid userTeleport(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(args.size() == 1)\n  {\n    std::string tUser = args[0];\n    double x,y,z;\n    if(mineserver->user.getPosition(tUser.c_str(), &x,&y,&z,NULL,NULL,NULL))\n    {\n      mineserver->user.teleport(user.c_str(),x,y+2,z);\n      mineserver->chat.sendmsgTo(user.c_str(), \"Teleported!\");\n    }\n    else\n    {\n      std::string msg = \"User \" + args[0] + \" not found (see /players)\";\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n    }\n  }\n  else if(args.size() == 2)\n  {\n    std::string whoUser = args[0];\n    std::string toUser  = args[1];\n\n    double x,y,z;\n    if(mineserver->user.getPosition(toUser.c_str(), &x,&y,&z,NULL,NULL,NULL))\n    {\n      mineserver->user.teleport(whoUser.c_str(),x,y+2,z);\n      mineserver->chat.sendmsgTo(user.c_str(), \"Teleported!\");\n    }\n    else\n    {\n      std::string msg = \"User \" + args[0] + \" not found (see /players)\";\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n    }\n  }\n  else\n  {\n    mineserver->chat.sendmsgTo(user.c_str(), \"Usage: /tp [player] targetplayer\");\n  }\n}\n\nvoid replace(std::string user, std::string command, std::deque<std::string> args)\n{\n  if (cuboidMap.find(user) != cuboidMap.end())\n  {\n    cuboidMap.erase(user);\n  }\n  if (args.size() == 2)\n  {\n    cuboidMap[user].active = 1;\n    cuboidMap[user].state = 0;\n    cuboidMap[user].action = REPLACE;\n\n    int blockID = atoi(args[0].c_str());\n\n    //If item was not a number, search the name from config\n    if (blockID == 0)\n    {\n      blockID = mineserver->config.iData(args[0].c_str());\n    }\n\n    if(blockID < 1 || blockID > 255)\n    {\n      cuboidMap.erase(user);\n      return;\n    }\n\n    cuboidMap[user].fromBlock = blockID;\n\n    blockID = atoi(args[1].c_str());\n\n    //If item was not a number, search the name from config\n    if (blockID == 0 && args[1] != \"0\")\n    {\n      blockID = mineserver->config.iData(args[1].c_str());\n    }\n\n    if(blockID < 0 || blockID > 255)\n    {\n      cuboidMap.erase(user);\n      return;\n    }\n\n    cuboidMap[user].toBlock = blockID;\n\n    mineserver->chat.sendmsgTo(user.c_str(),\"Cuboid replace start, hit first block\");\n  }\n}\n\n\nvoid replacechunk(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(args.size() == 2)\n  {\n    double x,y,z;\n    if(mineserver->user.getPosition(user.c_str(), &x,&y,&z,NULL,NULL,NULL))\n    {\n\n      int fromBlock = atoi(args[0].c_str());\n\n      //If item was not a number, search the name from config\n      if (fromBlock == 0)\n      {\n        fromBlock = mineserver->config.iData(args[0].c_str());\n      }\n\n      if(fromBlock < 1 || fromBlock > 255)\n      {\n        return;\n      }\n\n\n      int toBlock = atoi(args[1].c_str());\n\n      //If item was not a number, search the name from config\n      if (toBlock == 0 && args[1] != \"0\")\n      {\n        toBlock = mineserver->config.iData(args[1].c_str());\n      }\n\n      if(toBlock < 0 || toBlock > 255)\n      {\n        return;\n      }\n\n      int chunkx,chunkz;\n      chunkx = ((int)x)>>4;\n      chunkz = ((int)z)>>4;\n      unsigned char* blocks = mineserver->map.getMapData_block(chunkx,chunkz);\n      for(int bX = 0; bX < 16; bX++)\n      {\n        for(int bZ = 0; bZ < 16; bZ++)\n        {\n          for(int bY = 0; bY < 128; bY++)\n          {\n            if(blocks[bY + ((bZ << 7) + (bX << 11))] == fromBlock)\n            {\n              blocks[bY + ((bZ << 7) + (bX << 11))] = toBlock;\n            }\n          }\n        }\n      }\n\n      // TODO: Send chunk update to all players.\n      mineserver->chat.sendmsgTo(user.c_str(),\"Replace chunk done\");\n    }\n  }\n}\n\nvoid flattenchunk(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(args.size() == 1)\n  {\n    double x,y,z;\n    if(mineserver->user.getPosition(user.c_str(), &x,&y,&z,NULL,NULL,NULL))\n    {\n\n      int topBlock = atoi(args[0].c_str());\n\n      //If item was not a number, search the name from config\n      if (topBlock == 0)\n      {\n        topBlock = mineserver->config.iData(args[0].c_str());\n      }\n\n      if(topBlock < 1 || topBlock > 255)\n      {\n        return;\n      }\n\n      int chunkx,chunkz;\n      chunkx = ((int)x)>>4;\n      chunkz = ((int)z)>>4;\n      unsigned char* blocks = mineserver->map.getMapData_block(chunkx,chunkz);\n      for(int bX = 0; bX < 16; bX++)\n      {\n        for(int bZ = 0; bZ < 16; bZ++)\n        {\n          for(int bY = 127; bY >= 0; bY--)\n          {\n            if(bY >= y)\n            {\n              blocks[bY + ((bZ << 7) + (bX << 11))] = 0;\n            }\n            else if(bY == y - 1)\n            {\n              blocks[bY + ((bZ << 7) + (bX << 11))] = topBlock;\n            }\n            else\n            {\n              // Do nothing; leave this block untouched\n            }\n          }\n        }\n      }\n\n      // TODO: Send chunk update to all players.\n      mineserver->chat.sendmsgTo(user.c_str(),\"Flatten chunk done\");\n    }\n  }\n}\n\nvoid cuboid(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(cuboidMap.find(user) != cuboidMap.end())\n  {\n    cuboidMap.erase(user);\n  }\n  cuboidMap[user].active = 1;\n  cuboidMap[user].state = 0;\n  cuboidMap[user].action = PLANE;\n  mineserver->chat.sendmsgTo(user.c_str(),\"Cuboid start, place first block\");\n}\n\nvoid playerList(std::string user, std::string command, std::deque<std::string> args)\n{\n  mineserver->chat.sendUserlist(user.c_str());\n}\n\nvoid saveMap(std::string user, std::string command, std::deque<std::string> args)\n{\n  mineserver->map.saveWholeMap();\n  mineserver->chat.sendmsgTo(user.c_str(),\"Saved map!\");\n}\n\nvoid setTime(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(args.size() == 1)\n  {\n    std::string timeValue = args[0];\n\n    // Check for time labels\n    if(timeValue == \"day\" || timeValue == \"morning\")\n    {\n      timeValue = \"24000\";\n    }\n    else if (timeValue == \"dawn\")\n    {\n      timeValue = \"22500\";\n    }\n    else if (timeValue == \"noon\")\n    {\n      timeValue = \"6000\";\n    }\n    else if (timeValue == \"dusk\")\n    {\n      timeValue = \"12000\";\n    }\n    else if (timeValue == \"night\" || timeValue == \"midnight\")\n    {\n      timeValue = \"18000\";\n    }\n\n    mineserver->map.setTime(atoi(timeValue.c_str()));\n\n    mineserver->chat.sendmsgTo(user.c_str(),\"World time changed.\");\n  }\n  else\n  {\n    mineserver->chat.sendmsgTo(user.c_str(),\"Usage: /settime time (time = 0-24000)\");\n  }\n}\n\nvoid getTime(std::string user, std::string command, std::deque<std::string> args)\n{\n  std::string msg = \"The current server time is \" + dtos(mineserver->map.getTime());\n  mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n}\n\nbool translateDirection(int32_t *x, int8_t *y, int32_t *z, int8_t direction)\n{\n    switch(direction)\n    {\n      case BLOCK_BOTTOM: (*y)--;  break;\n      case BLOCK_TOP:    (*y)++;  break;\n      case BLOCK_NORTH:  (*x)++;  break;\n      case BLOCK_SOUTH:  (*x)--;  break;\n      case BLOCK_EAST:   (*z)++;  break;\n      case BLOCK_WEST:   (*z)--;  break;\n      default:                    break;\n    }\n  return true;\n}\n\n\nbool startedDiggingFunction(const char* userIn, int32_t x,int8_t y,int32_t z,int8_t direction)\n{\n  //translateDirection(&x,&y,&z,direction);\n  std::string user(userIn);\n  int map = 0;\n  mineserver->user.getPositionW(userIn, NULL, NULL, NULL, &map,NULL, NULL, NULL);\n\n  if(cuboidMap.find(user) != cuboidMap.end())\n  {\n    if(cuboidMap[user].active)\n    {\n      if(cuboidMap[user].action == REPLACE)\n      {\n        if(cuboidMap[user].state == 0)\n        {\n          cuboidMap[user].state = 1;\n          cuboidMap[user].x     = x;\n          cuboidMap[user].y     = y;\n          cuboidMap[user].z     = z;\n          mineserver->chat.sendmsgTo(user.c_str(),\"First block done, now second\");\n        }\n        else if(cuboidMap[user].state == 1)\n        {\n          int xstart,xend;\n          int ystart,yend;\n          int zstart,zend;\n          xstart=(x<cuboidMap[user].x)?x:cuboidMap[user].x;\n          xend=(x<cuboidMap[user].x)?cuboidMap[user].x:x;\n\n          ystart=(y<cuboidMap[user].y)?y:cuboidMap[user].y;\n          yend=(y<cuboidMap[user].y)?cuboidMap[user].y:y;\n\n          zstart=(z<cuboidMap[user].z)?z:cuboidMap[user].z;\n          zend=(z<cuboidMap[user].z)?cuboidMap[user].z:z;\n\n          unsigned char block,meta;\n\n          if((xend-xstart) * (yend-ystart) * (zend-zstart) > 10000)\n          {\n            mineserver->chat.sendmsgTo(user.c_str(),\"Area too large!\");\n            return true;\n          }\n          for(int xpos = xstart; xpos <= xend; xpos ++)\n          {\n            for(int zpos = zstart;  zpos <= zend; zpos ++)\n            {     \n              for(int ypos = ystart;  ypos <= yend; ypos ++)\n              {  \n                if(mineserver->map.getBlock(xpos,ypos,zpos,&block,&meta) && block == cuboidMap[user].fromBlock)\n                {\n                  mineserver->map.setBlock(xpos,ypos,zpos,cuboidMap[user].toBlock,map);\n                }\n              }\n            }\n          }\n          mineserver->chat.sendmsgTo(user.c_str(),\"Replace done\");\n          cuboidMap.erase(user);\n        }        \n      }\n    }\n  }\n\n  return true;\n}\n\nbool blockPlacePreFunction(const char* userIn, int32_t x,int8_t y,int32_t z,int16_t block,int8_t direction)\n{  \n  translateDirection(&x,&y,&z,direction);\n  std::string user(userIn);\n  if(cuboidMap.find(user) != cuboidMap.end())\n  {\n    if(cuboidMap[user].active)\n    {\n      if(cuboidMap[user].action == PLANE)\n      {\n      if(cuboidMap[user].state == 0)\n      {\n      cuboidMap[user].state = 1;\n      cuboidMap[user].x     = x;\n      cuboidMap[user].y     = y;\n      cuboidMap[user].z     = z;\n      cuboidMap[user].block = block;\n      mineserver->chat.sendmsgTo(user.c_str(),\"First block done, place second\");\n      }\n      else if(cuboidMap[user].state == 1)\n      {\n      if(cuboidMap[user].block == block)\n      {\n        int xstart,xend;\n        int ystart,yend;\n        int zstart,zend;\n        xstart=(x<cuboidMap[user].x)?x:cuboidMap[user].x;\n        xend=(x<cuboidMap[user].x)?cuboidMap[user].x:x;\n\n        ystart=(y<cuboidMap[user].y)?y:cuboidMap[user].y;\n        yend=(y<cuboidMap[user].y)?cuboidMap[user].y:y;\n\n        zstart=(z<cuboidMap[user].z)?z:cuboidMap[user].z;\n        zend=(z<cuboidMap[user].z)?cuboidMap[user].z:z;\n        if((xend-xstart) * (yend-ystart) * (zend-zstart) > 10000)\n        {\n          mineserver->chat.sendmsgTo(user.c_str(),\"Area too large!\");\n          return true;\n        }\n        for(int xpos = xstart; xpos <= xend; xpos ++)\n        {\n          for(int zpos = zstart;  zpos <= zend; zpos ++)\n          {                \n          for(int ypos = ystart;  ypos <= yend; ypos ++)\n          {\n            mineserver->map.setBlock(xpos,ypos,zpos,block,0);\n          }\n          }\n        }\n        mineserver->chat.sendmsgTo(user.c_str(),\"Cuboid done\");\n        cuboidMap.erase(user);\n        }\n      }\n    }\n    }\n  }\n  return true;\n}\n\nvoid doNotDisturb(std::string user, std::string command, std::deque<std::string> args)\n{\n  mineserver->user.toggleDND(user.c_str());\n}\n\nvoid gps(std::string user, std::string command, std::deque<std::string> args) \n{\n  double x,y,z,stance;\n  float yaw,pitch;\n  mineserver->user.getPosition(user.c_str(), &x, &y, &z, &yaw, &pitch, &stance);\n  std::string msg = \"X: \" + dtos(x) + \" Y: \" + dtos(y) + \" Z: \" + dtos(z);\n  mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n}\n\nvoid banUser(std::string user, std::string command, std::deque<std::string> args)\n{\n  return;\n}\n\nvoid unbanUser(std::string user, std::string command, std::deque<std::string> args) \n{\n  return;\n}\n\nvoid sendRules(std::string user, std::string command, std::deque<std::string> args) \n{\n  std::string line;\n  std::ifstream rules(\"rules.txt\");\n  \n  if(rules.is_open()) {\n    while(rules.good()) {\n      std::getline(rules, line);\n      if(line.size() > 0 && line.at(0) != '#')\n        mineserver->chat.sendmsgTo(user.c_str(), line.c_str());\n    }\n    rules.close();\n  }\n}\nvoid about(std::string user, std::string command, std::deque<std::string> args)\n{  \n  if (mineserver->config.bData(\"system.show_version\"))\n  {\n    std::string msg  = std::string(\"§9\") + std::string(mineserver->config.sData(\"system.server_name\")) + std::string(\" Running Mineserver v.\") + std::string(VERSION_SIMPLE);\n    mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n  }\n}\n\nvoid sendHelp(std::string user, std::string command, std::deque<std::string> args)\n{\n  // TODO: Add paging support, since not all commands will fit into\n  // the screen at once.\n\n  CommandList* commandList = &m_Commands; // defaults\n  //std::string commandColor = MC_COLOR_BLUE;\n\n  if (args.size() == 0)\n  {\n    bool isAdmin = mineserver->permissions.isAdmin(user.c_str());\n    bool isOp = mineserver->permissions.isOp(user.c_str());\n    bool isMember = mineserver->permissions.isMember(user.c_str());\n\n    for(CommandList::iterator it = commandList->begin();it != commandList->end();++it)\n    {\n      //Display only commands you can use and add !A!, !O! or !M! to signal who can use those\n      std::string msg;\n      if(it->second->needAdmin)\n      {\n        if(!isAdmin)\n        {\n          continue;\n        }\n        else\n        {\n          msg += \"§o§c!A!§r \";\n        }\n      }\n      if(it->second->needOp)\n      {\n        if(!isOp)\n        {\n          continue;\n        }\n        else\n        {\n          msg += \"§o§c!O!§r \";\n        }\n      }\n      if(it->second->needMember)\n      {\n        if(!isMember)\n        {\n          continue;\n        }\n        else\n        {\n          msg += \"§o§c!M!§r \";\n        }\n      }\n      std::string args = it->second->arguments;\n      std::string description = it->second->description;\n      msg += /*commandColor +*/ CHATCMDPREFIX + it->first + \" \" + args + \" : \" /*+ MC_COLOR_YELLOW*/ + description;\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n    }\n  }\n  else\n  {\n    CommandList::iterator iter;\n    if ((iter = commandList->find(args.front())) != commandList->end())\n    {\n      std::string args = iter->second->arguments;\n      std::string description = iter->second->description;\n      std::string msg = /*commandColor +*/ CHATCMDPREFIX + iter->first + \" \" + args;\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n      msg = /*MC_COLOR_YELLOW + */CHATCMDPREFIX + description;\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n    }\n    else\n    {\n      std::string msg = /*MC_COLOR_RED +*/ \"Unknown Command: \" + args.front();\n      mineserver->chat.sendmsgTo(user.c_str(),msg.c_str());\n    }\n  }\n}\n\nvoid sendMOTD(std::string user, std::string command, std::deque<std::string> args)\n{\n  std::string line;\n  std::ifstream MOTDFile(\"motd.txt\");\n  if (MOTDFile.is_open())\n    {\n    while (MOTDFile.good() )\n    {\n      std::getline(MOTDFile, line);\n      if(line.size() > 0 && line.at(0) != '#')\n        mineserver->chat.sendmsgTo(user.c_str(), line.c_str());\n    }\n    MOTDFile.close();\n  }\n}\nvoid changeGameMode(std::string user, std::string command, std::deque<std::string> args){\n    std::string changeUser;\n    if(args.size() == 2){\n        changeUser = args[0];\n        args.erase(args.begin());\n    }\n    else changeUser = user;\n\n    if(args.size() == 1){\n        bool ok;\n        int i = _atoi(args[0], &ok);\n\n        if(!ok){\n            if(args[0] == \"survival\") i=0;\n            else if(args[0] == \"creative\") i=1;\n            else goto printhelp;\n        }\n\n        if(i != 0 && i != 1) goto printhelp;\n\n        mineserver->user.setGameMode(user.c_str(), i);\n        std::string info = user + \" set \" + changeUser\n                + \"'s gamemode to \" + ( i ? \"creative\" : \"survival\") + \".\";\n        mineserver->logger.log(LOG_INFO, \"plugin.commands\", info.c_str());\n        return;\n    }\n\n    printhelp:\n    mineserver->chat.sendmsgTo(user.c_str(), \"usage: /gamemode [player] < survival | 0 ; creative | 1 > \" ) ;\n}\n\nstd::string pluginName = \"commands\";\n\nPLUGIN_API_EXPORT void CALLCONVERSION commands_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) > 0)\n  {\n    std::string msg = \"commands is already loaded v.\"+dtos(mineserver->plugin.getPluginVersion(pluginName.c_str()));\n    mineserver->logger.log(LOG_INFO, \"plugin.commands\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(LOG_INFO, \"plugin.commands\", msg.c_str());\n\n  mineserver->plugin.setPluginVersion(pluginName.c_str(), PLUGIN_COMMANDS_VERSION);\n\n  mineserver->plugin.addCallback(\"PlayerChatCommand\", reinterpret_cast<voidF>(chatCommandFunction));\n  mineserver->plugin.addCallback(\"BlockPlacePre\", reinterpret_cast<voidF>(blockPlacePreFunction));\n\n  mineserver->plugin.addCallback(\"PlayerDiggingStarted\", reinterpret_cast<voidF>(startedDiggingFunction));\n\n  registerCommand(ComPtr(new Command(parseCmd(\"about\"), \"\", \"Displays server name and software version\", about)));\n  registerCommand(ComPtr(new Command(parseCmd(\"ctp\"), \"<x> <y> <z>\", \"Teleport to coordinates (eg. /ctp 100 100 100)\", coordinateTeleport,false,false,true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"cuboid\"), \"\", \"Type in the command and place two blocks, it will fill the space between them\", cuboid,false,true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"dnd\"), \"\", \"Toggles Do Not Disturb mode\", doNotDisturb)));\n  registerCommand(ComPtr(new Command(parseCmd(\"flattenchunk\"), \"<id/alias>\", \"Erases all blocks above you and changes all blocks at your Y-level to your block of choice\", flattenchunk, false,true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"gettime\"), \"\", \"Gets the world time\", getTime)));\n  registerCommand(ComPtr(new Command(parseCmd(\"give\"), \"<player> <id/alias> [count]\", \"Gives <player> [count] pieces of <id/alias>. By default [count] = 1\", giveItems,false,true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"gps\"), \"\", \"Display current coordinates\", gps)));\n  registerCommand(ComPtr(new Command(parseCmd(\"help\"), \"[<commandName>]\", \"Display this help message.\", sendHelp)));\n  registerCommand(ComPtr(new Command(parseCmd(\"home\"), \"\", \"Teleports you to this world's spawn location\", home)));\n  registerCommand(ComPtr(new Command(parseCmd(\"igive i item\"), \"<id/alias> [count]\", \"Gives self [count] pieces of <id/alias>. By default [count] = 1\", giveItemsSelf, false,true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"motd\"), \"\", \"Displays the server's MOTD\", sendMOTD)));\n  registerCommand(ComPtr(new Command(parseCmd(\"players who names list\"), \"\", \"Lists online players\", playerList)));\n  registerCommand(ComPtr(new Command(parseCmd(\"replace\"), \"<from-id/alias> <to-id/alias>\", \"Type in the command and left-click two blocks, it will replace the selected blocks with the new blocks\", replace, true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"replacechunk\"), \"<from-id/alias> <to-id/alias>\", \"Replaces the chunk you are at with the block you specify\", replacechunk, true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"rules\"), \"\", \"Displays server rules\", sendRules)));\n  registerCommand(ComPtr(new Command(parseCmd(\"save\"), \"\", \"Manually saves map to disc\", saveMap, false, true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"setspawn\"), \"\", \"Sets home to your current coordinates\", setSpawn, true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"settime\"), \"<time>\", \"Sets the world time. (<time> = 0-24000, 0 & 24000 = day, ~15000 = night)\", setTime, false, true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"tp\"), \"<player> [<anotherPlayer>]\", \"Teleport yourself to <player>'s position or <player> to <anotherPlayer>\", userTeleport, false, true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"world\"), \"<world-id>\", \"Moves you between worlds\", userWorld, true)));\n  registerCommand(ComPtr(new Command(parseCmd(\"gamemode\"), \"[player] < survival | 0 ; creative | 1 >\", \"Changes your or someone else's gamemode.\", changeGameMode, false, true)));\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION commands_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) <= 0)\n  {\n    mineserver->logger.log(LOG_INFO, \"plugin.commands\", \"commands is not loaded!\");\n    return;\n  }\n}\n\n\nstd::deque<std::string> parseCmd(std::string cmd)\n{\n  int del;\n  std::deque<std::string> temp;\n\n  while(cmd.length() > 0)\n  {\n    while(cmd[0] == ' ')\n    {\n      cmd = cmd.substr(1);\n    }\n\n    del = cmd.find(' ');\n\n    if(del > -1)\n    {\n      temp.push_back(cmd.substr(0, del));\n      cmd = cmd.substr(del+1);\n    }\n    else\n    {\n      temp.push_back(cmd);\n      break;\n    }\n  }\n\n  if(temp.empty())\n  {\n    temp.push_back(\"empty\");\n  }\n\n  return temp;\n}\n"
  },
  {
    "path": "plugins/commands/commands.h",
    "content": "#include <string>\n\n#ifndef _PLUGIN_COMMANDS_H\n#define _PLUGIN_COMMANDS_H\n\nstd::deque<std::string> parseCmd(std::string cmd);\n\n\n#endif\n"
  },
  {
    "path": "plugins/crapMobs/crapMobs.cpp",
    "content": "/*\ng++ -c crapMobs.cpp\ng++ -shared crapMobs.o -o crapMobs.so\n\ncopy nether.so to Mineserver bin directory.\n*/\n/*\n  Copyright (c) 2010, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdlib.h>\n#include <string>\n#include <deque>\n#include <ctime>\n#include <sstream>\n#include <cstdlib>\n#include <map>\n#include <vector>\n#include <iostream>\n#include <stdint.h>\n#include <math.h>\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\n#include \"crapMobs.h\"\n\n#define PLUGIN_CRAPMOBS_VERSION 1.1\nmineserver_pointer_struct* mineserver;\n\nint myPetGiant;\nint myPetGiantz;\nbool blah=false;\n\nvoid setBlock(const char* name,int x,int y,int z,unsigned char id)\n{\n  int map;\n  mineserver->user.getPositionW(name,NULL,NULL,NULL,&map,NULL,NULL,NULL);\n  mineserver->map.setBlockW(x,y,z,map,(unsigned char)id,0);\n}\n\nint getBlock(const char* name,int x,int y,int z)\n{\n  int map;\n  mineserver->user.getPositionW(name,NULL,NULL,NULL,&map,NULL,NULL,NULL);\n  unsigned char type, meta;\n  if(mineserver->map.getBlockW(x,y,z,map,&type,&meta))\n  {\n    return type;\n  }\n  return 0;\n}\n\nvoid timer200Function()\n{\n  mineserver->mob.moveMob(myPetGiant, 0,85,0);\n  blah = !blah;\n  if(blah){\n//    mineserver->mob.despawnMob(myPetGiant);\n  }else{\n    mineserver->mob.spawnMob(myPetGiant);\n  }\n  myPetGiantz+=1;\n  if(myPetGiantz > 40)\n    myPetGiantz = 0;\n  //mineserver->logger.log(LOG_INFO, \"crapMobs\", dtos(myPetGiantz));\n  mineserver->mob.moveMob(myPetGiant, 0,85,myPetGiantz);\n}\n\nstd::string pluginName = \"crapMobs\";\n\nPLUGIN_API_EXPORT void CALLCONVERSION crapMobs_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) > 0)\n  {\n    std::string msg = \"crapMobs is already loaded\";\n    mineserver->logger.log(LOG_INFO, \"plugin.crapMobs\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(LOG_INFO, \"plugin.crapMobs\", msg.c_str());\n\n  mineserver->plugin.setPluginVersion(pluginName.c_str(), PLUGIN_CRAPMOBS_VERSION);\n\n  mineserver->plugin.addCallback(\"Timer200\", reinterpret_cast<voidF>(timer200Function));\n  myPetGiant = mineserver->mob.createSpawnMob(MOB_GIANT_ZOMBIE);\n  mineserver->mob.spawnMob(myPetGiant);\n  mineserver->mob.moveMob(myPetGiant,0,0,0);\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION command_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) <= 0)\n  {\n    mineserver->logger.log(LOG_INFO, \"plugin.crapMobs\", \"crapMobs is not loaded!\");\n    return;\n  }\n}\n"
  },
  {
    "path": "plugins/crapMobs/crapMobs.h",
    "content": "#include <string>\n\n#ifndef _PLUGIN_COMMAND_H\n#define _PLUGIN_COMMAND_H\n\nstd::deque<std::string> parseCmd(std::string cmd);\n\n\n#endif\n"
  },
  {
    "path": "plugins/cursesui/screen.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"screen.h\"\n\n#include \"logtype.h\"\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\n#include <cstdlib>\n#include <ctime>\n#include <iostream>\n#include <stack>\n\n// Constants\n#define PLUGIN_NAME \"cursesui\"\nconst char* pluginName = PLUGIN_NAME;\nconst char* logSource = \"plugin.screen\";\nconst float pluginVersion = 1.0f;\n\nenum \n{\n  LOG_TITLE,\n  LOG_COMMAND,\n  LOG_GENERAL,\n  LOG_PLAYERS\n};\n\n// Variables\nmineserver_pointer_struct* mineserver;\nCursesScreen *screen;\n\nstd::string currentTimestamp(bool seconds)\n{\n  time_t currentTime = time(NULL);\n  struct tm *Tm  = localtime(&currentTime);\n  std::string timeStamp (asctime(Tm));\n  timeStamp = timeStamp.substr(11, seconds ? 8 : 5);\n\n  return timeStamp;\n}\n\nvoid CursesScreen::initWindows()\n{\n  // Work out our dimensions\n  int titleHeight = 5;\n  int logBar = titleHeight - 1;\n  int commandHeight = 1;\n  int commandBar = LINES - commandHeight - 1;\n  int helpBar = commandBar - 1;\n  int chatBar = (commandBar - logBar)/2 + logBar + 1;\n  int logHeight = chatBar - logBar - 1;\n  int chatHeight = helpBar - chatBar - 1;\n  int playerWidth = 20;\n  int playerHeight = commandBar - logBar - 1;\n  \n  // Create our windows\n  // CursesScreen::createWindow(int width, int height, int startx, int starty)\n  titleWin = createWindow(COLS, titleHeight, 0, 0);\n  logWin = createWindow(COLS - (playerWidth + 1),\n                        logHeight, \n                        0, \n                        logBar + 1);\n  chatWin = createWindow(COLS - (playerWidth + 1), \n                         chatHeight, \n                         0, \n                         chatBar + 1);\n  playerWin = createWindow(playerWidth, \n                           playerHeight, \n                           COLS - playerWidth, \n                           logBar + 1);\n  commandWin = createWindow(COLS, \n                            commandHeight, \n                            0, \n                            commandBar + 1);  \n\n  \n  // Make sure nothing waits for input\n  wtimeout(titleWin, 0);\n  wtimeout(logWin, 0);\n  wtimeout(chatWin, 0);\n  wtimeout(commandWin, 0);\n  wtimeout(playerWin, 0);\n  nodelay(titleWin, true);\n  nodelay(logWin, true);\n  nodelay(chatWin, true);\n  nodelay(commandWin, true);\n  nodelay(playerWin, true);\n  \n  // Setup color if we haz it\n  if (has_colors())\n  {\n    start_color();\n    use_default_colors();\n    init_pair(TEXT_COLOR_RED, COLOR_RED, -1);\n    init_pair(TEXT_COLOR_GREEN, COLOR_GREEN, -1);\n    init_pair(TEXT_COLOR_YELLOW, COLOR_YELLOW, -1);\n    init_pair(TEXT_COLOR_BLUE, COLOR_BLUE, -1);\n    init_pair(TEXT_COLOR_MAGENTA, COLOR_MAGENTA, -1);\n    init_pair(TEXT_COLOR_CYAN, COLOR_CYAN, -1);\n    init_pair(TEXT_COLOR_WHITE, COLOR_WHITE, -1);\n    init_pair(TEXT_COLOR_INVERSE, COLOR_BLACK, COLOR_WHITE);\n    \n    wattron(titleWin, COLOR_PAIR(TEXT_COLOR_CYAN));\n    wattron(playerWin, COLOR_PAIR(TEXT_COLOR_WHITE));\n  }  \n  \n  // Write our border lines on the regular stdscr\n  attron(COLOR_PAIR(TEXT_COLOR_WHITE));\n  \n  /* Draw dividers */  \n  /* These mvaddch calls are cast to void to avoid an unused return value\n     warning in clang. If there's a better way to do it, feel free to change\n     things. */\n  // log bar\n  for (int x = 0; x < COLS; x++)\n    (void)mvaddch(logBar, x, '=');\n\n  // chat bar\n  for(int x = 0; x < COLS - (playerWidth + 1); x++)\n    (void)mvaddch(chatBar, x, '=');\n\n  // help bar\n  const char* helpStr = \"Help:/help History:<UP>|<DOWN> Delete:<BACKSACE> CLEAR:<HOME>\";\n  mvaddstr(helpBar, 0, helpStr);\n\n  // command bar\n  for (int x = 0; x < COLS; x++)\n    (void)mvaddch(commandBar, x, '=');\n\n  // playerlist column divider\n  for (int y = logBar + 1; y < commandBar; y++)\n    (void)mvaddch(y, COLS - (playerWidth + 1), '|');\n\n  attroff(COLOR_PAIR(TEXT_COLOR_MAGENTA));\n  \n  // Write the window labels\n  attron(COLOR_PAIR(TEXT_COLOR_WHITE));\n  attron(WA_BOLD);\n  mvprintw(logBar, 2, \" Log \");\n  mvprintw(logBar, COLS - 15, \" Players \");\n  mvprintw(chatBar, 2, \" Chat \");\n  attroff(COLOR_PAIR(TEXT_COLOR_WHITE));\n  attroff(WA_BOLD);\n  refresh();\n  \n  // Now shove our logo in at the top\n  log(LogType::LOG_INFO, \"Title\", \"  /\\\\/\\\\ (_)_ __   ___ ___  ___ _ ____   _____ _ __ \");\n  log(LogType::LOG_INFO, \"Title\", \" /    \\\\| | '_ \\\\ / _ | __|/ _ \\\\ '__\\\\ \\\\ / / _ \\\\ '__|\");\n  log(LogType::LOG_INFO, \"Title\", \"/ /\\\\/\\\\ \\\\ | | | |  __|__ \\\\  __/ |   \\\\ V /  __/ |   \");\n  log(LogType::LOG_INFO, \"Title\", \"\\\\/    \\\\/_|_| |_|\\\\___|___/\\\\___|_|    \\\\_/ \\\\___|_|  \");\n\n  wmove(titleWin, logBar - 1, 50);\n  wattron(titleWin, COLOR_PAIR(TEXT_COLOR_WHITE));\n  wprintw(titleWin, (\"v\"+this->version).c_str());\n  wattroff(titleWin, COLOR_PAIR(TEXT_COLOR_WHITE));\n  wrefresh(titleWin);\n\n  keypad(commandWin, true);\n\n}\n\nvoid CursesScreen::init(std::string version)\n{\n  this->version = version;\n  commandBuf = \"\";\n  \n  initscr(); // Start NCurses\n  timeout(0); // Non blocking\n  //noecho();\n  echo();\n  refresh();\n\n  CursesScreen::initWindows();\n  CursesScreen::redrawPlayerList();\n}\n\nvoid CursesScreen::redraw()\n{\n  timeout(0);\n  refresh();\n  CursesScreen::initWindows();\n  CursesScreen::redrawPlayerList();\n  \n  wclear(commandWin);\n  waddstr(commandWin, commandBuf.c_str());\n  wrefresh(commandWin);\n}\n\nstd::string CursesScreen::prevCommand()\n{\n  std::string str = \"\";\n  if (prevCommands.size() > 0)\n  {\n    str = prevCommands.top();\n    prevCommands.pop();\n    nextCommands.push(str);\n  }\n  return str;\n}\n\nstd::string CursesScreen::nextCommand()\n{\n  std::string str = \"\";\n  if (nextCommands.size() > 0)\n  {\n    str = nextCommands.top();\n    nextCommands.pop();\n    prevCommands.push(str);\n  }\n  return str;\n}\n\nvoid CursesScreen::addCommand(std::string str)\n{\n  while (!prevCommands.empty())\n  {\n    nextCommands.push(prevCommands.top());\n    prevCommands.pop();\n  }\n  nextCommands.push(str);\n}\n\n/* This is where the keyboard interactions are handled. */\nbool CursesScreen::hasCommand()\n{\n  bool running = true;\n  std::string str = \"\";\n  int c;\n\n  do{\n    c = wgetch(commandWin);\n    switch(c)\n    {\n      case ERR:\n      case KEY_RIGHT:\n      case KEY_END:\n        running = false;\n        break;\n      case KEY_RESIZE:\n        CursesScreen::redraw();\n        wdeleteln(commandWin);\n        wclear(commandWin);\n        waddstr(commandWin, commandBuf.c_str());\n        running = false;\n        break;\n      case KEY_UP:\n      case KEY_PPAGE:\n        str = nextCommand();\n        wdeleteln(commandWin);\n        wclear(commandWin);\n        if (str == \"\")\n        {\n          waddstr(commandWin, commandBuf.c_str());\n        }\n        else\n        {\n          waddstr(commandWin, str.c_str());\n          commandBuf = str;\n        }\n        break;\n      case KEY_DOWN:\n      case KEY_NPAGE:\n        str = prevCommand();\n        wdeleteln(commandWin);\n        wclear(commandWin);\n        waddstr(commandWin, str.c_str());\n        commandBuf = str;\n        break;\n      case KEY_ENTER:\n      case '\\n':\n      case '\\r':\n        wdeleteln(commandWin);\n        wclear(commandWin);\n        command = commandBuf;\n        addCommand(commandBuf);\n        commandBuf = \"\";\n        return true;\n        break;\n      case KEY_HOME:\n        wdeleteln(commandWin);\n        wclear(commandWin);\n        commandBuf = \"\";\n        running = false;\n        break;\n      case KEY_BACKSPACE:\n      case KEY_LEFT:\n      case KEY_SDC:\n      case KEY_DC:\n      case '\\b':\n        if (commandBuf.length() > 0)\n          commandBuf.erase(commandBuf.length()-1,1);\n        wdeleteln(commandWin);\n        wclear(commandWin);\n        waddstr(commandWin, commandBuf.c_str());\n        running = false;\n        break;\n      default:\n        commandBuf += c;\n    }\n  } while(running);\n\n  return false;\n}\n\nstd::string CursesScreen::getCommand()\n{\n  std::string str = command;\n  command = \"\";\n  return str;\n}\n\nWINDOW* CursesScreen::createWindow(int width, int height, int startx, int starty)\n{  \n  WINDOW *local_win;\n\n  local_win = newwin(height, width, starty, startx);\n  scrollok(local_win, 1);    // Fine to scroll\n  wrefresh(local_win);  \n\n  return local_win;\n}\n\nvoid CursesScreen::destroyWindow(WINDOW *local_win)\n{  \n  /* box(local_win, ' ', ' '); : This won't produce the desired\n   * result of erasing the window. It will leave it's four corners \n   * and so an ugly remnant of window. \n   */\n  wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');\n  /* The parameters taken are \n   * 1. win: the window on which to operate\n   * 2. ls: character to be used for the left side of the window \n   * 3. rs: character to be used for the right side of the window \n   * 4. ts: character to be used for the top side of the window \n   * 5. bs: character to be used for the bottom side of the window \n   * 6. tl: character to be used for the top left corner of the window \n   * 7. tr: character to be used for the top right corner of the window \n   * 8. bl: character to be used for the bottom left corner of the window \n   * 9. br: character to be used for the bottom right corner of the window\n   */\n  wrefresh(local_win);\n  delwin(local_win);\n}\n\nvoid CursesScreen::end()\n{\n  // Kill our windows\n  destroyWindow(titleWin);\n  destroyWindow(logWin);\n  destroyWindow(chatWin);\n  destroyWindow(playerWin);\n  \n  // Stop NCurses\n  endwin();\n}\n\nvoid CursesScreen::log(LogType::LogType type, const std::string& source, const std::string& message)\n{\n  WINDOW *window;\n  \n  if (source == \"Chat\")\n  {\n    window = chatWin;\n  }\n  else if (source == \"Command\")\n  {\n    window = commandWin;\n  }\n  else if (source == \"Players\")\n  {\n    window = playerWin;\n  }\n  else if (source == \"Title\")\n  {\n    window = titleWin;\n  }\n  else\n  {\n    window = logWin;\n  }\n\n  // Set the color\n  if (type == LogType::LOG_ERROR)\n  {\n    wattron(window, COLOR_PAIR(TEXT_COLOR_RED));\n  }\n\n  // Get the cursor so we can indent a bit\n  int x, y;\n  getyx(window, y, x);\n\n  if (type != LogType::LOG_ERROR && (window == chatWin || window == logWin))\n  {\n    waddstr(window, \"\\n\");\n    wattron(window, WA_BOLD);\n    waddstr(window, (\"[\" + currentTimestamp(true) + \"] \").c_str());\n    wattroff(window, WA_BOLD);\n    waddstr(window, (message).c_str());\n  }\n  else if (window == titleWin || window == playerWin)\n  {\n    waddstr(window, (message).c_str());\n    waddstr(window, \"\\n\");\n  }\n  else \n  {\n    waddstr(window, \"\\n\");\n    waddstr(window, (message).c_str());\n  }\n    \n  // Turn off color again\n  if (type == LogType::LOG_ERROR)\n  {\n    wattroff(window, COLOR_PAIR(TEXT_COLOR_RED));\n  }\n\n  wrefresh(window);  \n}\n\n#include <algorithm>\n\nvoid CursesScreen::redrawPlayerList()\n{\n  // Clear the playerlist\n  wclear(playerWin);\n\n  // Now fill it up!\n  if(usernames.size() == 0) \n  {\n    log(LogType::LOG_INFO, \"Players\", \"No active players\");\n  }\n  else\n  {\n    for (std::vector<std::string>::const_iterator username = usernames.begin();\n         username != usernames.end();\n         ++username)\n    {\n      log(LogType::LOG_INFO, \"Players\", *username);\n    }\n  }\n}\n\nvoid CursesScreen::updatePlayerList(bool joining, const char *username)\n{\n  // Update the list\n  if (joining)\n  {\n    usernames.push_back(username);\n  } \n  else\n  {\n    std::vector<std::string>::iterator element = std::find(usernames.begin(), usernames.end(), std::string(username));\n\n    if (element != usernames.end())\n    {\n      usernames.erase(element);\n    }\n  }\n\n  // Redraw the list\n  CursesScreen::redrawPlayerList();\n}\n\nbool logPost(int type, const char* source, const char* message)\n{\n  screen->log((LogType::LogType)type, source, message);\n  return false;\n}\n\nstatic const unsigned int SERVER_CONSOLE_UID = -1;\n\nbool checkForCommand()\n{\n  if (screen->hasCommand())\n  {\n    // Now handle this command as normal\n    mineserver->chat.handleMessage(\"[Server]\", screen->getCommand().c_str());\n  }\n  return false;\n}\n\nbool on_player_login(const char *username)\n{\n  screen->updatePlayerList(true, username);\n  return false;\n}\n\nbool on_player_quit(const char *username)\n{\n  screen->updatePlayerList(false, username);\n  return false;\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION cursesui_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName) > 0)\n  {\n    mineserver->logger.log(LogType::LOG_INFO, logSource, \"The \" PLUGIN_NAME \" plugin is already loaded\");\n    return;\n  }\n\n  mineserver->plugin.setPluginVersion(pluginName, pluginVersion);\n\n  screen = new CursesScreen();\n  screen->init(\"1.2\"); // TODO This should query mineserver for the version\n  mineserver->plugin.addCallback(\"LogPost\", reinterpret_cast<voidF>(logPost));\n  mineserver->plugin.addCallback(\"Timer200\", reinterpret_cast<voidF>(checkForCommand));\n  mineserver->plugin.addCallback(\"PlayerLoginPost\", reinterpret_cast<voidF>(on_player_login));\n  mineserver->plugin.addCallback(\"PlayerQuitPost\", reinterpret_cast<voidF>(on_player_quit));\n\n  mineserver->logger.log(LogType::LOG_INFO, logSource, \"Loaded \" PLUGIN_NAME);\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION cursesui_shutdown(void)\n{\n  screen->end();\n  //mineserver = NULL;\n}\n"
  },
  {
    "path": "plugins/cursesui/screen.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _CURSESSCREEN_H\n#define _CURSESSCREEN_H\n\n#ifdef WIN32\n  #pragma warning( disable: 4005)\n  #include <winsock2.h>\n  #include <curses.h>\n#else\n  #include <ncurses.h>\n#endif\n\n#include <string>\n#include <vector>\n#include <stack>\n\n#include \"logtype.h\"\nenum\n{\n  TEXT_COLOR_RED = 1,\n  TEXT_COLOR_GREEN,\n  TEXT_COLOR_YELLOW,\n  TEXT_COLOR_BLUE,\n  TEXT_COLOR_MAGENTA,\n  TEXT_COLOR_CYAN,\n  TEXT_COLOR_WHITE,\n  TEXT_COLOR_INVERSE\n};\n\nclass CursesScreen\n{\npublic:\n  void init(std::string version);\n  WINDOW* createWindow(int width, int height, int startx, int starty);\n  void destroyWindow(WINDOW *local_win);\n  void log(LogType::LogType type, const std::string& source, const std::string& message);\n  void updatePlayerList(bool joining, const char *username);\n  void end();\n  WINDOW *commandLog;\n  bool hasCommand();\n  std::string getCommand();\n\nprivate:\n  WINDOW *titleWin;\n  WINDOW *logWin;\n  WINDOW *chatWin;\n  WINDOW *commandWin;\n  WINDOW *playerWin;\n\n  std::vector<std::string> usernames;\n  \n  std::string version;\n  \n  std::string command;\n  std::string commandBuf;\n  std::stack<std::string> prevCommands;\n  std::stack<std::string> nextCommands;\n\n\n  \n  /* Helper funcions */\n  std::string prevCommand();\n  std::string nextCommand();\n  void addCommand(std::string str);\n\n  /* Screen Helpers */\n  void initWindows();\n  void redraw();\n  void redrawPlayerList();\n};\n\n#endif /* _CURSESSCREEN_H */\n"
  },
  {
    "path": "plugins/filelog/filelog.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/*\n  Feature List:\n    * Logging chat messages to a file\n    * Logging server messages to a file\n    * Configuration for disabling the chat and/or server features\n    * Configuration option for specificing the filename of the server and chat files.\n    \n  Feature list todo:\n    * Linux Makefile\n    * Support for splitting chat and server log files per day\n    * Configration settings\n    ** Split per day\n    ** Support for the splitting in the filename, or just append before the .log.\n    ** timestamp format (ie strftime format maybe? without the % part)\n\n  Options\n    filelog.chat.enable = true;\n    filelog.chat.filename = \"mineserver_chat.log\";\n    filelog.chat.daily_split = false;\n    filelog.server.enable = true;\n    filelog.server.filename = \"mineserver.log\";\n    filelog.server.daily_split = false;\n*/\n\n#include <cstdio>\n#include <cstdlib>\n#include <ctime>\n#include <cstring>\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\n// This should mirror mineserver/logtype.h.\nstatic const char* logTypeName[] = {\n  \"EMERG\",\n  \"Alert\",\n  \"Critical\",\n  \"Error\",\n  \"Warning\",\n  \"Notice\",\n  \"Info\",\n  \"Debug\"\n};\n\n// limits, defaults\n#define STR_MAXLEN     80\n#define FORMAT_TIME    \"%Y-%m-%d %H:%M:%S\"\n#define FILENAME_LOG   \"mineserver.log\"\n#define FILENAME_CHAT  \"mineserver_chat.log\"\n\n// Constants\n#define PLUGIN_NAME \"Filelog\"\nconst char* pluginName = PLUGIN_NAME;\nconst char* logSource = \"plugin.filelog\";\nconst float pluginVersion = 1.0f;\n\n// Variables\nmineserver_pointer_struct* mineserver;\nFILE* logFile;\nFILE* chatFile;\nconst char* formatTimestamp = FORMAT_TIME;\n\n// Configuration Helper functions\nbool filelog_config_boolean(const char* key, bool defaultValue)\n{\n  if (!mineserver->config.has(key))\n  {\n    return defaultValue;\n  }\n  return mineserver->config.bData(key);\n}\n\nconst char* filelog_config_string(const char* key, const char*defaultValue)\n{\n  if (!mineserver->config.has(key))\n  {\n    return defaultValue;\n  }\n  return mineserver->config.sData(key);\n}\n\nbool chatPost(const char* name, time_t time, const char* message)\n{\n  char str[STR_MAXLEN];\n  struct tm* localTime;\n\n  localTime = localtime(&time);\n  strftime(str, sizeof(str), formatTimestamp, localTime);\n  fprintf(chatFile, \"%s <%s> %s\\n\", str, name, message);\n  return false;\n}\n\nbool logPost(int type, const char* source, const char* message)\n{\n  char str[STR_MAXLEN];\n  time_t t;\n  struct tm* tmLocal;\n\n  t = time(NULL);\n  tmLocal = localtime(&t);\n  strftime(str, sizeof(str), formatTimestamp, tmLocal);\n\n  if (type >= LOG_COUNT || type < 0) // Unknown log type\n    fprintf(logFile, \"%s [%d] %s: %s\\n\", str, type, source, message);\n  else\n    fprintf(logFile, \"%s [%s] %s: %s\\n\", str, logTypeName[type], source, message);\n\n  return false;\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION filelog_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName) > 0)\n  {\n    mineserver->logger.log(LOG_INFO, logSource, \"The \" PLUGIN_NAME \" plugin is already loaded\");\n    return;\n  }\n\n  mineserver->logger.log(LOG_INFO, logSource, \"Loaded \" PLUGIN_NAME);\n  mineserver->plugin.setPluginVersion(pluginName, pluginVersion);\n\n  // Check if server message logging is enabled, if the option is not specified default to true.\n  if (filelog_config_boolean(\"filelog.server.enable\", true))\n  {\n    const char *filename = filelog_config_string(\"filelog.server.filename\", FILENAME_LOG);\n    char *message = (char *)malloc(strlen(filename) + 12); \n\n    mineserver->plugin.addCallback(\"LogPost\", reinterpret_cast<voidF>(logPost));\n    logFile = fopen(filename, \"a\");   \n    sprintf(message, \"Logging to %s\", filename);\n    mineserver->logger.log(LOG_INFO, logSource, message);\n    free(message);\n  }\n  else\n  {\n    mineserver->logger.log(LOG_INFO, logSource, \"Logging server messages to file is disabled\");\n  }\n\n  // Check if chat logging is enabled, if the option is not specified default to true.\n  if (filelog_config_boolean(\"filelog.chat.enable\", true))\n  {\n    const char* filename = filelog_config_string(\"filelog.chat.filename\", FILENAME_CHAT);\n    char* message = (char *)malloc(strlen(filename) + 17); \n\n    mineserver->plugin.addCallback(\"PlayerChatPost\", reinterpret_cast<voidF>(chatPost));\n    chatFile = fopen(filename, \"a\");    \n    sprintf(message, \"Logging chat to %s\", filename);\n    mineserver->logger.log(LOG_INFO, logSource, message);\n    free(message);\n  }\n  else\n  {\n    mineserver->logger.log(LOG_INFO, logSource, \"Logging chat messages to file is disabled\");\n  }\n}\n\n\nPLUGIN_API_EXPORT void CALLCONVERSION filelog_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName) <= 0)\n  {\n    mineserver->logger.log(LOG_INFO, logSource, PLUGIN_NAME \" is not loaded!\");\n    return;\n  }\n  mineserver->logger.log(LOG_INFO, logSource, PLUGIN_NAME \" has been unloaded!\");\n  fclose(logFile);\n  fclose(chatFile);\n  logFile = NULL;\n  chatFile = NULL;\n}\n"
  },
  {
    "path": "plugins/flatpermissions/flatpermissions.cpp",
    "content": "/*\n\ng++ -c flatpermissions.cpp\ng++ -shared flatpermissions.o -o flatpermissions.so\n\n*/\n/*\n  Copyright (c) 2013, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cstdlib>\n#include <string>\n#include <algorithm>\n#include <iostream>\n#include <sstream>\n#include <fstream>\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\n#define PLUGIN_VERSION 1.1\nmineserver_pointer_struct* mineserver;\nstd::string pluginName = \"flatpermissions\";\n\nstd::string dtos(double n)\n{\n  std::stringstream result;\n  result << n;\n  return result.str();\n}\n\nvoid loginPost(const char* userIn){\n  std::ifstream file;\n  file.open(\"permissions.txt\", std::ios::in);\n  std::string line;\n  if(file.is_open())\n  {\n    while(file.good())\n    {\n      std::string msg;\n      std::getline(file, msg);\n      if(msg.size()>1)\n      {\n        std::string name, rank;\n        std::istringstream line(msg);\n        std::getline(line,name,':');\n        std::getline(line,rank);\n        if(name.compare(std::string(userIn))==0)\n        {\n          std::transform(rank.begin(), rank.end(), rank.begin(), ::tolower);\n          if(rank.compare(\"admin\")==0 || rank.compare(\"admins\")==0)\n          {\n            mineserver->permissions.setAdmin(userIn);\n          }\n          else if(rank.compare(\"op\")==0 || rank.compare(\"ops\")==0)\n          {\n            mineserver->permissions.setOp(userIn);\n          }\n          else if(rank.compare(\"member\")==0 || rank.compare(\"members\")==0)\n          {\n            mineserver->permissions.setMember(userIn);\n          }\n          else\n          {\n            mineserver->permissions.setGuest(userIn);\n          }\n          break;\n        }\n      }\n    }\n    file.close();\n  }\n}\n\n\nPLUGIN_API_EXPORT void CALLCONVENSION flatpermissions_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) <= 0)\n  {\n    mineserver->logger.log(6, \"plugin.flatpermissions\", \"flatpermission is not loaded!\");\n    return;\n  }\n}\n\nPLUGIN_API_EXPORT void CALLCONVENSION flatpermissions_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n  if(mineserver->plugin.getPluginVersion(pluginName.c_str())>0){\n    std::string msg = \"flatpermission is already loaded, v. \"+dtos(mineserver->plugin.getPluginVersion(pluginName.c_str()));\n    mineserver->logger.log(6, \"plugin.flatpermissions\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(6, \"plugin.flatpermissions\", msg.c_str());\n\n  mineserver->plugin.setPluginVersion(pluginName.c_str(), PLUGIN_VERSION);\n  mineserver->plugin.addCallback(\"PlayerLoginPost\", reinterpret_cast<voidF>(loginPost));\n}\n"
  },
  {
    "path": "plugins/luascript/luascript.cpp",
    "content": "/*\n  Copyright (c) 2013, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <iostream>\n#include <sstream>\n#include <string>\n#include <deque>\n#include <stdint.h>\n#include <cstdlib>\n#include <ctime>\n#include <map>\n#include <vector>\n\nextern \"C\"\n{\n#include <lua.h>\n#include <lauxlib.h>\n#include <lualib.h>\n}\n\n#include \"luawrapper.h\"\n\nstruct LuaScript\n{\n  std::string script;\n  lua_State* pL;\n};\n\nstd::vector<LuaScript> luaScripts;\n\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\nstd::deque<std::string> parseCmd(std::string cmd);\nconst char CHATCMDPREFIX   = '/';\n#define PLUGIN_LUASCRIPT_VERSION 0.1\n#define MSG_PREFIX std::string(\"[LuaScript] \")\n\nmineserver_pointer_struct* mineserver;\n\nstd::string dtos(double n)\n{\n  std::ostringstream result;\n  result << n;\n  return result.str();\n}\n\ntypedef void (*CommandCallback)(std::string nick, std::string, std::deque<std::string>);\n\nstruct Command\n{\n  Command(std::deque<std::string> _names, std::string _arguments, std::string _description, CommandCallback _callback)\n    : names(_names),\n      arguments(_arguments),\n      description(_description),\n      callback(_callback)\n  {}\n  std::deque<std::string> names;\n  std::string arguments;\n  std::string description;\n  CommandCallback callback;\n};\n\ntypedef Command* ComPtr;\ntypedef std::map<std::string, ComPtr> CommandList;\nCommandList m_Commands;\n\nvoid registerCommand(ComPtr command)\n{\n  // Loop thru all the words for this command\n  std::string currentWord;\n  std::deque<std::string> words = command->names;\n  while(!words.empty())\n  {\n    currentWord = words.front();\n    words.pop_front();\n    m_Commands[currentWord] = command;\n  }\n}\n\nbool chatCommandFunction(const char* userIn,const char* cmdIn, int argc, char** argv)\n{\n  std::string user(userIn);\n  std::string command(cmdIn);\n  std::deque<std::string> cmd(argv, argv+argc);\n\n  if(command.size() == 0)\n  {\n    return false;\n  }\n\n  // User commands\n  CommandList::iterator iter;\n  if((iter = m_Commands.find(command)) != m_Commands.end())\n  {\n    iter->second->callback(user, command, cmd);\n    return true;\n  }\n  return false;\n}\n\n\nbool startedDiggingFunction(const char* userIn, int32_t x,int8_t y,int32_t z,int8_t direction)\n{\n  //translateDirection(&x,&y,&z,direction);\n  std::string user(userIn);\n  int map = 0;\n  mineserver->user.getPositionW(userIn, NULL, NULL, NULL, &map,NULL, NULL, NULL);\n  \n\n  return true;\n}\n\nbool translateDirection(int32_t *x, int8_t *y, int32_t *z, int8_t direction)\n{\n    switch(direction)\n    {\n      case BLOCK_BOTTOM: (*y)--;  break;\n      case BLOCK_TOP:    (*y)++;  break;\n      case BLOCK_NORTH:  (*x)++;  break;\n      case BLOCK_SOUTH:  (*x)--;  break;\n      case BLOCK_EAST:   (*z)++;  break;\n      case BLOCK_WEST:   (*z)--;  break;\n      default:                    break;\n    }\n  return true;\n}\n\nbool blockPlacePreFunction(const char* userIn, int32_t x,int8_t y,int32_t z,int16_t block,int8_t direction)\n{  \n  translateDirection(&x,&y,&z,direction);\n  std::string user(userIn);\n  \n  return true;\n}\n\nvoid sendHelp(std::string user, std::string command, std::deque<std::string> args)\n{\n  if(!mineserver->permissions.isAdmin(user.c_str())) return;\n  CommandList* commandList = &m_Commands; // defaults\n  //std::string commandColor = MC_COLOR_BLUE;\n\n  if (args.size() == 0)\n  {\n    for(CommandList::iterator it = commandList->begin();it != commandList->end();++it)\n    {\n      if(it->first != \"help\")\n      {\n        std::string args = it->second->arguments;\n        std::string description = it->second->description;\n        std::string msg = \"ic!A!r \"+ CHATCMDPREFIX + it->first + \" \" + args + \" : \" + description;\n        mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n      }\n    }\n  }\n  else\n  {\n    CommandList::iterator iter;\n    if ((iter = commandList->find(args.front())) != commandList->end())\n    {\n      if(iter->first != \"help\")\n      {\n        std::string args = iter->second->arguments;\n        std::string description = iter->second->description;\n        std::string msg = CHATCMDPREFIX + iter->first + \" \" + args;\n        mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n        msg = CHATCMDPREFIX + description;\n        mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n      }\n    }\n  }\n}\n\n//Calltest, string a, string b\nint lua_calltest(lua_State *pL)\n{\n  int n = lua_gettop(pL);\n  if(n != 2)\n  {\n    return 0;\n  }\n  if(!lua_isstring(pL, 1) || !lua_isstring(pL, 2))\n  {\n    return 0;\n  }\n\n  std::string msg=lua_tostring(pL,1);\n  std::string msg2=lua_tostring(pL,2);\n\n  mineserver->logger.log(LOG_INFO, \"plugin.luascript\", msg.c_str());\n  return 0;\n}\n\nvoid registerLuaFunctions(lua_State *pL)\n{\n  lua_register(pL, \"calltest\", lua_calltest);\n}\n\nvoid luaLoad(std::string user, std::string command, std::deque<std::string> args)\n{\n\n  if (args.size() == 0)\n  {\n    std::string msg = MSG_PREFIX+\"Usage: /luaload <scriptname>\";\n    mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n  }\n  else\n  {\n    std::string msg = \"Trying to load \" + args[0];\n    mineserver->logger.log(LOG_INFO, \"plugin.luascript\", msg.c_str());\n    luaScripts.push_back(LuaScript());\n    unsigned int last = luaScripts.size()-1;\n\n    //Initialize\n    luaScripts[last].pL = lua_open();\n    luaScripts[last].script = args[0];    \n    luaL_openlibs(luaScripts[last].pL);\n\n    //Try to open and run\n    if(luaL_dofile(luaScripts[last].pL,  luaScripts[last].script.c_str()) != 0)\n    {\n      lua_close(luaScripts[last].pL);\n      luaScripts.pop_back();\n      std::string msg = MSG_PREFIX+\"failed to load script \"+args[0];\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n    }\n    else\n    {\n      //Init stuff\n      registerLuaFunctions(luaScripts[last].pL);\n      std::string msg = MSG_PREFIX+\"script \"+args[0]+\" loaded and running!\";\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n    }\n  }\n}\n\nvoid luaUnload(std::string user, std::string command, std::deque<std::string> args)\n{\n  if (args.size() == 0)\n  {\n    std::string msg = MSG_PREFIX+\"Usage: /luaunload <scriptname>\";\n    mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n  }\n  else\n  {\n    bool found = false;\n    for(unsigned int i = 0;  i < luaScripts.size(); i++)\n    {\n      if(luaScripts[i].script == args[0])\n      {\n        lua_close(luaScripts[i].pL);\n        luaScripts.erase(luaScripts.begin()+i);\n        std::string msg = MSG_PREFIX+\"unloaded script \"+args[0];\n        mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n        found = true;\n        break;\n      }\n    }\n    if(!found)\n    {\n      std::string msg = MSG_PREFIX+\"unable to unload script \"+args[0];\n      mineserver->chat.sendmsgTo(user.c_str(), msg.c_str());\n    }\n  }\n}\n\n\nvoid luaStatus(std::string user, std::string command, std::deque<std::string> args)\n{\n\n}\n\nvoid timer200Function()\n{\n  for(unsigned int i = 0;  i < luaScripts.size(); i++)\n  {\n    lua_getglobal(luaScripts[i].pL, \"timer200\");\n    if(lua_isfunction(luaScripts[i].pL, -1))\n    {\n      lua_call(luaScripts[i].pL, 0, 0);\n    }\n  }\n}\n\nstd::string pluginName = \"luascript\";\n\nPLUGIN_API_EXPORT void CALLCONVERSION luascript_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) > 0)\n  {\n    std::string msg = \"luascript is already loaded v.\"+dtos(mineserver->plugin.getPluginVersion(pluginName.c_str()));\n    mineserver->logger.log(LOG_INFO, \"plugin.luascript\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(LOG_INFO, \"plugin.luascript\", msg.c_str());\n\n  mineserver->plugin.setPluginVersion(pluginName.c_str(), PLUGIN_LUASCRIPT_VERSION);\n\n  mineserver->plugin.addCallback(\"PlayerChatCommand\", reinterpret_cast<voidF>(chatCommandFunction));\n  mineserver->plugin.addCallback(\"BlockPlacePre\", reinterpret_cast<voidF>(blockPlacePreFunction));\n  mineserver->plugin.addCallback(\"PlayerDiggingStarted\", reinterpret_cast<voidF>(startedDiggingFunction));\n  mineserver->plugin.addCallback(\"Timer200\", reinterpret_cast<voidF>(timer200Function));\n\n  registerCommand(ComPtr(new Command(parseCmd(\"help\"), \"[<commandName>]\", \"Display this help message.\", sendHelp)));\n  registerCommand(ComPtr(new Command(parseCmd(\"luaload\"), \"<scriptname>\", \"Load Lua script\", luaLoad)));\n  registerCommand(ComPtr(new Command(parseCmd(\"luaunload\"), \"<scriptname>\", \"Unload Lua script\", luaUnload)));\n  registerCommand(ComPtr(new Command(parseCmd(\"luastatus\"), \"\", \"Give status of luascript\", luaStatus)));\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION commands_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) <= 0)\n  {\n    mineserver->logger.log(LOG_INFO, \"plugin.luascript\", \"luascript is not loaded!\");\n    return;\n  }\n}\n\n\nstd::deque<std::string> parseCmd(std::string cmd)\n{\n  int del;\n  std::deque<std::string> temp;\n\n  while(cmd.length() > 0)\n  {\n    while(cmd[0] == ' ')\n    {\n      cmd = cmd.substr(1);\n    }\n\n    del = cmd.find(' ');\n\n    if(del > -1)\n    {\n      temp.push_back(cmd.substr(0, del));\n      cmd = cmd.substr(del+1);\n    }\n    else\n    {\n      temp.push_back(cmd);\n      break;\n    }\n  }\n\n  if(temp.empty())\n  {\n    temp.push_back(\"empty\");\n  }\n\n  return temp;\n}\n"
  },
  {
    "path": "plugins/luascript/luawrapper.cpp",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <iostream>\n#include <sstream>\n#include <string>\n#include <deque>\n#include <stdint.h>\n#include <cstdlib>\n#include <ctime>\n#include <map>\n#include <vector>\n\nextern \"C\"\n{\n#include <lua.h>\n#include <lauxlib.h>\n#include <lualib.h>\n}\n\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\nextern mineserver_pointer_struct* mineserver;"
  },
  {
    "path": "plugins/luascript/luawrapper.h",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n"
  },
  {
    "path": "plugins/nBreak/nBreak.cpp",
    "content": "/*\ng++ -c nBreak.cpp\ng++ -shared nBreak.o -o nBreak.so\n\ncopy nether.so to Mineserver bin directory.\n*/\n/*\n  Copyright (c) 2010, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdlib.h>\n#include <string>\n#include <deque>\n#include <ctime>\n#include <sstream>\n#include <cstdlib>\n#include <map>\n#include <vector>\n#include <iostream>\n#include <stdint.h>\n#include <math.h>\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\n#include \"nBreak.h\"\n\n#define PLUGIN_NBREAK_VERSION 1.1\nmineserver_pointer_struct* mineserver;\n\nvoid setBlock(const char* name,int x,int y,int z,unsigned char id)\n{\n  int map;\n  mineserver->user.getPositionW(name,NULL,NULL,NULL,&map,NULL,NULL,NULL);\n  mineserver->map.setBlockW(x,y,z,map,(unsigned char)id,0);\n}\n\nint getBlock(const char* name,int x,int y,int z)\n{\n  int map;\n  mineserver->user.getPositionW(name,NULL,NULL,NULL,&map,NULL,NULL,NULL);\n  unsigned char type, meta;\n  if(mineserver->map.getBlockW(x,y,z,map,&type,&meta))\n  {\n    return type;\n  }\n  return 0;\n}\n\nbool blockBreakPreFunction(const char* userIn, int32_t x, int32_t y, int32_t z,int16_t block, int8_t direction)\n{\n  int id = getBlock(userIn,x,y,z);\n  int item,meta,count;\n  mineserver->user.getItemInHand(userIn,&item, &meta, &count);\n  if(id == 4 || id == 1 || id == 16 || id == 48 || id == 67)\n  {\n    if(item == 270 || item == 278 || item == 257 || item == 285 || item == 274)\n    {\n      return true;\n    }\n    else\n    {\n      setBlock(userIn,x,y,z,0);\n      return false;\n    }\n  }\n  if(id == 15)\n  {\n    if(item == 278 || item == 257 || item == 285 || item == 274)\n    {\n      return true;\n    }\n    else\n    {\n      setBlock(userIn,x,y,z,0);\n      return false;\n    }\n  }\n  if(id == 14)\n  {\n    if(item == 278 || item == 257 || item == 285)\n    {\n      return true;\n    }\n    else\n    {\n      setBlock(userIn,x,y,z,0);\n      return false;\n    }\n  }\n  if(id == 49 || id == 21 || id == 56 || id == 73 || id ==74 || id == 52)\n  {\n    if(item == 278 || item == 257)\n    {\n      return true;\n    }\n    else\n    {\n      setBlock(userIn,x,y,z,0);\n      return false;\n    }\n  }\n\n  \n  return true;\n}\n\nstd::string pluginName = \"nBreak\";\n\nPLUGIN_API_EXPORT void CALLCONVERSION nBreak_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) > 0)\n  {\n    std::string msg = \"nBreak is already loaded\";\n    mineserver->logger.log(6, \"plugin.nether\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(6, \"plugin.nBreak\", msg.c_str());\n\n  mineserver->plugin.setPluginVersion(pluginName.c_str(), PLUGIN_NBREAK_VERSION);\n\n  mineserver->plugin.addCallback(\"BlockBreakPre\", reinterpret_cast<voidF>(blockBreakPreFunction));\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION command_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) <= 0)\n  {\n    mineserver->logger.log(6, \"plugin.nBreak\", \"nBreak is not loaded!\");\n    return;\n  }\n}\n"
  },
  {
    "path": "plugins/nBreak/nBreak.h",
    "content": "#include <string>\n\n#ifndef _PLUGIN_COMMAND_H\n#define _PLUGIN_COMMAND_H\n\nstd::deque<std::string> parseCmd(std::string cmd);\n\n\n#endif\n"
  },
  {
    "path": "plugins/nether/nether.cpp",
    "content": "/*\ng++ -c nether.cpp\ng++ -shared nether.o -o nether.so\n\ncopy nether.so to Mineserver bin directory.\n*/\n/*\n  Copyright (c) 2010, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string>\n#include <deque>\n#include <ctime>\n#include <sstream>\n#include <cstdlib>\n#include <map>\n#include <vector>\n#include <iostream>\n#include <stdint.h>\n#include <cmath>\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n\n#include \"nether.h\"\n\n#define PLUGIN_NETHER_VERSION 1.1\n\n\nclass block\n{\npublic:\n  int x,y,z;\n  const char* name;\n  block(const char* n, int xx, int yy, int zz){\n    x=xx;y=yy;z=zz;name=n;\n  }\n};\n\nstd::vector<block*> blockToDo;\nstd::vector<block*> blockDone;\n\nconst char CHATCMDPREFIX   = '/';\nmineserver_pointer_struct* mineserver;\n\nstd::string dtos(double n)\n{\n  std::ostringstream result;\n  result << n;\n  return result.str();\n}\n\nvoid setBlock(const char* name,int x,int y,int z,unsigned char id)\n{\n  int map;\n  mineserver->user.getPositionW(name,NULL,NULL,NULL,&map,NULL,NULL,NULL);\n  mineserver->map.setBlockW(x,y,z,map,(unsigned char)id,0);\n}\n\nint getBlock(const char* name,int x,int y,int z)\n{\n  int map;\n  mineserver->user.getPositionW(name,NULL,NULL,NULL,&map,NULL,NULL,NULL);\n  unsigned char type, meta;\n  if(mineserver->map.getBlockW(x,y,z,map,&type,&meta))\n  {\n    return type;\n  }\n  return 0;\n}\n\nvoid addToDo(const char* user, int x, int y, int z){\n  for(size_t i = 0;i<blockToDo.size();i++){\n    block* c=blockToDo[i];\n    if(x==c->x && y==c->y && z==c->z)\n    {\n      return;\n    }\n  }\n  for(size_t i = 0;i<blockDone.size();i++){\n    block* c=blockDone[i];\n    if(x==c->x && y==c->y && z==c->z)\n    {\n      return;\n    }\n  }\n  block* b = new block(user,x,y,z);\n  blockToDo.push_back(b);\n}\n\nvoid doPortalFromFrame(const char* user, int x,int y, int z)\n{\n  bool up=false,down=false,left=false,right=false,forward=false,backward=false;\n  for(int c=1; c<10; c++) // Yes, we start at 1 so we DONT see the start again\n  {\n    if(getBlock(user,x,y+c,z)==49){ up=true; addToDo(user,x,y+c,z);}\n    if(getBlock(user,x,y-c,z)==49){ down=true; addToDo(user,x,y-c,z);}\n    if(getBlock(user,x+c,y,z)==49){ left=true; addToDo(user,x+c,y,z);}\n    if(getBlock(user,x-c,y,z)==49){ right=true; addToDo(user,x-c,y,z);}\n    if(getBlock(user,x,y,z+c)==49){ forward=true; addToDo(user,x,y,z+c);}\n    if(getBlock(user,x,y,z-c)==49){ backward=true; addToDo(user,x,y,z-c);}\n  }\n  for(int c=1; c<10; c++)\n  {\n    if(up)\n    {\n      if(getBlock(user,x,y+c,z)!=49)\n      {\n        setBlock(user,x,y+c,z,90);\n      }else{\n        up=false;\n      }\n    }\n    if(down)\n    {\n      if(getBlock(user,x,y-c,z)!=49)\n      {\n        setBlock(user,x,y-c,z,90);\n      }else{\n        down=false;\n      }\n    }\n    if(left)\n    {\n      if(getBlock(user,x+c,y,z)!=49)\n      {\n        setBlock(user,x+c,y,z,90);\n      }else{\n        left=false;\n      }\n    }\n    if(right)\n    {\n      if(getBlock(user,x-c,y,z)!=49)\n      {\n        setBlock(user,x-c,y,z,90);\n      }else{\n        right=false;\n      }\n    }\n    if(forward)\n    {\n      if(getBlock(user,x,y,z+c)!=49)\n      {\n        setBlock(user,x,y,z+c,90);\n      }else{\n        forward=false;\n      }\n    }\n    if(backward)\n    {\n      if(getBlock(user,x,y,z-c)!=49)\n      {\n        setBlock(user,x,y,z-c,90);\n      }else{\n        backward=false;\n      }\n    } \n  }\n}\n\nvoid doPortal(const char* user,int x,int y, int z)\n{\n  int cx=x,cy=y,cz=z;\n  addToDo(user,x,y,z);\n  while(blockToDo.size()>0)\n  {\n    doPortalFromFrame(user, blockToDo[0]->x, blockToDo[0]->y, blockToDo[0]->z);\n    blockDone.push_back(blockToDo[0]);\n    blockToDo.erase(blockToDo.begin());\n    cz ++;\n  }\n  for(size_t i = 0; i < blockDone.size(); i++)\n  {\n    delete blockDone[i];\n  }\n  blockDone.clear();\n}\n\nbool blockPlacePreFunction(const char* userIn, int32_t x, int32_t y, int32_t z,int16_t block, int8_t direction)\n{\n  if(block == 259){\n    // Should we trigger Portal creation?\n    if(getBlock(userIn,x,y,z)==49){\n      mineserver->logger.log(LOG_INFO, \"plugin.nether\", \"Portal triggered\");\n      doPortal(userIn,x,y,z);\n    }\n  }\n  return true;\n}\n\n\nvoid timer200Function()\n{\n  for (int i = 0; i < mineserver->user.getCount(); i++){\n    const char* const name = mineserver->user.getUserNumbered(i);\n    double x,y,z;\n    int map;\n    mineserver->user.getPositionW(name, &x,&y,&z,&map,NULL,NULL,NULL);\n    if(map<0 || map > 100)\n    {\n      // Watch out for this, means uninitialized!\n      continue;\n    }\n    unsigned char type, meta;\n    mineserver->map.getBlockW((int)floor(x),(int)floor(y),(int)floor(z),map,&type,&meta);\n    if((int)type == 90)\n    {\n      // They're on a portal TP TIEM\n      if(map==0){\n        // Normal > Nether\n        double nx, nz;\n        nx = x /16;\n        nz = z /16;\n        mineserver->user.teleportMap(name, nx,y+1,nz,1);\n      }else if(map==1){\n        double nx, nz;\n        nx = x * 16;\n        nz = z * 16;\n        mineserver->user.teleportMap(name, nx,y+1,nz,0);\n      }\n      // You're on another world? FIND YOUR OWN WAY BACK\n    }\n  }\n}\n\nstd::string pluginName = \"nether\";\n\nPLUGIN_API_EXPORT void CALLCONVERSION nether_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) > 0)\n  {\n    std::string msg = \"nether is already loaded v.\"+dtos(mineserver->plugin.getPluginVersion(pluginName.c_str()));\n    mineserver->logger.log(LOG_INFO, \"plugin.nether\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(LOG_INFO, \"plugin.nether\", msg.c_str());\n\n  mineserver->plugin.setPluginVersion(pluginName.c_str(), PLUGIN_NETHER_VERSION);\n\n  mineserver->plugin.addCallback(\"Timer200\", reinterpret_cast<voidF>(timer200Function));\n  mineserver->plugin.addCallback(\"BlockPlacePre\", reinterpret_cast<voidF>(blockPlacePreFunction));\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION command_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) <= 0)\n  {\n    mineserver->logger.log(LOG_INFO, \"plugin.nether\", \"nether is not loaded!\");\n    return;\n  }\n}\n"
  },
  {
    "path": "plugins/nether/nether.h",
    "content": "#include <string>\n\n#ifndef _PLUGIN_COMMAND_H\n#define _PLUGIN_COMMAND_H\n\nstd::deque<std::string> parseCmd(std::string cmd);\n\n\n#endif\n"
  },
  {
    "path": "plugins/passiveMobs/passiveMobs.cpp",
    "content": "/*\n  Copyright (c) 2010, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string>\n#include <deque>\n#include <ctime>\n#include <sstream>\n#include <cstdlib>\n#include <map>\n#include <vector>\n#include <iostream>\n#include <ctime>\n#include <stdint.h>\n#include <cmath>\n\n#include <memory>\n\n\n#define MINESERVER_C_API\n#include \"plugin_api.h\"\n#include \"tools.h\"\n\n#include \"passiveMobs.h\"\n\n#define PLUGIN_PASSIVEMOBS_VERSION 1.1\n\n#define PI 3.14159265\n\ndouble sin_lt[3600];\ndouble cos_lt[3600];\n\nconst char CHATCMDPREFIX   = '/';\nmineserver_pointer_struct* mineserver;\n\nstd::string dtos(double n)\n{\n  std::ostringstream result;\n  result << n;\n  return result.str();\n}\n\nstatic const int passiveMobs[] = { MOB_SHEEP, MOB_COW, MOB_CHICKEN, MOB_PIG };\n\n// The list of Mobs this plugin has control of\n// Note that other plugins may make other mobs, and control them itself\nclass MyPetMob\n{\npublic:\n  int ID;\n  int deSpawn;\n  int lastSay;\n  double velocity;\n  explicit MyPetMob(int ID, double velocity = 0) : ID(ID), deSpawn(0), velocity(velocity), lastSay(time(0)) { }\n};\n\ntypedef std::shared_ptr<MyPetMob> MyPetMobPtr;\n\nstd::vector<MyPetMobPtr> MyMobs;\n\nconst unsigned int maxMobs = 15; // Maximum ammount of mobs allowed\ntime_t lastSpawn = time(NULL);\n\nint topBlockSuitable(int x, int z, int w)\n{\n  int y;\n  unsigned char block, meta;\n  for(y = 127; y > 0; y--)\n  {\n    mineserver->map.getBlockW(x,y,z,w,&block,&meta);\n    if(block!=0){break;}\n  }\n  if(block == 78 || block == 2 || block == 38 || block == 37)\n  {\n    return y;\n  }\n  return 0;\n}\n\nbool canStepIn(int type)\n{\n  if(type == 0 || type == 6 || type == 8 || type == 9 || type == 10 ||\n    type == 11 || type == 37 || type == 38 || type == 39 || type == 40 ||\n    type == 50 || type == 51 || type == 55 || type == 59 ||\n    type == 69 || type == 70 || type == 72 || type == 75 || type == 76 ||\n    type == 77 || type == 78 || type == 83)\n    return true;\n  return false;\n}\n\nbool moveSuitable(double* x, double* y, double* z, int w)\n{\n  unsigned char block, meta;\n  mineserver->map.getBlockW((int)floor(*x),(int)*y,(int)floor(*z),w,&block,&meta);\n  return canStepIn(block);\n}\n\nvoid fallMob(double* x, double* y, double* z, int w)\n{\n  unsigned char block, meta;\n  for(int count = 1; count < 128; count ++)\n  {\n    mineserver->map.getBlockW((int)floor(*x),(int)(*y)-count,(int)floor(*z),w,&block,&meta);\n    if (!canStepIn(block))\n    {\n      *y=(1+(*y))-count;\n      return;\n    }\n  }\n}\n\nint defaultHealth(int mob)\n{\n  switch (mob)\n  {\n    case MOB_PIG:\n    case MOB_COW:\n    case MOB_SHEEP:\n      return 10;\n    case MOB_CHICKEN:\n      return 4;\n    default:\n      return 10;\n  }\n}\n\nint defaultDamage(int item)\n{\n  switch (item)\n  {\n    case ITEM_WOODEN_SWORD:\n    case ITEM_GOLD_SWORD:\n      return 5;\n    case ITEM_STONE_SWORD:\n      return 7;\n    case ITEM_IRON_SWORD:\n      return 9;\n    case ITEM_DIAMOND_SWORD:\n      return 11;\n    default:\n      return 2;\n  }\n}\n\nvoid spawn()\n{\n  if (MyMobs.size() < maxMobs &&\n      time(NULL)-lastSpawn > 2 &&\n      mineserver->user.getCount() > 0 &&\n      mineserver->map.getTime() <= 18000)\n  {\n    int randomPlayer = mineserver->tools.uniformInt(0, mineserver->user.getCount() - 1);\n    double x,y,z;\n    int w;\n    if (mineserver->user.getPositionW(mineserver->user.getUserNumbered(randomPlayer),&x,&y,&z,&w,NULL,NULL,NULL))\n    {\n      x += mineserver->tools.uniformInt(-50, 50);\n      z += mineserver->tools.uniformInt(-50, 50);\n      y = topBlockSuitable(x,z,w);\n      if (y > 0)\n      {\n        y+=1;\n        int type = passiveMobs[mineserver->tools.uniformInt(0, sizeof(passiveMobs) / sizeof(passiveMobs[0]) - 1)];\n        int newMob = mineserver->mob.createMob(type);\n        mineserver->mob.setHealth(newMob, defaultHealth(type));\n        MyPetMobPtr newMobData(new MyPetMob(newMob));\n        MyMobs.push_back(newMobData);\n        mineserver->mob.moveMobW(newMob,x,y,z,w);\n        mineserver->mob.spawnMob(newMob);\n        if (type == MOB_SHEEP)\n        {\n          int color = mineserver->tools.uniformInt(0, 15);\n          mineserver->mob.setByteMetadata(newMob, 16, (int8_t)color);\n          mineserver->mob.updateMetadata(newMob);\n        }\n        lastSpawn=time(NULL);\n      }\n    }\n  }\n}\n\nvoid timer200Function()\n{\n  spawn();\n\n  for (int i = MyMobs.size() - 1; i >= 0; i--)\n  {\n    double x,y,z;\n    int w;\n    // get position and world\n    mineserver->mob.getMobPositionW(MyMobs[i]->ID, &x, &y, &z, &w);\n    // kill dead mobs\n    if(mineserver->mob.getHealth(MyMobs[i]->ID) == 0)\n    {\n      if (MyMobs[i]->deSpawn < 12)\n      {\n        MyMobs[i]->deSpawn++;\n      }\n      else\n      {\n        mineserver->mob.despawnMob(MyMobs[i]->ID);\n        /* TODO: fix memory leak */\n        MyMobs.erase(MyMobs.begin()+i);\n      }\n      continue;\n    }\n    else\n    {\n      MyMobs[i]->deSpawn=0;\n    }\n    // get the nearest user\n    int nearest = 10000;\n    double nearest_x = .0, nearest_y = .0, nearest_z = .0;\n    for (int j = 0; j < mineserver->user.getCount(); j++)\n    {\n      const char * const name = mineserver->user.getUserNumbered(j);\n      double px,py,pz;\n      int pmap;\n      mineserver->user.getPositionW(name, &px,&py,&pz,&pmap,NULL,NULL,NULL);\n\n      if (w != pmap) { continue; }\n      int distance = abs(int(px-x)) + abs(int(py-y)) + abs(int(pz-z));\n      if(distance < nearest) {\n        nearest = distance;\n        nearest_x = px;\n        nearest_y = py;\n        nearest_z = pz;\n      }\n    }\n    if(nearest < 0 || nearest > 200)\n    {\n      // if there is no user here, despawn the mob\n      mineserver->mob.despawnMob(MyMobs[i]->ID);\n      MyMobs.erase(MyMobs.begin()+i);\n      continue;\n    }\n    // do something, my little mob\n    int action = rand() % 150;\n    double yaw, pitch, head_yaw;\n    float forward = 0;\n    mineserver->mob.getLook(MyMobs[i]->ID, &yaw, &pitch, &head_yaw);\n    if (action < 5)\n    {\n      yaw += 30;\n    }\n    else if (action < 10)\n    {\n      yaw += 15;\n      forward = 0.3;\n    }\n    else if (action < 15)\n    {\n      yaw -= 30;\n    }\n    else if (action < 20)\n    {\n      yaw -= 15;\n      forward = 0.3;\n    }\n    else if (action < 30)\n    {\n      forward = 0.6;\n    }\n    else if (action < 40)\n    {\n      // for now, just look around stupidly\n      head_yaw += rand() % 40;\n    }\n    else if (action < 50)\n    {\n      forward = -0.6;\n      // turn around!\n      yaw -= 180;\n    }\n    MyMobs[i]->velocity += forward;\n    if (MyMobs[i]->velocity > 2.0){ MyMobs[i]->velocity = 2.0; }\n    if (MyMobs[i]->velocity < 0.0){ MyMobs[i]->velocity = 0.0; }\n    forward = MyMobs[i]->velocity;\n\n    if (yaw <= 0) { yaw += 360; }\n    if (yaw >= 360) { yaw -= 360; }\n\n    // TODO: make it look at the player if he's near enough.\n    // (nearest_x, nearest_y, nearest_z).\n/*    if(nearest_z != z) {\n      head_yaw = RADIANS_TO_DEGREES(tan((nearest_x - x) / (nearest_z - z)));\n    }*/\n\n    if (forward>0.1 && rand()%6 == 3)\n    {\n      float incz = cos((yaw*PI)/180)* forward;\n      float incx = sin((yaw*PI)/180)* forward;\n      x-=incx; z+=incz;\n\n      if(moveSuitable(&x,&y,&z,w))\n      {\n        fallMob(&x,&y,&z,w);\n        mineserver->mob.moveMobW(MyMobs[i]->ID,x,y,z,w);\n\n        // Make stepping sounds\n        int type = mineserver->mob.getType(MyMobs[i]->ID);\n        if (type == MOB_SHEEP)  {\n          mineserver->tools.namedSoundEffect(\"mob.sheep.step\", x*32, y*32, z*32, 100.0f, 100);\n        } else if (type == MOB_COW) {    \n          mineserver->tools.namedSoundEffect(\"mob.cow.step\", x*32, y*32, z*32, 100.0f, 100);\n        } else if (type == MOB_CHICKEN) {\n          mineserver->tools.namedSoundEffect(\"mob.chicken.step\", x*32, y*32, z*32, 100.0f, 100);\n        } else if (type == MOB_PIG) {\n          mineserver->tools.namedSoundEffect(\"mob.pig.step\", x*32, y*32, z*32, 100.0f, 100);\n        }\n      }\n      fallMob(&x,&y,&z,w); // Even if they dont move, make them fall\n    }\n    mineserver->mob.setLook(MyMobs[i]->ID, yaw, pitch, head_yaw);\n\n    // Random noises\n    if (mineserver->tools.uniformInt(0, 255) > 240) {\n      if (time(NULL) - MyMobs[i]->lastSay > 2) {\n        MyMobs[i]->lastSay = time(NULL);\n        \n        char rand = mineserver->tools.uniformInt(80,100);\n        int type = mineserver->mob.getType(MyMobs[i]->ID);\n        if (type == MOB_SHEEP)  {\n          mineserver->tools.namedSoundEffect(\"mob.sheep.say\", x*32, y*32, z*32, 100.0f, rand);\n        } else if (type == MOB_COW) {    \n          mineserver->tools.namedSoundEffect(\"mob.cow.say\", x*32, y*32, z*32, 100.0f, rand);\n        } else if (type == MOB_CHICKEN) {\n          mineserver->tools.namedSoundEffect(\"mob.chicken.say\", x*32, y*32, z*32, 100.0f, rand);\n        } else if (type == MOB_PIG) {\n          mineserver->tools.namedSoundEffect(\"mob.pig.say\", x*32, y*32, z*32, 100.0f, rand);\n        }\n      }\n    }\n\n  }\n}\n\nvoid drop(int mobID)\n{\n  int type = mineserver->mob.getType(mobID);\n  double x,y,z;\n  int w;\n  mineserver->mob.getMobPositionW(mobID,&x,&y,&z,&w);\n  int item = 0, count = 1;\n  switch (type)\n  {\n    case MOB_PIG:\n      item = ITEM_PORK;\n      break;\n    case MOB_SHEEP:\n      /* sheep drops on first hit */\n      break;\n    case MOB_COW:\n      item = ITEM_LEATHER;\n      break;\n    case MOB_CHICKEN:\n      item = ITEM_FEATHER;\n      break;\n  }\n  if (item)\n  {\n    mineserver->map.createPickupSpawn((int)floor(x),(int)floor(y),(int)floor(z),\n                                      item, count, 0,NULL);\n  }\n}\n\nvoid gotAttacked(const char* userIn,int mobID)\n{\n  std::string user(userIn);\n  int atk_item, _meta, _quant;\n  mineserver->user.getItemInHand(userIn, &atk_item, &_meta, &_quant);\n  int mobHealth = mineserver->mob.getHealth((int)mobID);\n\n  if (mobHealth <= 0) return;\n\n  mobHealth -= defaultDamage(atk_item);\n  int type = mineserver->mob.getType(mobID);\n  double x, y, z; int w;\n  char rand = mineserver->tools.uniformInt(100,150);\n  mineserver->mob.getMobPositionW(mobID, &x, &y, &z, &w);\n  if (type == MOB_SHEEP)  {\n    mineserver->tools.namedSoundEffect(\"mob.sheep.say\", x*32, y*32, z*32, 100.0f, rand);\n  } else if (type == MOB_COW) {    \n    mineserver->tools.namedSoundEffect(\"mob.cow.say\", x*32, y*32, z*32, 100.0f, rand);\n  } else if (type == MOB_CHICKEN) {\n    mineserver->tools.namedSoundEffect(\"mob.chicken.say\", x*32, y*32, z*32, 100.0f, rand);\n  } else if (type == MOB_PIG) {\n    mineserver->tools.namedSoundEffect(\"mob.pig.say\", x*32, y*32, z*32, 100.0f, rand);\n  }\n\n  if (mobHealth <= 0)\n  {\n    drop(mobID);\n  }\n  mineserver->mob.setHealth((int)mobID, (int)mobHealth);\n}\n\nvoid interact(const char* userIn,int mobID)\n{\n  // Certain mobs drop something when the user interacts with them.\n  // Sheep drop wool.\n  std::string user(userIn);\n  int atk_item, _meta, _quant;\n  mineserver->user.getItemInHand(userIn, &atk_item, &_meta, &_quant);\n  int mobHealth = mineserver->mob.getHealth((int)mobID);\n\n  if (mobHealth <= 0) return;\n\n  int type = mineserver->mob.getType(mobID);\n  double x, y, z; int w;\n  mineserver->mob.getMobPositionW(mobID, &x, &y, &z, &w);\n  if (type == MOB_SHEEP)\n  {\n    // On unsheared sheeps, use a shear to obtain 1-3 wool blocks.\n    int8_t meta = mineserver->mob.getByteMetadata(mobID, 16);\n    if (atk_item == ITEM_SHEARS && !(meta & 0x10))\n    {\n      size_t amount = rand() % 3 + 1;\n      mineserver->map.createPickupSpawn((int)floor(x),(int)floor(y),(int)floor(z),\n                                        BLOCK_WOOL, amount, meta, NULL);\n      meta |= 0x10;\n      mineserver->mob.setByteMetadata(mobID, 16, meta);\n      mineserver->mob.updateMetadata(mobID);\n      mineserver->tools.namedSoundEffect(\"mob.sheep.shear\", x*32, y*32, z*32, 100.0f, 100);\n    }\n  } else if(type == MOB_COW)\n  {\n    if(atk_item == ITEM_BUCKET)\n    {\n      // give him milk, take the bucket!\n      _quant--;\n      mineserver->user.setItemInHand(userIn, atk_item, _meta, _quant);\n      mineserver->user.addItem(userIn, ITEM_MILK_BUCKET, 1, 0);\n    }\n  }\n}\n\nstd::string pluginName = \"passiveMobs\";\n\nPLUGIN_API_EXPORT void CALLCONVERSION passiveMobs_init(mineserver_pointer_struct* mineserver_temp)\n{\n  mineserver = mineserver_temp;\n\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) > 0)\n  {\n    std::string msg = atoi(pluginName.c_str())+ \" is already loaded v.\"+dtos(mineserver->plugin.getPluginVersion(pluginName.c_str()));\n    mineserver->logger.log(6, \"plugin.passiveMobs\", msg.c_str());\n    return;\n  }\n  std::string msg = \"Loaded \"+pluginName+\"!\";\n  mineserver->logger.log(6, \"plugin.passiveMobs\", msg.c_str());\n\n  mineserver->plugin.setPluginVersion(pluginName.c_str(), PLUGIN_PASSIVEMOBS_VERSION);\n\n  for(int i=0; i<3600; i ++){\n    sin_lt[i] = sin(((double)(i/10)*PI/180));\n    cos_lt[i] = cos(((double)(i/10)*PI/180));\n  }\n  mineserver->plugin.addCallback(\"Timer200\", reinterpret_cast<voidF>(timer200Function));\n  mineserver->plugin.addCallback(\"gotAttacked\", reinterpret_cast<voidF>(gotAttacked));\n  mineserver->plugin.addCallback(\"interact\", reinterpret_cast<voidF>(interact));\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION passiveMobs_shutdown(void)\n{\n  if (mineserver->plugin.getPluginVersion(pluginName.c_str()) <= 0)\n  {\n    mineserver->logger.log(6, \"plugin.passiveMobs\", atoi(pluginName.c_str()) + \" is not loaded!\");\n    return;\n  }\n}\n"
  },
  {
    "path": "plugins/passiveMobs/passiveMobs.h",
    "content": "#include <string>\n\n#ifndef _PLUGIN_MOBS_H\n#define _PLUGIN_MOBS_H\n\nstd::deque<std::string> parseCmd(std::string cmd);\n\n\n#endif\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 2.6)\n# forbid running cmake from this subdir\nif(PROJECT_NAME STREQUAL \"Project\")\n  message(FATAL_ERROR \"\\nplease run cmake from the project's parent directory\\n\")\nendif()\n\n#\n# Get Mineserver sources\n#\nFILE(GLOB_RECURSE ${PROJECT_NAME}_source RELATIVE ${PROJECT_SOURCE_DIR}/src/ \"*.cpp\")\n\n#\n# Remove any duplicates and sort the list\n#\nLIST(REMOVE_DUPLICATES ${PROJECT_NAME}_source)\nLIST(SORT ${PROJECT_NAME}_source)\n\n# Exclude sources in src/plugins directory, that's compiled elsewhere\nFOREACH(source ${${PROJECT_NAME}_source})\n  if(${source} MATCHES \"plugins/*\")\n    LIST(REMOVE_ITEM ${PROJECT_NAME}_source ${source})\n  ENDIF(${source} MATCHES \"plugins/*\")\nENDFOREACH(source ${${PROJECT_NAME}_source})\n\n# Set the list as s source group\nSOURCE_GROUP(${PROJECT_NAME} FILES ${${PROJECT_NAME}_source})\n\n# Override the default link destination\nSET(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"../${CONFIG_DIR_BIN}\")\n\n# Build Mineserver\nSET(TARGET ${PROJECT_NAME})\nMESSAGE(STATUS \"Target: ${TARGET}\")\nADD_EXECUTABLE(${TARGET} ${exe} ${${TARGET}_source})\nTARGET_LINK_LIBRARIES(${TARGET} ${CMAKE_DL_LIBS} ${mineserver_depends})\n\n# FOREACH(lib ${${TARGET}_depends})\n#   STRING(TOUPPER ${lib} LIB)\n#   INCLUDE_DIRECTORIES(${${LIB}_INCLUDE_DIR})\n#   TARGET_LINK_LIBRARIES(${TARGET} ${${LIB}_LIBRARY})\n# ENDFOREACH()\n\n# Where to install the target file.\ninstall(TARGETS ${PROJECT_NAME}\n  RUNTIME DESTINATION ${CONFIG_DIR_BIN}/\n)"
  },
  {
    "path": "src/SystemExceptions.h",
    "content": "/*\n  Copyright (c) 2011-2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n#ifndef SYSTEM_EXCEPTIONS_H\n#define SYSTEM_EXCEPTIONS_H\n\n#include <string>\n#include <exception>\n\nclass CoreException : public std::exception\n{\n public:\n\t// Holds the error message to be displayed\n\tconst std::string err;\n\t// Source of the exception\n\tconst std::string source;\n\t// Default constructor, just uses the error mesage 'Core threw an exception'.\n\tCoreException() : err(\"Core threw an exception\"), source(\"The core\") { }\n\t// This constructor can be used to specify an error message before throwing.\n\tCoreException(const std::string &message) : err(message), source(\"The core\") { }\n\t// This constructor can be used to specify an error message before throwing,\n\t// and to specify the source of the exception.\n\tCoreException(const std::string &message, const std::string &src) : err(message), source(src) { }\n\t// This destructor solves world hunger, cancels the world debt, and causes the world to end.\n\t// Actually no, it does nothing. Never mind.\n\tvirtual ~CoreException() throw() { };\n\t// Returns the reason for the exception.\n\t// The module should probably put something informative here as the user will see this upon failure.\n\tvirtual const char* GetReason() const\n\t{\n\t  return err.c_str();\n\t}\n\n\tvirtual const char* GetSource()\n\t{\n\t  return source.c_str();\n\t}\n};\n#endif"
  },
  {
    "path": "src/blocks/basic.cpp",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cmath>\n#include <cstdlib>\n\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"map.h\"\n\n#include \"basic.h\"\n#include \"protocol.h\"\n\n\nbool BlockBasic::isBlockStackable(const uint8_t block)\n{\n  /* Check block below allows blocks placed on top */\n  switch (block)\n  {\n  case BLOCK_WORKBENCH:\n  case BLOCK_CHEST:\n  case BLOCK_JUKEBOX:\n  case BLOCK_TORCH:\n  case BLOCK_REDSTONE_TORCH_OFF:\n  case BLOCK_REDSTONE_TORCH_ON:\n  case BLOCK_REDSTONE_WIRE:\n  case BLOCK_WATER:\n  case BLOCK_STATIONARY_WATER:\n  case BLOCK_LAVA:\n  case BLOCK_STATIONARY_LAVA:\n  case BLOCK_AIR:\n  case BLOCK_MINECART_TRACKS:\n  case BLOCK_WOODEN_DOOR:\n  case BLOCK_IRON_DOOR:\n  case BLOCK_ICE:\n  case BLOCK_CAKE:\n  case BLOCK_BED:\n  case BLOCK_LEVER:\n  case BLOCK_STONE_BUTTON:\n  case BLOCK_STONE_PRESSURE_PLATE:\n    return false;\n    break;\n  default:\n    break;\n  }\n\n  return true;\n}\n\nbool BlockBasic::isUserOnBlock(const int32_t x, const int16_t y, const int32_t z, const int map)\n{\n  /* TODO: Get Users by chunk rather than whole list */\n  for (std::set<User*>::iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    /* don't allow block placement on top of player */\n    if ((*it)->checkOnBlock(x, y, z) || (*it)->checkOnBlock(x, y - 1, z))\n    {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nbool BlockBasic::translateDirection(int32_t* x, int16_t* y, int32_t* z, int map, const int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(*x, *y, *z, &block, &meta);\n  if (block != BLOCK_SNOW)\n  {\n    switch (direction)\n    {\n    case BLOCK_SOUTH:\n      *x -= 1;\n      break;\n    case BLOCK_NORTH:\n      *x += 1;\n      break;\n    case BLOCK_EAST:\n      *z += 1;\n      break;\n    case BLOCK_WEST:\n      *z -= 1;\n      break;\n    case BLOCK_TOP:\n      *y += 1;\n      break;\n    case BLOCK_BOTTOM:\n      *y -= 1;\n      break;\n    default:\n      return false;\n      break;\n    }\n  }\n  return true;\n}\n\nbool BlockBasic::isBlockEmpty(const int32_t x, const int16_t y, const int32_t z, const int map)\n{\n  uint8_t block;\n  uint8_t meta;\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return false;\n  }\n  return (block == BLOCK_AIR || block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER || block == BLOCK_LAVA || block == BLOCK_STATIONARY_LAVA || block == BLOCK_SNOW);\n}\n\nbool BlockBasic::spawnBlockItem(const int32_t x, const int16_t y, const int32_t z, int map, const uint8_t block, const uint8_t meta)\n{\n  DropPtr drop;\n  int16_t item; uint8_t count, item_meta = meta;\n  BLOCKDROPS[block]->getDrop(item, count, item_meta);\n  if (count)\n  {\n    ServerInstance->map(map)->createPickupSpawn(x, y, z, item, count, item_meta, NULL);\n    return true;\n  }\n  return false;\n}\n\nvoid BlockBasic::notifyNeighbours(const int32_t x, const int16_t y, const int32_t z, const int map, const std::string callback, User* user, const uint8_t oldblock, const int8_t ignore_direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  //Call all onNeighbourMove callbacks for all the neighbouring blocks\n\n  if (ignore_direction != BLOCK_SOUTH && ServerInstance->map(map)->getBlock(x+1, y, z, &block, &meta) && block != BLOCK_AIR)\n  {\n    for(unsigned int i = 0; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      if(ServerInstance->plugin()->getBlockCB()[i]->affectedBlock(block))\n      {\n        ServerInstance->plugin()->getBlockCB()[i]->onNeighbourMove(user, 0, x+1, y, z, BLOCK_SOUTH, map);\n      }\n    }\n  }\n\n  if (ignore_direction != BLOCK_NORTH && ServerInstance->map(map)->getBlock(x-1, y, z, &block, &meta) && block != BLOCK_AIR)\n  {\n    for(unsigned int i = 0; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      if(ServerInstance->plugin()->getBlockCB()[i]->affectedBlock(block))\n      {\n        ServerInstance->plugin()->getBlockCB()[i]->onNeighbourMove(user, 0, x-1, y, z, BLOCK_NORTH, map);\n      }\n    }\n  }\n\n  if (y < 255 && ignore_direction != BLOCK_TOP && ServerInstance->map(map)->getBlock(x, y+1, z, &block, &meta) && block != BLOCK_AIR)\n  {\n    for(unsigned int i = 0; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      if(ServerInstance->plugin()->getBlockCB()[i]->affectedBlock(block))\n      {\n        ServerInstance->plugin()->getBlockCB()[i]->onNeighbourMove(user, 0, x, y+1, z, BLOCK_TOP, map);\n      }\n    }\n  }\n\n  if (y > 0 && ignore_direction != BLOCK_BOTTOM && ServerInstance->map(map)->getBlock(x, y-1, z, &block, &meta) && block != BLOCK_AIR)\n  {\n    for(unsigned int i = 0; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      if(ServerInstance->plugin()->getBlockCB()[i]->affectedBlock(block))\n      {\n        ServerInstance->plugin()->getBlockCB()[i]->onNeighbourMove(user, 0, x, y-1, z, BLOCK_BOTTOM, map);\n      }\n    }\n  }\n\n  if (ignore_direction != BLOCK_WEST && ServerInstance->map(map)->getBlock(x, y, z+1, &block, &meta) && block != BLOCK_AIR)\n  {\n    for(unsigned int i = 0; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      if(ServerInstance->plugin()->getBlockCB()[i]->affectedBlock(block))\n      {\n        ServerInstance->plugin()->getBlockCB()[i]->onNeighbourMove(user, 0, x, y, z+1, BLOCK_WEST, map);\n      }\n    }\n  }\n\n  if (ignore_direction != BLOCK_EAST && ServerInstance->map(map)->getBlock(x, y, z-1, &block, &meta) && block != BLOCK_AIR)\n  {\n    for(unsigned int i = 0; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      if(ServerInstance->plugin()->getBlockCB()[i]->affectedBlock(block))\n      {\n        ServerInstance->plugin()->getBlockCB()[i]->onNeighbourMove(user, 0, x, y, z-1, BLOCK_EAST, map);\n      }\n    }\n  }\n}\n\nvoid BlockBasic::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockBasic::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n}\n\nvoid BlockBasic::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n}\n\nbool BlockBasic::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n  //Clear block on destroy\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  spawnBlockItem(x, y, z, map, block, meta);\n  return false;\n}\n\nvoid BlockBasic::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n}\n\nbool BlockBasic::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n  // Don't allow placement of unknown blocks\n  revertBlock(user,x , y, z, map);\n  return false;\n}\n\nvoid BlockBasic::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n}\n\nvoid BlockBasic::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n}\n\nvoid BlockBasic::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int8_t direction)\n{\n}\n\nvoid BlockBasic::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int8_t direction, int map)\n{\n}\n\nbool BlockBasic::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  return false;\n}\n\nvoid BlockBasic::revertBlock(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  unsigned char block, meta;\n  ServerInstance->map(map)->getBlock((int)x, (int)y, (int)z, &block, &meta);\n  user->writePacket(Protocol::blockChange(x, y, z, block, meta));\n}\n"
  },
  {
    "path": "src/blocks/basic.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _BLOCKS_BASIC_H\n#define _BLOCKS_BASIC_H\n\n#include <stdint.h>\n#include <string>\n\n#include \"constants.h\"\n\nclass User;\n\n/**\n * BlockBasic can be used to extend your own block classes. It contains useful\n * methods for reuse in your own block extensions.\n */\nclass BlockBasic\n{\npublic:\n  // Base class needs virtual destructor.\n  virtual ~BlockBasic() { }\n\n  // Everybody MUST implement this, so we make it pure virtual.\n  virtual bool affectedBlock(int block) const = 0;\n\n  virtual void notifyNeighbours(const int32_t x, const int16_t y, const int32_t z,\n                                const int map, const std::string callback, User* user,\n                                const uint8_t oldblock, const int8_t ignore_direction);\n\n  virtual void timer200() { }\n  virtual void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  virtual void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  virtual void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  virtual bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  virtual void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  virtual bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  virtual void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  virtual void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  virtual void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int8_t direction);\n  virtual void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int8_t direction, int map);\n  virtual bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n  virtual void revertBlock(User* user, int32_t x, int16_t y, int32_t z, int map);\n\nprotected:\n  virtual bool isBlockStackable(const uint8_t block);\n  virtual bool isUserOnBlock(const int32_t x, const int16_t y, const int32_t z, const int map);\n  virtual bool translateDirection(int32_t* x, int16_t* y, int32_t* z, const int map, const int8_t direction);\n  virtual bool isBlockEmpty(const int32_t x, const int16_t y, const int32_t z, const int map);\n  virtual bool spawnBlockItem(const int32_t x, const int16_t y, const int32_t z, const int map, const uint8_t block, uint8_t meta = 0);\n};\n\n#endif\n"
  },
  {
    "path": "src/blocks/bed.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"bed.h\"\n\n\nvoid BlockBed::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockBed::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockBed::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockBed::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  return false;\n}\n\nvoid BlockBed::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockBed::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n  int zMod = 0, xMod = 0;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  // checking for an item rather then a block\n  if (newblock == ITEM_BED)\n  {\n    newblock = BLOCK_BED;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  switch (direction)\n  {\n  case BLOCK_EAST:\n    direction = BLOCK_SOUTH;\n  zMod = -1;\n  xMod = 0;\n    break;\n  case BLOCK_BOTTOM:\n    direction = BLOCK_EAST;\n  zMod = 0;\n  xMod = +1;\n    break;\n  case BLOCK_NORTH:\n    direction = BLOCK_NORTH;\n  zMod = 0;\n  xMod = -1;\n    break;\n  case BLOCK_SOUTH:\n    direction = BLOCK_BOTTOM;\n  zMod = +1;\n  xMod = 0;\n    break;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);\n\n  // set head of the bed\n  direction ^= 8;\n\n  ServerInstance->map(map)->setBlock(x + xMod, y, z + zMod, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x + xMod, y, z + zMod, (char)newblock, direction);\n  return false;\n}\n\nvoid BlockBed::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockBed::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockBed::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  return false;\n}\n"
  },
  {
    "path": "src/blocks/bed.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n\nclass BlockBed : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_BED || block == ITEM_BED; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int map, int32_t z, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n};\n\n"
  },
  {
    "path": "src/blocks/blockbrewingstand.cpp",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"tools.h\"\n\n#include \"blockbrewingstand.h\"\n\nbool BlockBrewingStand::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)BLOCK_BREWING_STAND, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)BLOCK_BREWING_STAND, 0);\n\n  // ToDo: Chunk->brewingstands\n  /*\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n  sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);\n\n  if (chunk == NULL)\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }  \n\n\n  for (uint32_t i = 0; i < chunk->brewingstands.size(); i++)\n  {\n    if (chunk->brewingstands[i]->x == x &&\n        chunk->brewingstands[i]->y == y &&\n        chunk->brewingstands[i]->z == z)\n    {\n      chunk->brewingstands.erase(chunk->brewingstands.begin() + i);\n      break;\n    }\n  }\n  */\n\n  return false;\n}\n\nbool BlockBrewingStand::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  ServerInstance->inventory()->windowOpen(user, WINDOW_BREWING_STAND, x, y, z);\n  return true;\n}\n\n\nbool BlockBrewingStand::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return true;\n  }\n\n  bool destroy = false;\n  // ToDo: Chunk->brewingstands\n  /*\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);\n\n  if (chunk == NULL)\n  {\n    return true;\n  }\n\n  for (uint32_t i = 0; i < chunk->brewingstands.size(); i++)\n  {\n    if (chunk->brewingstands[i]->x == x &&\n        chunk->brewingstands[i]->y == y &&\n        chunk->brewingstands[i]->z == z)\n    {\n      chunk->brewingstands.erase(chunk->furnaces.begin() + i);\n      break;\n    }\n  }\n  */\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block);\n  return false;\n}\n\n"
  },
  {
    "path": "src/blocks/blockbrewingstand.h",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockBrewingStand deals specifically with Brewing Stand interaction.\n@see BlockBasic\n*/\n\nclass BlockBrewingStand : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_BREWING_STAND || block == ITEM_BREWING_STAND; }\n\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n"
  },
  {
    "path": "src/blocks/blockfurnace.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"tools.h\"\n\n#include \"blockfurnace.h\"\n\nbool BlockFurnace::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  // Fix orientation  \n  switch (direction)\n  {\n  case BLOCK_EAST:\n    direction = 3;\n    break;\n  case BLOCK_BOTTOM:\n    direction = 4;\n    break;\n  case BLOCK_NORTH:\n    direction = 5;\n    break;\n  default:\n    direction = 2;\n    break;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);\n\n\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n  sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);\n\n  if (chunk == NULL)\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }  \n\n  for (uint32_t i = 0; i < chunk->furnaces.size(); i++)\n  {\n    if (chunk->furnaces[i]->x == x &&\n        chunk->furnaces[i]->y == y &&\n        chunk->furnaces[i]->z == z)\n    {\n      chunk->furnaces.erase(chunk->furnaces.begin() + i);\n      break;\n    }\n  }\n\n  return false;\n}\n\nbool BlockFurnace::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  ServerInstance->inventory()->windowOpen(user, WINDOW_FURNACE, x, y, z);\n  return true;\n}\n\n\nbool BlockFurnace::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return true;\n  }\n\n  bool destroy = false;\n\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);\n\n  if (chunk == NULL)\n  {\n    return true;\n  }\n\n  for (uint32_t i = 0; i < chunk->furnaces.size(); i++)\n  {\n    if (chunk->furnaces[i]->x == x &&\n        chunk->furnaces[i]->y == y &&\n        chunk->furnaces[i]->z == z)\n    {\n      chunk->furnaces.erase(chunk->furnaces.begin() + i);\n      break;\n    }\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block);\n  return false;\n}\n\n"
  },
  {
    "path": "src/blocks/blockfurnace.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockFurnace deals specifically with Furnace interaction.\nIt does not handle furnaces cooking, only right click interaction.\n@see BlockBasic\n*/\n\nclass BlockFurnace : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_FURNACE || block == BLOCK_BURNING_FURNACE; }\n\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n"
  },
  {
    "path": "src/blocks/cake.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"packets.h\"\n\n#include \"cake.h\"\n\n\nbool BlockCake::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_CAKE, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_CAKE, 0);\n  return false;\n}\n\nbool BlockCake::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  uint8_t block;\n  uint8_t metadata;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &metadata);\n  metadata = metadata + 1;\n  int healammount = 3;\n  int newhealth = user->health + healammount;\n\n  if (metadata < 6)\n  {\n    if (newhealth > 20)\n    {\n      newhealth = 20;\n    }\n    user->sethealth(newhealth);\n    ServerInstance->map(map)->setBlock(x, y, z, block, metadata);\n    ServerInstance->map(map)->sendBlockChange(x, y, z, (char)block, metadata);\n  }\n  else\n  {\n    if (newhealth > 20)\n    {\n      newhealth = 20;\n    }\n    user->sethealth(newhealth);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  }\n  return false;\n}\nvoid BlockCake::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockCake::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockCake::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return true;\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  return false;\n}\n"
  },
  {
    "path": "src/blocks/cake.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\nclass User;\n\n/** The BlockDefault type comprises of the functionality seen in most of the\nblocktypes in the game. These functions are reused and mixed with multiple\ndifferent blocks. */\n\nclass BlockCake: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_CAKE || block == ITEM_CAKE; }\n\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n};\n\n"
  },
  {
    "path": "src/blocks/chest.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"chest.h\"\n\n#include \"user.h\"\n#include \"permissions.h\"\n#include \"nbt.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"chat.h\"\n#include \"tools.h\"\n\nvoid BlockChest::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  // Locksystem\n  if (user->inv[36 + user->currentItemSlot()].getType() == ITEM_WOODEN_AXE)\n  {\n    int chunk_x = blockToChunk(x);\n    int chunk_z = blockToChunk(z);\n\n    sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);\n\n    if (chunk == NULL)\n    {\n      return;\n    }\n\n    NBT_Value* entityList = (*(*(chunk->nbt))[\"Level\"])[\"TileEntities\"];\n\n    if (!entityList)\n    {\n      entityList = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);\n      chunk->nbt->Insert(\"TileEntities\", entityList);\n    }\n\n    if (entityList->GetType() == NBT_Value::TAG_LIST)\n    {\n      if (entityList->GetListType() != NBT_Value::TAG_COMPOUND)\n      {\n        entityList->SetType(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);\n      }\n\n      std::vector<NBT_Value*> *entities = entityList->GetList();\n      std::vector<NBT_Value*>::iterator iter = entities->begin(), end = entities->end();\n\n      //bool done = false; // Unused variable\n\n      for (; iter != end; iter++)\n      {\n        if ((**iter)[\"x\"] == NULL || (**iter)[\"y\"] == NULL || (**iter)[\"z\"] == NULL ||\n            (**iter)[\"x\"]->GetType() != NBT_Value::TAG_INT ||\n            (**iter)[\"y\"]->GetType() != NBT_Value::TAG_INT ||\n            (**iter)[\"z\"]->GetType() != NBT_Value::TAG_INT)\n        {\n          continue;\n        }\n\n        if ((int32_t)(*(**iter)[\"x\"]) == x && (int32_t)(*(**iter)[\"y\"]) == y && (int32_t)(*(**iter)[\"z\"]) == z)\n        {\n          int8_t locked;\n          NBT_Value* nbtLockdata = (**iter)[\"Lockdata\"];\n          if (nbtLockdata != NULL)\n          {\n            std::string player = *(*nbtLockdata)[\"player\"]->GetString();\n            // Toggle lock if player is the owner of block\n            if (player == user->nick)\n            {\n              locked = *(*nbtLockdata)[\"locked\"];\n              locked = (locked == 1) ? 0 : 1;\n              *(*nbtLockdata)[\"locked\"] = locked;\n\n              if (locked == 1)\n              {\n                ServerInstance->chat()->sendMsg(user, MC_COLOR_RED + \"Chest locked\", Chat::USER);\n              }\n              else\n              {\n                ServerInstance->chat()->sendMsg(user, MC_COLOR_RED + \"Chest opened\", Chat::USER);\n              }\n\n            }\n          }\n          else\n          {\n            // If lockdata is missing (old chest)\n            NBT_Value* nbtLock = new NBT_Value(NBT_Value::TAG_COMPOUND);\n            nbtLock->Insert(\"player\", new NBT_Value(user->nick));\n            nbtLock->Insert(\"locked\", new NBT_Value((int8_t)1));\n            (*iter)->Insert(\"Lockdata\", nbtLock);\n          }\n          break;\n        }\n      }\n    }\n  }\n}\n\nvoid BlockChest::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockChest::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockChest::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return true;\n  }\n\n  bool destroy = false;\n\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  sChunk* chunk = ServerInstance->map(map)->loadMap(chunk_x, chunk_z);\n\n  if (chunk == NULL)\n  {\n    return true;\n  }\n\n  // Do quick connection test\n  chestDataPtr _thischest;\n  if (!getChestByCoordinates(x, y, z, map, _thischest)) {\n    _thischest = chestDataPtr(new chestData);\n    _thischest->x(x);\n    _thischest->y(y);\n    _thischest->z(z);\n    chunk->chests.push_back(_thischest);\n  }\n\n  if (!_thischest->large() && !_thischest->isConnectionChecked()) {\n    int32_t connectedChestX, connectedChestZ;\n    if (findConnectedChest(x, y, z, map, &connectedChestX, &connectedChestZ)) {\n      chestDataPtr _connectedChest;\n      if (!findConnectedChest(x, y, z, map, _connectedChest)) {\n        _connectedChest = chestDataPtr(new chestData);\n        _connectedChest->x(connectedChestX);\n        _connectedChest->y(y);\n        _connectedChest->z(connectedChestZ);\n        chunk->chests.push_back(_connectedChest);\n      }\n      _connectedChest->connect(vec(x,y,z),_thischest,true);\n      _thischest->connect(vec(connectedChestX,y,connectedChestZ),_connectedChest,false);\n    }\n  }\n  _thischest->setConnectionCheck();\n\n\n\n  chestDataPtr connected_chest = nullptr;\n\n  for (uint32_t i = 0; i < chunk->chests.size(); i++)\n  {\n    if (chunk->chests[i]->x() == x &&\n        chunk->chests[i]->y() == y &&\n        chunk->chests[i]->z() == z)\n    {    \n      // clean up a small chest\n      int32_t item_i = 26;\n      for(int32_t item_i = 26; 0 <= item_i; item_i--)\n      {\n        if ((*chunk->chests[i]->items())[(size_t)item_i]->getType() != -1)\n        {\n          ServerInstance->map(map)->createPickupSpawn(chunk->chests[i]->x(),\n              chunk->chests[i]->y(),\n              chunk->chests[i]->z(),\n              (*chunk->chests[i]->items())[(size_t)item_i]->getType(),\n              (*chunk->chests[i]->items())[(size_t)item_i]->getCount(),\n              (*chunk->chests[i]->items())[(size_t)item_i]->getHealth(),\n              NULL);\n        }\n        chunk->chests[i]->items()->pop_back();\n      }\n\n      // Store connected chest for large chests\n      if (chunk->chests[i]->large()) {\n        connected_chest = chunk->chests[i]->getConnectedData();\n      }\n\n      chunk->chests.erase(chunk->chests.begin() + i);\n\n      break;\n    }\n  }\n\n  if (connected_chest != nullptr)\n  {\n    // Clear connection before deletion -> prevent deletion loop\n    connected_chest->clearConnection();\n    // Destroy connected chest\n    onBroken(user, status, connected_chest->x(), connected_chest->y(), connected_chest->z(), map, direction);\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block);\n  return false;\n\n}\n\nvoid BlockChest::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockChest::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  // if there is a large chest around --> block\n  {\n    chestDataPtr _connectedChest;\n    if(findConnectedChest(x, y, z, map, _connectedChest))\n    {\n      if(_connectedChest->large())\n      {\n        revertBlock(user, x, y, z, map);\n        return true;\n      }\n    }\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  //// Fix orientation  \n  switch (direction)\n  {\n  case BLOCK_EAST:\n    //direction = BLOCK_SOUTH;\n    break;\n  case BLOCK_BOTTOM:\n    direction = BLOCK_WEST;\n    break;\n  case BLOCK_NORTH:\n    direction = BLOCK_TOP;\n    break;\n  case BLOCK_SOUTH:\n    //direction = BLOCK_NORTH;\n    break;\n  }\n  \n  // create a new (small) chest\n  chestDataPtr newchest(new chestData);\n  sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));\n  if(chunk != NULL)\n  {\n    newchest->x(x);\n    newchest->y(y);\n    newchest->z(z);\n    chunk->chests.push_back(newchest);\n  }  \n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);\n\n\n  int32_t connectedChestX, connectedChestZ;\n  if(findConnectedChest(x, y, z, map, &connectedChestX, &connectedChestZ))\n  {\n    if(connectedChestX != x)\n    {\n      if(!(direction == 3 || direction == 2))\n      {\n        direction = 3;\n      }\n    }\n    if(connectedChestZ != z)\n    {\n      if(!(direction == 4 || direction == 5))\n      {\n        direction = 4;\n      }\n    }\n\n    // Rotate the same way\n    ServerInstance->map(map)->setBlock(connectedChestX, y, connectedChestZ, (char)newblock, direction);\n    ServerInstance->map(map)->sendBlockChange(connectedChestX, y, connectedChestZ, (char)newblock, direction);\n\n    // Select \"top\" chest based on the coordinates\n    bool connected_top = connectedChestX < x || connectedChestZ < z;\n\n    // create a new chest and connect it to another chest --> large chest\n    chestDataPtr connectedChest;\n    if(getChestByCoordinates(connectedChestX, y, connectedChestZ, map, connectedChest))\n    {\n      // We cannot connect to an already connected chest\n      if(!connectedChest->large()) {\n       \n       connectedChest->connect(vec(x, y, z), newchest, connected_top);\n       newchest->connect(vec(connectedChestX, y, connectedChestZ), connectedChest, !connected_top);\n      }\n    } else { // Create chest data if not exist\n      chestDataPtr newConnectedChest(new chestData);\n      newConnectedChest->x(connectedChestX);\n      newConnectedChest->y(y);\n      newConnectedChest->z(connectedChestZ);\n      chunk->chests.push_back(newConnectedChest);\n      newConnectedChest->connect(vec(x, y, z), newchest, connected_top);\n      newchest->connect(vec(connectedChestX, y, connectedChestZ), newConnectedChest, !connected_top);\n    }\n  }\n  newchest->setConnectionCheck();\n\n  return false;\n}\n\nvoid BlockChest::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockChest::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockChest::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockChest::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  //ToDo: check for large chest!\n  sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));\n  if(chunk == NULL)\n  {\n    return false;\n  }\n\n    // Do quick connection test\n  chestDataPtr _thischest;\n  if (!getChestByCoordinates(x, y, z, map, _thischest)) {\n    _thischest = chestDataPtr(new chestData);\n    _thischest->x(x);\n    _thischest->y(y);\n    _thischest->z(z);\n    chunk->chests.push_back(_thischest);\n  }\n\n  if (!_thischest->large() && !_thischest->isConnectionChecked()) {\n    int32_t connectedChestX, connectedChestZ;\n    if (findConnectedChest(x, y, z, map, &connectedChestX, &connectedChestZ)) {\n      // Select \"top\" chest based on the coordinates\n      bool connected_top = connectedChestX < x || connectedChestZ < z;\n\n      chestDataPtr _connectedChest;\n      if (!findConnectedChest(x, y, z, map, _connectedChest)) {\n        _connectedChest = chestDataPtr(new chestData);\n        _connectedChest->x(connectedChestX);\n        _connectedChest->y(y);\n        _connectedChest->z(connectedChestZ);\n        chunk->chests.push_back(_connectedChest);\n      }\n      _connectedChest->connect(vec(x,y,z),_thischest, connected_top);\n      _thischest->connect(vec(connectedChestX,y,connectedChestZ),_connectedChest,!connected_top);\n    }\n  }\n  _thischest->setConnectionCheck();\n\n  if(_thischest != NULL)\n  {\n    ServerInstance->inventory()->windowOpen(user, (_thischest->large() ? WINDOW_LARGE_CHEST : WINDOW_CHEST), x, y, z);\n    return true;\n  } else {\n    return false;\n  }\n}\n\nbool BlockChest::findConnectedChest(int32_t x, int16_t y, int32_t z, int map, int32_t* chest_x, int32_t* chest_z)\n{\n  uint8_t blocktype, blockmeta;\n\n  *chest_x = x - 1;\n  *chest_z = z;\n  ServerInstance->map(map)->getBlock(*chest_x, y, *chest_z, &blocktype, &blockmeta);\n  if(blocktype == BLOCK_CHEST)\n    return true;\n\n  *chest_x = x + 1;\n  ServerInstance->map(map)->getBlock(*chest_x, y, *chest_z, &blocktype, &blockmeta);\n  if(blocktype == BLOCK_CHEST)\n    return true;\n\n  *chest_x = x;\n  *chest_z = z - 1;\n  ServerInstance->map(map)->getBlock(*chest_x, y, *chest_z, &blocktype, &blockmeta);\n  if(blocktype == BLOCK_CHEST)\n    return true;\n\n  *chest_x = x;\n  *chest_z = z + 1;\n  ServerInstance->map(map)->getBlock(*chest_x, y, *chest_z, &blocktype, &blockmeta);\n  if(blocktype == BLOCK_CHEST)\n    return true;\n\n  return false;\n}\n\nbool BlockChest::findConnectedChest(int32_t x, int16_t y, int32_t z, int map, chestDataPtr& chest)\n{\n  int32_t connectedX, connectedZ;\n  if(findConnectedChest(x, y, z, map, &connectedX, &connectedZ))\n  {\n    return getChestByCoordinates(connectedX, y, connectedZ, map, chest);\n  } else {\n    return false;\n  }\n}\n\nbool BlockChest::getChestByCoordinates(int32_t x, int16_t y, int32_t z, int map, chestDataPtr& chest)\n{\n  sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));\n  for(size_t i = 0; i < chunk->chests.size(); i++)\n  {\n    if((chunk->chests[i]->x() == x)\n      && (chunk->chests[i]->y() == y)\n      && (chunk->chests[i]->z() == z))\n    {\n      chest = chunk->chests[i];\n      return true;\n    }\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/blocks/chest.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include \"basic.h\"\n#include \"chunkmap.h\"\n\nclass User;\n\n/**\n * BlockChest deals specifically with chests\n * @see BlockBasic\n */\nclass BlockChest : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_CHEST; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int map, int32_t z, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int map, int32_t z, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n\n  /** finds the chest, that is connected to a block. gets coordinates. for large chests\n   * @param x x coordinate of the chest you know\n   * @param y y coordinate of the chest you know\n   * @param z z coordinate of the chest you know\n   * @param map map\n   * @param chest_x contains the x coordinate of the other chest part\n   * @param chest_z contains the z coordinate of the other chest part\n   * @returns true when a chest could be found, otherwise false.\n   */\n  bool findConnectedChest(int32_t x, int16_t y, int32_t z, int map, int32_t* chest_x, int32_t* chest_z);\n\n  /** find the chest, that is connected to a block. gets chestData.\n   * @param x x coordinate of the chest you know\n   * @param y y coordinate of the chest you know\n   * @param z z coordinate of the chest you know\n   * @param map map\n   * @param chest reference to a chestDataPtr. will be filled, if connected chest is found.\n   * @returns true when a chest could be found, otherwise false.\n   */\n  bool findConnectedChest(int32_t x, int16_t y, int32_t z, int map, chestDataPtr& chest);\n\n  /** gets the chestDataPtr for a cest at given coordinates\n   * @param x x coordinate of the chest\n   * @param y y coordinate of the chest\n   * @param z z coordinate of the chest\n   * @param chest is filled with the chestData, if the chest can be found\n   * @returns true, when a chest at given coordinates was found, otherwise false\n   */\n  bool getChestByCoordinates(int32_t x, int16_t y, int32_t z, int map, chestDataPtr& chest);\n\n};\n"
  },
  {
    "path": "src/blocks/default.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"default.h\"\n\n\nvoid BlockDefault::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockDefault::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockDefault::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockDefault::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n  if (block != BLOCK_WOOL && block != BLOCK_LOG && block != BLOCK_STEP)\n  {\n    // Only Cloth, Wood and Step have colour metadata\n    meta = 0;\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block, meta);\n  return false;\n}\n\nvoid BlockDefault::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockDefault::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (newblock > 255)\n  {\n    return true;\n  }\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  //direction = user->relativeToBlock(x, y, z);\n\n  if (newblock < 256)\n  {\n    ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, 0);\n    ServerInstance->map(map)->sendBlockChange(x, y, z, newblock, 0);\n  }\n  return false;\n}\n\nvoid BlockDefault::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockDefault::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  //ToDo: fix spawning items on replace\n  return;\n\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    return;\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->createPickupSpawn(x, y, z, oldblock, 1, 0, NULL);\n}\n\nvoid BlockDefault::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\n"
  },
  {
    "path": "src/blocks/default.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\nclass User;\n\n/** The BlockDefault type comprises of the functionality seen in most of the\nblocktypes in the game. These functions are reused and mixed with multiple\ndifferent blocks. */\n\nclass BlockDefault: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return true; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/door.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"mineserver.h\"\n#include \"map.h\"\n//#include \"logger.h\"\n\n#include \"door.h\"\n\n\nvoid BlockDoor::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, metadata;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &metadata);\n  \n  if (block != BLOCK_IRON_DOOR)\n  {\n\n  // Toggle door state\n  metadata ^= 0x4;\n\n  uint8_t metadata2, block2;\n\n  int modifier = ((metadata & 0x8) == 0x8) ? -1 : 1;\n  ServerInstance->map(map)->setBlock(x, y, z, block, metadata);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)block, metadata);\n\n  ServerInstance->map(map)->getBlock(x, y + modifier, z, &block2, &metadata2);\n\n  if (block2 == block)\n  {\n    if ((metadata2 & 0x4) && !(metadata & 0x4))\n    {\n      metadata2 ^= 0x4;\n    }\n    else if (!(metadata2 & 0x4) && (metadata & 0x4))\n    {\n      metadata2 ^= 0x4;\n    }\n\n    ServerInstance->map(map)->setBlock(x, y + modifier, z, block2, metadata2);\n    ServerInstance->map(map)->sendBlockChange(x, y + modifier, z, (char)block, metadata2);\n  }\n  }\n}\n\nvoid BlockDoor::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockDoor::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockDoor::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  // get block info\n  uint8_t block, metadata;\n  uint8_t metadata2, block2;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &metadata);\n  // check if block is the upper part of the door\n  int modifier = ((metadata & 0x8) == 0x8) ? -1 : 1;\n  ServerInstance->map(map)->getBlock(x, y + modifier, z, &block2, &metadata2);\n  // if upper part, remove it\n  if (block2 == block)\n  {\n    ServerInstance->map(map)->setBlock(x, y + modifier, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->sendBlockChange(x, y + modifier, z, BLOCK_AIR, 0);\n  }\n  // remove lower part\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block, 0);\n  return false;\n}\n\nvoid BlockDoor::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  // get block info\n  uint8_t block, metadata;\n  uint8_t metadata2, block2;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &metadata);\n  // check if block is the upper part of the door\n  int modifier = ((metadata & 0x8) == 0x8) ? -1 : 1;\n\n  ServerInstance->map(map)->getBlock(x, y + modifier, z, &block2, &metadata2);\n  if (metadata & 0x4)\n  {\n    metadata &= (0x8 | 0x3);\n  }\n  else\n  {\n    metadata |= 0x4;\n  }\n  // do nothing if the block is not below door\n  if (direction == BLOCK_BOTTOM && (block == BLOCK_WOODEN_DOOR || block == BLOCK_IRON_DOOR))\n  {\n    return;\n  }\n  // break the door if the block is below it\n  if (direction == BLOCK_TOP && (block == BLOCK_WOODEN_DOOR || block == BLOCK_IRON_DOOR))\n  {\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    this->spawnBlockItem(x, y, z, map, block, 0);\n\n    ServerInstance->map(map)->getBlock(x, y + modifier, z, &block2, &metadata2);\n\n    if (block2 == block)\n    {\n      metadata2 = metadata;\n\n      if (metadata & 0x8)\n      {\n        metadata2 &= 0x7;\n      }\n      else\n      {\n        metadata2 |= 0x8;\n      }\n\n      ServerInstance->map(map)->setBlock(x, y + modifier, z, BLOCK_AIR, 0);\n      ServerInstance->map(map)->sendBlockChange(x, y + modifier, z, BLOCK_AIR, 0);\n    }\n  }\n}\n\nbool BlockDoor::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  // checking for an item rather then a block\n  if (newblock == ITEM_WOODEN_DOOR)\n  {\n    newblock = BLOCK_WOODEN_DOOR;\n  }\n  else if (newblock == ITEM_IRON_DOOR)\n  {\n    newblock = BLOCK_IRON_DOOR;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  switch (direction)\n  {\n  case BLOCK_EAST:\n  //LOG(INFO, \"Map\", \"EAST\");\n    direction = BLOCK_EAST;\n    break;\n  case BLOCK_WEST:\n  //LOG(INFO, \"Map\", \"WEST\");\n    direction = BLOCK_WEST;\n    break;\n  case BLOCK_NORTH:\n  //LOG(INFO, \"Map\", \"NORTH\");\n    direction = BLOCK_SOUTH;\n    break;\n  case BLOCK_SOUTH:\n  //LOG(INFO, \"Map\", \"SOUTH\");\n    direction = BLOCK_NORTH;\n    break;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);\n\n  /* Get correct direction for top of the door */\n  direction ^= 8;\n\n  ServerInstance->map(map)->setBlock(x, y + 1, z, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y + 1, z, (char)newblock, direction);\n  return false;\n}\n\nvoid BlockDoor::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockDoor::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockDoor::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  uint8_t block, metadata;\n  uint8_t metadata2, block2;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &metadata);\n  int modifier = ((metadata & 0x8) == 0x8) ? -1 : 1;\n\n  if (block != BLOCK_IRON_DOOR)\n  {\n\n  ServerInstance->map(map)->getBlock(x, y + modifier, z, &block2, &metadata2);\n  if (metadata & 0x4)\n  {\n    metadata &= (0x8 | 0x3);\n  }\n  else\n  {\n    metadata |= 0x4;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, block, metadata);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)block, metadata);\n\n  ServerInstance->map(map)->getBlock(x, y + modifier, z, &block2, &metadata2);\n\n  if (block2 == block)\n  {\n    metadata2 = metadata;\n\n    if (metadata & 0x8)\n    {\n      metadata2 &= 0x7;\n    }\n    else\n    {\n      metadata2 |= 0x8;\n    }\n\n    ServerInstance->map(map)->setBlock(x, y + modifier, z, block2, metadata2);\n    ServerInstance->map(map)->sendBlockChange(x, y + modifier, z, (char)block, metadata2);\n  }\n }\n  return false;\n}\n"
  },
  {
    "path": "src/blocks/door.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockDoor deals specifically with Door block functionality.\n@see BlockBasic\n*/\n\nclass BlockDoor : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const\n  {\n    return block == BLOCK_WOODEN_DOOR || block == BLOCK_IRON_DOOR || block == ITEM_WOODEN_DOOR || block == ITEM_IRON_DOOR;\n  }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int map, int32_t z, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n};\n\n"
  },
  {
    "path": "src/blocks/falling.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdio.h>\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"plugin.h\"\n#include \"logger.h\"\n#include \"protocol.h\"\n#include \"physics.h\"\n\n#include \"falling.h\"\n\nbool BlockFalling::affectedBlock(int block) const\n{\n  if (block == BLOCK_SAND || block == BLOCK_SLOW_SAND || block == BLOCK_GRAVEL)\n    return true;\n  return false;\n}\n\nstd::string printfify(const char *fmt, ...)\n{\n  if(fmt)\n  {\n    va_list args;\n    char buf[4096];\n    va_start(args, fmt);\n    vsnprintf(buf, sizeof(buf), fmt, args);\n    va_end(args);\n    return buf;\n  }\n  else\n    return fmt;\n}\n\nvoid BlockFalling::onNeighbourBroken(User* user, int16_t, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  this->onNeighbourMove(user, 0, x, y, z, direction, map);\n}\n\nbool BlockFalling::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, newblock, 0);\n\n  applyPhysics(user, x, y, z, map);\n  return false;\n}\n\nvoid BlockFalling::onNeighbourMove(User* user, int16_t, int32_t x, int16_t y, int32_t z, int8_t direction, int map)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if(!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n    return;\n  if (affectedBlock(block))\n  {\n    applyPhysics(user, x, y, z, map);\n  }\n}\n\nvoid BlockFalling::applyPhysics(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  uint8_t fallblock, block;\n  uint8_t fallmeta, meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &fallblock, &fallmeta))\n  {\n    return;\n  }\n\n\n  \n  if (ServerInstance->map(map)->getBlock(x, y - 1, z, &block, &meta))\n  {\n    switch (block)\n    {\n    case BLOCK_AIR:\n    case BLOCK_WATER:\n    case BLOCK_STATIONARY_WATER:\n    case BLOCK_LAVA:\n    case BLOCK_STATIONARY_LAVA:\n    case BLOCK_SNOW:\n      break;\n    default:\n       return;\n      break;\n    }\n\n    // Destroy original block\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n\n    y--;\n\n\n    //Spawn an entity for the falling block\n    const int chunk_x = blockToChunk(x);\n    const int chunk_z = blockToChunk(z);\n\n    const ChunkMap::const_iterator it = ServerInstance->map(map)->chunks.find(Coords(chunk_x, chunk_z));\n\n    if (it == ServerInstance->map(map)->chunks.end())\n       return;\n\n    uint32_t EID = Mineserver::generateEID();\n    uint8_t object = 70; //type == Falling object\n    Packet pkt = Protocol::spawnObject(EID,object, (x<<5)+16, ((y+1)<<5)+16, (z<<5)+16, fallblock|(fallmeta<<0x10));\n    it->second->sendPacket(pkt);\n\n    //Add to physics loop\n    ServerInstance->physics(map)->addFallSimulation(fallblock,vec(x, y, z), EID);\n\n    this->notifyNeighbours(x, y + 1, z, map, \"onNeighbourMove\", user, fallblock, BLOCK_BOTTOM);\n\n  }\n}\n\n"
  },
  {
    "path": "src/blocks/falling.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _BLOCKS_FALLING_H\n#define _BLOCKS_FALLING_H\n\n#include \"basic.h\"\n#include \"user.h\"\n\n/**\n * BlockFalling deals specifically with blocks that fall when there are empty\n * blocks below them.\n * @see BlockBasic\n */\n\nclass BlockFalling: public BlockBasic\n{\npublic:\n  bool affectedBlock(int block) const;\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourMove(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int8_t direction, int map);\nprivate:\n  void applyPhysics(User* user, int32_t x, int16_t y, int32_t z, int map);\n};\n\n#endif\n"
  },
  {
    "path": "src/blocks/fire.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"fire.h\"\n\n\nvoid BlockFire::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockFire::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockFire::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockFire::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  return false;\n}\n\nvoid BlockFire::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  ServerInstance->map(map)->setBlock(x, y, z, (char)BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)BLOCK_AIR, 0);\n}\n\nbool BlockFire::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* burning block regardless of direction */\n  y++;\n\n  /* FIXME: Need this or should be just let em burn? */\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* if the block isn't empty then you can't burn it */\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)BLOCK_FIRE, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)BLOCK_FIRE, 0);\n  return false;\n}\n\nvoid BlockFire::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockFire::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n}\n\n"
  },
  {
    "path": "src/blocks/fire.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockFire deals specifically with fire block functionality.\n@see BlockBasic\n*/\nclass BlockFire : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_FIRE || block == ITEM_FLINT_AND_STEEL; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/ice.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"logger.h\"\n\n#include \"ice.h\"\n\nbool BlockIce::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_WATER, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_WATER, direction);\n  return true;\n}\n\nbool BlockIce::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (newblock > 255)\n  {\n    return true;\n  }\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  //direction = user->relativeToBlock(x, y, z);\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, 0);\n  return false;\n}\n\n"
  },
  {
    "path": "src/blocks/ice.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockIce deals specifically with ice, for instance breaking ice turning into water\n@see BlockBasic\n*/\n\nclass BlockIce : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_ICE; }\n\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n"
  },
  {
    "path": "src/blocks/jackolantern.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"jackolantern.h\"\n\n\nvoid Blockjackolantern::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid Blockjackolantern::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid Blockjackolantern::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool Blockjackolantern::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n\n  this->spawnBlockItem(x, y, z, map, block, 0);\n  return false;\n}\n\nvoid Blockjackolantern::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool Blockjackolantern::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  switch (direction)\n  {\n  case BLOCK_EAST:\n    direction = BLOCK_SOUTH;\n    break;\n  case BLOCK_BOTTOM:\n    direction = BLOCK_EAST;\n    break;\n  case BLOCK_NORTH:\n    direction = BLOCK_NORTH;\n    break;\n  case BLOCK_SOUTH:\n    direction = BLOCK_BOTTOM;\n    break;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), char(direction));\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), char(direction));\n\n  return false;\n}\n\nvoid Blockjackolantern::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid Blockjackolantern::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n"
  },
  {
    "path": "src/blocks/jackolantern.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n\nclass Blockjackolantern: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_JACK_O_LANTERN; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/ladder.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"ladder.h\"\n\n\nvoid BlockLadder::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockLadder::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockLadder::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockLadder::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block);\n  return false;\n}\n\nvoid BlockLadder::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  //Ladder is not attached to top or bottom block\n  if (direction == BLOCK_TOP || direction == BLOCK_BOTTOM)\n  {\n    return;\n  }\n\n  if ((meta == 2 && direction == BLOCK_EAST) ||\n      (meta == 3 && direction == BLOCK_WEST) ||\n      (meta == 4 && direction == BLOCK_NORTH) ||\n      (meta == 5 && direction == BLOCK_SOUTH))\n  {\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->createPickupSpawn(x, y, z, block, 1, 0, NULL);\n  }\n\n}\n\nbool BlockLadder::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  //Cant place ladders on top or bottom of the block\n  if (direction == BLOCK_TOP || direction == BLOCK_BOTTOM)\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  int8_t ladderDirection = 0;\n  switch (direction)\n  {\n  case BLOCK_WEST:\n    ladderDirection = 2;\n    break;\n  case BLOCK_EAST:\n    ladderDirection = 3;\n    break;\n  case BLOCK_SOUTH:\n    ladderDirection = 4;\n    break;\n  case BLOCK_NORTH:\n    ladderDirection = 5;\n    break;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, ladderDirection);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, ladderDirection);\n  return false;\n}\n\nvoid BlockLadder::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockLadder::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    return;\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->createPickupSpawn(x, y, z, oldblock, 1, 0, NULL);\n}\n\nvoid BlockLadder::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\n"
  },
  {
    "path": "src/blocks/ladder.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\nclass User;\n\n\nclass BlockLadder: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_LADDER; }\n\n  /** Fired when the player's begins swinging to hit a block\n     @param user The user who is digging\n     @param status\n     @param x The x position of the current block being hit\n     @param y The y position of the current block being hit\n     @param z The z position of the current block being hit\n     @param direction The direction that the user is facing\n   */\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when the player is digging\n     @param user The user who is digging\n     @param status\n     @param x The x position of the current block being hit\n     @param y The y position of the current block being hit\n     @param z The z position of the current block being hit\n     @param direction The direction that the user is facing\n   */\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when the player stops digging but hasn't broken the block\n     @param user The user who has stopped digging\n     @param status\n     @param x The x position of the current block not being hit anymore\n     @param y The y position of the current block not being hit anymore\n     @param z The z position of the current block not being hit anymore\n     @param direction The direction that the user is facing\n   */\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when the player has broken the block\n     @param user The user who has broken the block\n     @param status\n     @param x The x position of the block that has been broken\n     @param y The y position of the block that has been broken\n     @param z The z position of the block that has been broken\n     @param direction The direction that the user is facing\n   */\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when a neighbour block is broken.\n     @param user The user who broke the block\n     @param oldblock The type of block that was just broken\n     @param x The x position of the current neighbour block being called\n     @param y The y position of the current neighbour block being called\n     @param z The z position of the current neighbour block being called\n     @param direction The direction of the neighbour block that was broken\n   */\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when a block is placed\n     @param user The user who placed the block\n     @param newblock The block that is attempting to be placed\n     @param x The x position of where the block was placed\n     @param y The y position of where the block was placed\n     @param z The z position of where the block was placed\n     @param direction The direction that the user is facing\n   */\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when a neighbour block is placed\n     @param user The user who placed the block\n     @param newblock The block that is attempting to be placed\n     @param x The x position of the current neighbour block being called\n     @param y The y position of the current neighbour block being called\n     @param z The z position of the current neighbour block being called\n     @param direction The direction that the user is facing\n\n     @note You should only check if the block is of type BLOCK_AIR before placing. This\n     allows another block's onReplace method to either allow of deny the replacement\n     of a block with the block you're replacing it with.\n   */\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when a block is to be placed\n     @param user The user who placed the block\n     @param newblock The block that is attempting to replaced this block\n     @param x The x position of where the block is to be replaced\n     @param y The y position of where the block is to be replaced\n     @param z The z position of where the block is to be replaced\n     @param direction The direction of the neighbour block that was broken\n\n     @note To deny the replace simply to not change the block. To replace\n     the block change the block to be BLOCK_AIR and check for BLOCK_AIR\n     in the onPlace callback.\n   */\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  /** Fired when a neighbour block is moving position.\n     @param user The user who broke the block\n     @param oldblock The type of block that has moved\n     @param x The x position of the current neighbour block being called\n     @param y The y position of the current neighbour block being called\n     @param z The z position of the current neighbour block being called\n     @param direction The direction that the block was in\n   */\n  void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/leaves.cpp",
    "content": "/*\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <cmath>\n#include <algorithm>\n#include \"leaves.h\"\n#include \"map.h\"\n#include \"mineserver.h\"\n#include \"constants.h\"\n#include \"plugin.h\"\n\n\nbool BlockLeaves::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  std::set<Decay>::iterator it = std::find_if(decaying.begin(), decaying.end(), DecayFinder(x,y,z,map));\n\n  if (it != decaying.end()) decaying.erase(it);\n\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block, meta);\n\n  return true;\n}\n\nvoid BlockLeaves::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  if ( (oldblock != BLOCK_LOG && oldblock != BLOCK_LEAVES)   ||\n       std::find_if(decaying.begin(), decaying.end(), DecayFinder(x,y,z,map)) != decaying.end() )\n  {\n    return;\n  }\n\n  for (int xi = -2; xi <= 2; ++xi)\n    for (int yi = -2; yi <= 2; ++yi)\n      for (int zi = -2; zi <= 2; ++zi)\n        if (std::abs(xi) + std::abs(yi) + std::abs(zi) <= 3)\n        {\n          uint8_t block, meta;\n\n          ServerInstance->map(map)->getBlock(x + xi, y + yi, z + zi, &block, &meta);\n\n          if (block == BLOCK_LOG) return;\n        }\n\n  decaying.insert(Decay(time(0), x, y, z, map));\n}\n\ninline void decayIt(const Decay & decaying)\n{\n  uint8_t block, meta;\n  const Plugin::BlockCBs & plugins =  ServerInstance->plugin()->getBlockCB();\n\n  //this->notifyNeighbours(decaying[0].x,decaying[0].y,decaying[0].z,decaying[0].map,\"onNeighbourBroken\",0,BLOCK_LEAVES,0); // <--- USE THIS WHEN IT's FIXED\n\n  for (int xoff = -1; xoff <= 1; ++xoff)\n  {\n    for (int yoff = -1; yoff <= 1; ++yoff)\n    {\n      for (int zoff = -1; zoff <= 1; ++zoff)\n      {\n        ServerInstance->map(decaying.map)->getBlock(decaying.x + xoff, decaying.y + yoff, decaying.z + zoff, &block, &meta);\n\n        for (Plugin::BlockCBs::const_iterator i = plugins.begin(); i != plugins.end(); ++i)\n        {\n          if (*i != NULL && (*i)->affectedBlock(block))\n          {\n            (*i)->onNeighbourBroken(0, BLOCK_LEAVES, decaying.x + xoff, decaying.y + yoff, decaying.z + zoff, decaying.map, 0);\n          }\n        }\n      }\n    }\n  }\n\n  for (Plugin::BlockCBs::const_iterator i = plugins.begin(); i != plugins.end(); ++i)\n  {\n    if ((*i)->affectedBlock(BLOCK_LEAVES))\n    {\n      (*i)->onBroken(0, 0, decaying.x, decaying.y, decaying.z, decaying.map, 0);\n    }\n  }\n}\n\nvoid BlockLeaves::timer200()\n{\n  while (!decaying.empty())\n  {\n    Decay d = *decaying.begin(); // copy! might get deleted by decayIt()\n\n    if ((time(NULL) - d.decayStart) >= 5)\n    {\n      decayIt(d);\n      decaying.erase(d); // Erasing by value is safe, erases either 0 or 1 elements.\n    }\n    else\n    {\n      return;\n    }\n  }\n}\n"
  },
  {
    "path": "src/blocks/leaves.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _BLOCKS_LEAVES_H\n#define _BLOCKS_LEAVES_H\n\n#include <time.h>\n#include <set>\n\n#include \"basic.h\"\n\nstruct Decay\n{\n  Decay(time_t decayStart, int32_t x, int32_t y, int32_t z, int32_t map)\n    :\n    decayStart(decayStart),\n    x(x),\n    y(y),\n    z(z),\n    map(map)\n  {\n  }\n\n  inline bool operator<(const Decay& o) const\n  {\n    return decayStart < o.decayStart               // Oldest first\n      || (decayStart == o.decayStart && x < o.x)\n      || (decayStart == o.decayStart && x == o.x && y < o.y)\n      || (decayStart == o.decayStart && x == o.x && y == o.y && z < o.z)\n      || (decayStart == o.decayStart && x == o.x && y == o.y && z == o.z && map < o.map);\n  }\n\n  time_t decayStart;\n  int32_t x, y, z, map;\n};\n\nclass BlockLeaves : public BlockBasic\n{\n  std::set<Decay> decaying;\n\n  struct DecayFinder\n  {\n    DecayFinder(int32_t x, int32_t y, int32_t z, int32_t map) : x(x), y(y), z(z), map(map) { }\n    inline bool operator()(const Decay& d) const { return x == d.x && y == d.y && z == d.z && map == d.map; }\n  private:\n    int32_t x, y, z, map;\n  };\n\n\npublic:\n\n  inline bool affectedBlock(int block) const { return block == BLOCK_LEAVES; }\n\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n\n  void timer200();\n\n};\n\n#endif //_BLOCKS_LEAVES\n"
  },
  {
    "path": "src/blocks/liquid.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"physics.h\"\n#include \"liquid.h\"\n\n\nvoid BlockLiquid::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockLiquid::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockLiquid::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockLiquid::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  return false;\n}\n\nvoid BlockLiquid::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  physics(x, y, z, map);\n}\n\nbool BlockLiquid::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n\n  Item* item = &user->inv[user->curItem + 36];\n  if (newblock > 255)\n  {\n    if (item->getCount() > 1)\n    {\n      // Too many bugs working with multi-buckets\n      revertBlock(user, x, y, z, map);\n      item->sendUpdate();\n      return true;\n    }\n  }\n  // Remove liquid from map, add to bucket.\n  if (newblock == ITEM_BUCKET && oldmeta == 0 && affectedBlock(oldblock))\n  {\n    int new_item = -1;\n    if (oldblock == BLOCK_LAVA || oldblock == BLOCK_STATIONARY_LAVA)\n    {\n      new_item = ITEM_LAVA_BUCKET;\n    }\n    else\n    {\n      new_item = ITEM_WATER_BUCKET;\n    }\n    item->setType(new_item);\n\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    return true;\n  }\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    item->sendUpdate();\n    return true;\n  }\n  if (oldblock != BLOCK_AIR)\n  {\n    // Shouldnt replace liquids.\n    revertBlock(user, x, y, z, map);\n    item->sendUpdate();\n    return true;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  if (newblock == ITEM_WATER_BUCKET)\n  {\n    newblock = BLOCK_WATER;\n    item->setType(ITEM_BUCKET);\n  }\n  else if (newblock == ITEM_LAVA_BUCKET)\n  {\n    newblock = BLOCK_LAVA;\n    item->setType(ITEM_BUCKET);\n  }\n  else if (newblock > 255)\n  {\n    revertBlock(user, x, y, z, map);\n    item->sendUpdate();\n    return true;\n  }\n  else\n  {\n    item->decCount();\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, 0);\n\n  physics(x, y, z, map);\n  return true;\n}\n\nvoid BlockLiquid::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  physics(x, y, z, map);\n}\n\nvoid BlockLiquid::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n  if (newblock > 255)\n  {\n    return;\n  }\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    return;\n  }\n\n  ServerInstance->physics(map)->removeSimulation(vec(x, y, z));\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n}\n\nvoid BlockLiquid::physics(int32_t x, int16_t y, int32_t z, int map)\n{\n  ServerInstance->physics(map)->addSimulation(vec(x, y, z));\n  //ServerInstance->physics()->checkSurrounding(vec(x, y, z));\n}\n"
  },
  {
    "path": "src/blocks/liquid.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockLiquid deals specifically with block that have liquid functionality and need\nphysics applied to them.\n@see BlockBasic\n*/\nclass BlockLiquid: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const\n  { \n    return block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER || block == BLOCK_LAVA ||\n           block == BLOCK_STATIONARY_LAVA || block == ITEM_BUCKET || block == ITEM_WATER_BUCKET || block == ITEM_LAVA_BUCKET;\n  }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\nprivate:\n  void physics(int32_t x, int16_t y, int32_t z, int map);\n};\n\n"
  },
  {
    "path": "src/blocks/note.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"note.h\"\n\n\nbool BlockNote::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_NOTE_BLOCK, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_NOTE_BLOCK, 0);\n  return false;\n}\n\nvoid BlockNote::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, metadata;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &metadata);\n  ServerInstance->map(map)->sendNote(x, y, z, BlockNote::getInstrument(x, y - 1, z, map), metadata, block);\n}\n\nbool BlockNote::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  uint8_t block, metadata;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &metadata);\n  if (metadata == 0x14)\n  {\n    metadata = 0x00;\n    ServerInstance->map(map)->setBlock(x, y, z, block, metadata);\n    ServerInstance->map(map)->sendNote(x, y, z, BlockNote::getInstrument(x, y - 1, z, map), metadata, block);\n  }\n  else\n  {\n    metadata++;\n    ServerInstance->map(map)->setBlock(x, y, z, block, metadata);\n    ServerInstance->map(map)->sendNote(x, y, z, BlockNote::getInstrument(x, y - 1, z, map), metadata, block);\n  }\n  return true;\n}\n\nint BlockNote::getInstrument(int32_t x, int16_t y, int32_t z, int map)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n  switch (block)\n  {\n  case BLOCK_LOG:\n  case BLOCK_PLANK:\n    return INSTRUMENT_BASS;\n  case BLOCK_SAND:\n  case BLOCK_GRAVEL:\n  case BLOCK_SLOW_SAND:\n    return INSTRUMENT_SNARE;\n  case BLOCK_GLASS:\n  case BLOCK_GLOWSTONE:\n    return INSTRUMENT_STICK;\n  case BLOCK_STONE:\n  case BLOCK_COBBLESTONE:\n  case BLOCK_BRICK:\n  case BLOCK_OBSIDIAN:\n  case BLOCK_NETHERSTONE:\n  case BLOCK_IRON_ORE:\n  case BLOCK_DIAMOND_ORE:\n  case BLOCK_GOLD_ORE:\n  case BLOCK_FURNACE:\n  case BLOCK_BURNING_FURNACE:\n  case BLOCK_DISPENSER:\n    return INSTRUMENT_BASSDRUM;\n  }\n  return INSTRUMENT_HARP;\n}\n"
  },
  {
    "path": "src/blocks/note.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockNote deals specifically with Note block functionality.\n@see BlockBasic\n*/\n\nclass BlockNote : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_NOTE_BLOCK; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int map, int32_t z, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\nprivate:\n  int getInstrument(int32_t x, int16_t y, int32_t z, int map);\n};\n\n\n"
  },
  {
    "path": "src/blocks/planks.cpp",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"planks.h\"\n\n\nbool BlockPlanks::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  Item item = user->inv[user->curItem + 36];\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), char(item.getHealth()));\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), char(item.getHealth()));\n  return false;\n}\n"
  },
  {
    "path": "src/blocks/planks.h",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\nclass User;\n\nclass BlockPlanks: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_PLANK; }\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/plant.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cstdlib>\n#include <algorithm>\n\n#include \"plant.h\"\n#include \"mineserver.h\"\n#include \"config.h\"\n#include \"map.h\"\n\n\nstd::vector<PlantBlockPtr> growingPlants;\n\nBlockPlant::BlockPlant()\n{\n  grass_timeout = ServerInstance->config()->iData(\"mapgen.grassrate\");\n  crop_timeout = ServerInstance->config()->iData(\"mapgen.croprate\");\n  cactus_timeout = ServerInstance->config()->iData(\"mapgen.cactusrate\");\n  reed_timeout = ServerInstance->config()->iData(\"mapgen.reedrate\");\n  cactus_max = ServerInstance->config()->iData(\"mapgen.cactusmax\");\n  reed_max = ServerInstance->config()->iData(\"mapgen.reedmax\");\n}\n\nvoid BlockPlant::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n \n}\n\nvoid BlockPlant::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockPlant::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockPlant::addBlock(PlantBlockPtr p2)\n{\n  for (size_t i = 0; i < growingPlants.size(); ++i)\n  {\n    PlantBlockPtr p = growingPlants[i];\n    if (p->x == p2->x && p->y == p2->y && p->z == p2->z && p->map == p2->map)\n    {\n      return;\n    }\n  }\n  growingPlants.push_back(p2);\n}\n\nvoid BlockPlant::remBlock(PlantBlockPtr p)\n{\n  growingPlants.erase(std::remove(growingPlants.begin(), growingPlants.end(), p), growingPlants.end());\n}\n\nvoid BlockPlant::remBlock(int x, int y, int z, int map)\n{\n  growingPlants.erase(std::remove_if(growingPlants.begin(), growingPlants.end(), PlantBlockFinder(x,y,z,map)), growingPlants.end());\n}\n\nvoid BlockPlant::addBlock(int x, int y, int z, int map)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  const int b = block;\n\n  if (b == BLOCK_GRASS || b == BLOCK_DIRT || b == BLOCK_CROPS || b == BLOCK_REED || b == BLOCK_CACTUS)\n  {\n    addBlock(PlantBlockPtr(new PlantBlock(x, y, z, map, 0)));\n  }\n}\n\nvoid BlockPlant::addBlocks(int x, int y, int z, int map)\n{\n  addBlock(x - 1, y, z, map);\n  addBlock(x + 1, y, z, map);\n  addBlock(x, y - 1, z, map);\n  addBlock(x, y + 1, z, map);\n  addBlock(x, y, z - 1, map);\n  addBlock(x, y, z + 1, map);\n  addBlock(x - 1, y, z - 1, map);\n  addBlock(x - 1, y, z + 1, map);\n  addBlock(x + 1, y, z - 1, map);\n  addBlock(x + 1, y, z + 1, map);\n  addBlock(x + 1, y + 1, z, map);\n  addBlock(x - 1, y + 1, z, map);\n  addBlock(x, y + 1, z + 1, map);\n  addBlock(x, y + 1, z - 1, map);\n  addBlock(x + 1, y - 1, z, map);\n  addBlock(x - 1, y - 1, z, map);\n  addBlock(x, y - 1, z + 1, map);\n  addBlock(x, y - 1, z - 1, map);\n\n}\n\nvoid BlockPlant::timer200()\n{\n  for (int i = growingPlants.size() - 1; i >= 0; i--)\n  {\n    PlantBlockPtr p = growingPlants[i];\n    uint8_t block, meta, sky, light;\n\n    ServerInstance->map(p->map)->getBlock(p->x, p->y, p->z, &block, &meta);\n    ServerInstance->map(p->map)->getLight(p->x, p->y, p->z, &light, &sky);\n\n    p->count++;\n\n    if (p->count > grass_timeout * 5 && (block == BLOCK_DIRT || block == BLOCK_GRASS))\n    {\n      uint8_t block2, meta2;\n      ServerInstance->map(p->map)->getBlock(p->x, p->y + 1, p->z, &block2, &meta2);\n      if (block2 == BLOCK_AIR || block2 == BLOCK_SAPLING ||\n          block2 == BLOCK_LEAVES || block2 == BLOCK_GLASS ||\n          block2 == BLOCK_BROWN_MUSHROOM || block2 == BLOCK_RED_MUSHROOM ||\n          block2 == BLOCK_YELLOW_FLOWER || block2 == BLOCK_RED_ROSE ||\n          block2 == BLOCK_TORCH || block2 == BLOCK_FIRE ||\n          block2 == BLOCK_SAPLING || block2 == BLOCK_SIGN_POST ||\n          block2 == BLOCK_WOODEN_DOOR || block2 == BLOCK_LADDER ||\n          block2 == BLOCK_WALL_SIGN || block2 == BLOCK_LEVER ||\n          block2 == BLOCK_IRON_DOOR || block2 == BLOCK_REDSTONE_TORCH_OFF ||\n          block2 == BLOCK_REDSTONE_TORCH_ON || block2 == BLOCK_STONE_BUTTON ||\n          block2 == BLOCK_SNOW)\n      {\n        // The grass can grow\n        if (block == BLOCK_DIRT)\n        {\n          if (light > 4 || sky > 3)\n          {\n            ServerInstance->map(p->map)->sendBlockChange(p->x, p->y, p->z, (char)BLOCK_GRASS, 0);\n            ServerInstance->map(p->map)->setBlock(p->x, p->y, p->z, (char)BLOCK_GRASS, 0);\n            addBlocks(p->x, p->y, p->z, p->map);\n          }\n        }\n      }\n      else\n      {\n        if (block == BLOCK_GRASS)\n        {\n          ServerInstance->map(p->map)->sendBlockChange(p->x, p->y, p->z, (char)BLOCK_DIRT, 0);\n          ServerInstance->map(p->map)->setBlock(p->x, p->y, p->z, (char)BLOCK_DIRT, 0);\n          addBlocks(p->x, p->y, p->z, p->map);\n        }\n      }\n\n      remBlock(p);\n      continue;\n    }\n    if (p->count > crop_timeout * 5 && block == BLOCK_CROPS)\n    {\n      p->count = 0;\n      if (light > 7 || sky > 3)\n      {\n        if (meta < 7)\n        {\n          meta ++;\n        }\n        else\n        {\n          remBlock(p);\n          continue;\n        }\n        ServerInstance->map(p->map)->sendBlockChange(p->x, p->y, p->z, (char)BLOCK_CROPS, meta);\n        ServerInstance->map(p->map)->setBlock(p->x, p->y, p->z, (char)BLOCK_CROPS, meta);\n      }\n    }\n    if (p->count > cactus_timeout * 5 && block == BLOCK_CACTUS)\n    {\n      uint8_t block, meta;\n      if (!ServerInstance->map(p->map)->getBlock(p->x, p->y + 1, p->z, &block, &meta))\n      {\n        remBlock(p);\n        continue;\n      }\n      if (block != BLOCK_AIR)\n      {\n        remBlock(p);\n        continue;\n      }\n      p->count = 0;\n      for (int i = 0 ; i < cactus_max; i++)\n      {\n        ServerInstance->map(p->map)->getBlock(p->x, p->y - i, p->z, &block, &meta);\n        if (block != BLOCK_CACTUS && block != BLOCK_SAND)\n        {\n          onBroken(NULL, 0, p->x, p->y, p->z, p->map, 0);\n          remBlock(p);\n          i = cactus_max;\n        }\n        if (block == BLOCK_SAND)\n        {\n          ServerInstance->map(p->map)->sendBlockChange(p->x, p->y + 1, p->z, (char)BLOCK_CACTUS, 0);\n          ServerInstance->map(p->map)->setBlock(p->x, p->y + 1, p->z, (char)BLOCK_CACTUS, 0);\n          addBlocks(p->x, p->y, p->z, p->map);\n          break;\n        }\n      }\n    }\n    if (p->count > reed_timeout * 5 && (block == BLOCK_REED))\n    {\n      uint8_t block, meta;\n      if (!ServerInstance->map(p->map)->getBlock(p->x, p->y + 1, p->z, &block, &meta))\n      {\n        remBlock(p);\n        continue;\n      }\n      if (block != BLOCK_AIR)\n      {\n        remBlock(p);\n        continue;\n      }\n      p->count = 0;\n      for (int i = 0 ; i < reed_max; i++)\n      {\n        ServerInstance->map(p->map)->getBlock(p->x, p->y - i, p->z, &block, &meta);\n        if (block != BLOCK_REED && block != BLOCK_GRASS && block != BLOCK_DIRT)\n        {\n          onBroken(NULL, 0, p->x, p->y, p->z, p->map, 0);\n          remBlock(p);\n          i = reed_max;\n        }\n        if (block == BLOCK_GRASS || block == BLOCK_DIRT)\n        {\n          ServerInstance->map(p->map)->sendBlockChange(p->x, p->y + 1, p->z, (char)BLOCK_REED, 0);\n          ServerInstance->map(p->map)->setBlock(p->x, p->y + 1, p->z, (char)BLOCK_REED, 0);\n          addBlocks(p->x, p->y, p->z, p->map);\n          break;\n        }\n      }\n    }\n\n  }\n}\n\n\nbool BlockPlant::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  remBlock(x, y, z, map);\n  if (block == BLOCK_CROPS && meta == 7)\n  {\n    ServerInstance->map(map)->createPickupSpawn(x, y + 1, z, ITEM_WHEAT, 1, 0, NULL);\n  }\n  else if (block == BLOCK_CROPS)\n  {\n    ServerInstance->map(map)->createPickupSpawn(x, y + 1, z, ITEM_SEEDS, 1, 0, NULL);\n  }\n  else if (block == BLOCK_REED)\n  {\n    ServerInstance->map(map)->createPickupSpawn(x, y + 1, z, ITEM_REED, 1, 0, NULL);\n  }\n  else\n  {\n    this->spawnBlockItem(x, y, z, map, block);\n  }\n  ServerInstance->map(map)->getBlock(x, y + 1, z, &block, &meta);\n  if (isPlant(block))\n  {\n    onBroken(user, status, x, y + 1, z, map, direction);\n  }\n  return false;\n}\n\nvoid BlockPlant::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  //   uint8_t block,meta,up_block,up_meta;\n  //   if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  //     return;\n  //   if (!ServerInstance->map(map)->getBlock(x, y-1, z,&up_block, &up_meta))\n  //     return;\n  //\n  //   if (direction == BLOCK_TOP && isPlant(up_block))\n  //   {\n  //      // Break plant and spawn plant item\n  //      ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  //      ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  //      this->spawnBlockItem(x, y, z, map, block);\n  //   }\n}\n\nbool BlockPlant::isPlant(int num)\n{\n  return (num == BLOCK_CROPS || num == BLOCK_CACTUS || num == BLOCK_YELLOW_FLOWER || num == BLOCK_RED_ROSE || num == BLOCK_REED || num == BLOCK_SAPLING || num == BLOCK_RED_MUSHROOM || num == BLOCK_BROWN_MUSHROOM);\n}\n\nbool BlockPlant::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!ServerInstance->map(map)->getBlock(x, y - 1, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (newblock != BLOCK_DIRT && newblock != BLOCK_SOIL && newblock != BLOCK_GRASS)\n  {\n    if (this->isBlockEmpty(x, y - 1, z, map) || !this->isBlockEmpty(x, y, z, map))\n    {\n      revertBlock(user, x, y, z, map);\n      return true;\n    }\n\n    if (!this->isBlockStackable(oldblock))\n    {\n      revertBlock(user, x, y, z, map);\n      return true;\n    }\n  }\n  else\n  {\n    if (this->isUserOnBlock(x, y, z, map))\n    {\n      revertBlock(user, x, y, z, map);\n      return true;\n    }\n  }\n\n  if ((newblock == BLOCK_REED || newblock == ITEM_REED) && (oldblock == BLOCK_GRASS || oldblock == BLOCK_DIRT))\n  {\n    // TODO : Check for water\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_REED, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_REED, 0);\n    addBlock(x, y, z, map);\n    return false;\n  }\n\n  if (newblock == BLOCK_CACTUS && oldblock != BLOCK_SAND)\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if ((newblock == BLOCK_YELLOW_FLOWER  ||\n       newblock == BLOCK_RED_ROSE) && (oldblock != BLOCK_DIRT &&\n                                       oldblock != BLOCK_GRASS))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if ((newblock == ITEM_SEEDS || newblock == BLOCK_CROPS) && (oldblock == BLOCK_SOIL))\n  {\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_CROPS, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_CROPS, 0);\n    addBlock(x, y, z, map);\n    return false;\n  }\n\n  if ((newblock == ITEM_SEEDS || newblock == BLOCK_CROPS))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (newblock > 255 && (oldblock == BLOCK_DIRT  || oldblock == BLOCK_GRASS))\n  {\n    // Hoe on dirt = Soil\n    ServerInstance->map(map)->sendBlockChange(x, y - 1, z, BLOCK_SOIL, 0);\n    ServerInstance->map(map)->setBlock(x, y - 1, z, BLOCK_SOIL, 0);\n    if (SEEDS_CHANCE >= rand() % 10000)\n    {\n      ServerInstance->map(map)->createPickupSpawn(x, y + 1, z, ITEM_SEEDS, 1, 0, NULL);\n    }\n    return true;\n  }\n\n  if (newblock > 255)\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if ((newblock == BLOCK_BROWN_MUSHROOM || newblock == BLOCK_RED_MUSHROOM)\n      && oldblock != BLOCK_DIRT)\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (newblock == BLOCK_SAPLING)\n  {\n    ServerInstance->map(map)->addSapling(user, x, y, z);\n  }\n\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), 0);\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), 0);\n  addBlocks(x, y, z, map);\n\n  return false;\n}\n\nvoid BlockPlant::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  addBlocks(x, y, z, map);\n}\n\nvoid BlockPlant::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n"
  },
  {
    "path": "src/blocks/plant.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n\n#ifndef _BLOCKS_PLANT_H\n#define _BLOCKS_PLANT_H\n\n#include \"basic.h\"\n\n#include <memory>\n\n\n// 10000 == 100%\nenum { SEEDS_CHANCE = 1000 };\n\nclass User;\n\nclass PlantBlock\n{\npublic:\n  PlantBlock(int x, int y, int z, int map, int count) : x(x), y(y), z(z), map(map), count(count) { }\n  int x, y, z, map, count;\n};\n\ntypedef std::shared_ptr<PlantBlock> PlantBlockPtr;\n\nstruct PlantBlockFinder\n{\n  PlantBlockFinder(int x, int y, int z, int map) : x(x), y(y), z(z), map(map) { }\n  inline bool operator()(const PlantBlockPtr & t) const { return t->x == x && t->y == y && t->z == z && t->map == map; }\n  int x, y, z, map;\n};\n\n/** BlockPlant deals specifically with plant block functionality\n@see BlockBasic\n*/\nclass BlockPlant: public BlockBasic\n{\npublic:\n  int grass_timeout;\n  int crop_timeout;\n  int cactus_timeout;\n  int reed_timeout;\n  int cactus_max;\n  int reed_max;\n\n  inline bool affectedBlock(int block) const\n  {\n    return block == BLOCK_YELLOW_FLOWER || block == BLOCK_RED_ROSE || block == BLOCK_BROWN_MUSHROOM || block == BLOCK_RED_MUSHROOM || block == BLOCK_CROPS || block == BLOCK_CACTUS || block == BLOCK_REED || block == BLOCK_SAPLING || block == BLOCK_DIRT || block == BLOCK_GRASS || block == BLOCK_SOIL || block == ITEM_REED || block == ITEM_WOODEN_HOE || block == ITEM_STONE_HOE || block == ITEM_IRON_HOE || block == ITEM_DIAMOND_HOE || block == ITEM_GOLD_HOE || block == ITEM_SEEDS;\n  }\n\n  BlockPlant();\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void timer200();\n  void addBlocks(int x, int y, int z, int map);\n  void addBlock(PlantBlockPtr p2);\n  void addBlock(int x, int y, int z, int map);\n  void remBlock(PlantBlockPtr p2);\n  void remBlock(int x, int y, int z, int map);\n  bool isPlant(int num);\n};\n\n\n#endif\n"
  },
  {
    "path": "src/blocks/pumpkin.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"pumpkin.h\"\n\n\nvoid BlockPumpkin::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockPumpkin::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockPumpkin::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockPumpkin::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n\n  this->spawnBlockItem(x, y, z, map, block, 0);\n  return false;\n}\n\nvoid BlockPumpkin::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockPumpkin::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n\n  switch (direction)\n  {\n  case BLOCK_EAST:\n    direction = BLOCK_SOUTH;\n    break;\n  case BLOCK_BOTTOM:\n    direction = BLOCK_EAST;\n    break;\n  case BLOCK_NORTH:\n    direction = BLOCK_NORTH;\n    break;\n  case BLOCK_SOUTH:\n    direction = BLOCK_BOTTOM;\n    break;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), char(direction));\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), char(direction));\n\n  return false;\n}\n\nvoid BlockPumpkin::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockPumpkin::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n"
  },
  {
    "path": "src/blocks/pumpkin.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n\nclass BlockPumpkin: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_PUMPKIN; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/redstone.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"logger.h\"\n#include \"redstoneSimulation.h\"\n#include \"vec.h\"\n\n#include \"redstone.h\"\n\n\nvoid BlockRedstone::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstone::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstone::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockRedstone::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(BLOCK_AIR), 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(BLOCK_AIR), 0);\n\n  spawnBlockItem(x, y, z, map, uint8_t(BLOCK_REDSTONE_WIRE), 0);\n\n  ServerInstance->redstone(map)->addSimulation(vec(x,y,z));\n\n  return false;\n}\n\nvoid BlockRedstone::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return;\n  }\n\n  if (isBlockEmpty(x, y - 1, z, map))\n  {\n    // Break torch and spawn torch item\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    spawnBlockItem(x, y, z, map, block);\n  }\n}\n\nbool BlockRedstone::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!isBlockStackable(block))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  newblock = 55;\n  meta = 0;\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), meta);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), meta);\n\n  ServerInstance->redstone(map)->addSimulation(vec(x,y,z));\n\n  return false;\n}\n\nvoid BlockRedstone::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstone::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstone::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n"
  },
  {
    "path": "src/blocks/redstone.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockRedstone deals specifically with minecart tracks\n@see BlockBasic\n*/\nclass BlockRedstone: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_REDSTONE_WIRE || block == ITEM_REDSTONE; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\nprivate:\n\n};\n"
  },
  {
    "path": "src/blocks/redstoneutil.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"logger.h\"\n#include \"redstoneSimulation.h\"\n#include \"vec.h\"\n\n#include \"redstoneutil.h\"\n\n\nvoid BlockRedstoneUtil::timer200() {\n  // Loop activated buttons -list\n  for (PositionList::iterator iter = activated.begin(); iter != activated.end();) {\n    if (!(--iter->timeleft)) {\n      uint8_t block;\n      uint8_t meta;\n      if (ServerInstance->map(iter->map)->getBlock(iter->x, iter->y, iter->z, &block, &meta)) {\n        // Enable button\n        meta ^= 0x08;\n\n        // Save the block\n        ServerInstance->map(iter->map)->setBlock(iter->x, iter->y, iter->z, char(block), meta);\n        ServerInstance->map(iter->map)->sendBlockChange(iter->x, iter->y, iter->z, char(block), meta);\n      }\n\n      // Remove button from list\n      iter = activated.erase(iter);\n    }\n    else {\n      iter++;\n    }\n  }\n}\n\nvoid BlockRedstoneUtil::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  this->onInteract(user, x, y, z, map);\n}\n\nvoid BlockRedstoneUtil::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstoneUtil::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstoneUtil::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n  bool destroy = false;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return;\n  }\n\n  if (direction == BLOCK_TOP && meta == BLOCK_TOP && this->isBlockEmpty(x, y - 1, z, map))\n  {\n    destroy = true;\n    // Crude fix for weird sign destruction\n    uint8_t tempblock;\n    uint8_t tempmeta;\n    if (ServerInstance->map(map)->getBlock(x, y, z, &tempblock, &tempmeta) && tempblock == BLOCK_WALL_SIGN)\n    {\n      destroy = false;\n    }\n  }\n  else if (direction == BLOCK_NORTH && meta == BLOCK_SOUTH && this->isBlockEmpty(x + 1, y, z, map))\n  {\n    destroy = true;\n  }\n  else if (direction == BLOCK_SOUTH && meta == BLOCK_NORTH && this->isBlockEmpty(x - 1, y, z, map))\n  {\n    destroy = true;\n  }\n  else if (direction == BLOCK_EAST && meta == BLOCK_WEST && this->isBlockEmpty(x, y, z + 1, map))\n  {\n    destroy = true;\n  }\n  else if (direction == BLOCK_WEST && meta == BLOCK_EAST && this->isBlockEmpty(x, y, z - 1, map))\n  {\n    destroy = true;\n  }\n\n  if (destroy)\n  {\n    // Break switch and spawn item\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    this->spawnBlockItem(x, y, z, map, block);\n  }\n}\n\nbool BlockRedstoneUtil::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta = 0;\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!isBlockStackable(block))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n\n  // Check that switch is placed on legal direction\n  if ((newblock == BLOCK_STONE_BUTTON && (direction == BLOCK_TOP || direction == BLOCK_BOTTOM))\n  || ((newblock == BLOCK_STONE_PRESSURE_PLATE || newblock == BLOCK_WOODEN_PRESSURE_PLATE) && direction != BLOCK_TOP)) {\n  revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  // Set metadata for the position\n  if (newblock == BLOCK_STONE_BUTTON || newblock == BLOCK_LEVER) {\n    // Wall switch\n    if (direction != BLOCK_TOP && direction != BLOCK_BOTTOM) {\n    meta = direction;\n    }\n    // Ceiling lever\n    else if (direction == BLOCK_BOTTOM) {\n      int yaw = abs(int(user->pos.yaw)) % 360;\n      if ((yaw > 45 && yaw <= 135) || (yaw > 225 && yaw <= 315)) {\n        meta = 0x00;\n      }\n      else {\n        meta = 0x07;\n      }\n    }\n    // Floor lever\n    else {\n      int yaw = abs(int(user->pos.yaw)) % 360;\n      if ((yaw > 45 && yaw <= 135) || (yaw > 225 && yaw <= 315)) {\n        meta = 0x06;\n      }\n      else {\n        meta = 0x05;\n      }\n    }\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), meta);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), meta);\n\n  return false;\n}\n\nvoid BlockRedstoneUtil::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstoneUtil::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockRedstoneUtil::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockRedstoneUtil::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map) {\n  uint8_t block = 0;\n  uint8_t meta = 0;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return true;\n  }\n\n  if (block == BLOCK_STONE_BUTTON) {\n    // Enable button if it's not already enabled\n    if ((meta & 0x08) != 0) {\n    return true;\n    }\n    \n    meta |= 0x08;\n\n    // Save button position\n    activated.push_back(Position(x, y, z, map));\n  }\n  else if (block == BLOCK_LEVER) {\n    // Enable/disable lever\n    meta ^= 0x08;\n  }\n  else {\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(block), meta);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(block), meta);\n\n  return true;\n}"
  },
  {
    "path": "src/blocks/redstoneutil.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef BLOCK_REDSTONE_UTIL_H\n#define BLOCK_REDSTONE_UTIL_H\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockRedstoneUtil deals specifically with redstone stuff\n@see BlockBasic\n*/\nclass BlockRedstoneUtil : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_STONE_BUTTON || block == BLOCK_LEVER || block == BLOCK_STONE_PRESSURE_PLATE || block == BLOCK_WOODEN_PRESSURE_PLATE; }\n\n  void timer200();\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\nprivate:\n  struct Position {\n    Position(int32_t _x, int16_t _y, int32_t _z, int _map)\n      : x(_x), y(_y), z(_z), map(_map), timeleft(5) {}\n    int32_t x;\n    int16_t y;\n    int32_t z;\n    int map;\n    uint8_t timeleft;\n  };\n  typedef std::vector<Position> PositionList;\n  PositionList activated;\n};\n\n#endif\n"
  },
  {
    "path": "src/blocks/sign.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <math.h>\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"sign.h\"\n#include \"protocol.h\"\n\n\nvoid BlockSign::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockSign::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockSign::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockSign::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, BLOCK_WALL_SIGN);\n\n  //Remove sign data from the chunk\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n  if (chunk != NULL)\n  {\n    for (uint32_t i = 0; i < chunk->signs.size(); i++)\n    {\n      if (chunk->signs[i]->x == x &&\n          chunk->signs[i]->y == y &&\n          chunk->signs[i]->z == z)\n      {\n        chunk->signs.erase(chunk->signs.begin() + i);\n        break;\n      }\n    }\n  }\n  return false;\n}\n\nvoid BlockSign::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  bool blockBroken = false;\n\n  //Ladder is not attached to top or bottom block\n  if (direction == BLOCK_BOTTOM)\n  {\n    return;\n  }\n\n  if (direction == BLOCK_TOP && block == BLOCK_SIGN_POST)\n  {\n    blockBroken = true;\n  }\n  else if (block == BLOCK_WALL_SIGN &&\n           ((meta == 2 && direction == BLOCK_EAST)  ||\n            (meta == 3 && direction == BLOCK_WEST)  ||\n            (meta == 4 && direction == BLOCK_NORTH) ||\n            (meta == 5 && direction == BLOCK_SOUTH)))\n  {\n    blockBroken = true;\n  }\n\n\n  if (blockBroken)\n  {\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    this->spawnBlockItem(x, y, z, map, block, 0);\n\n    //Remove sign data from the chunk\n    sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n    if (chunk != NULL)\n    {\n      for (uint32_t i = 0; i < chunk->signs.size(); i++)\n      {\n        if (chunk->signs[i]->x == x &&\n            chunk->signs[i]->y == y &&\n            chunk->signs[i]->z == z)\n        {\n          chunk->signs.erase(chunk->signs.begin() + i);\n          break;\n        }\n      }\n    }\n  }\n}\n\nbool BlockSign::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  // 0x0 -> West  West  West  West\n  // 0x1 -> West  West  West  North\n  // 0x2 -> West  West  North North\n  // 0x3 -> West  North North North\n  // 0x4 -> North North North North\n  // 0x5 -> North North North East\n  // 0x6 -> North North East  East\n  // 0x7 -> North East  East  East\n  // 0x8 -> East  East  East  East\n  // 0x9 -> East  East  East  South\n  // 0xA -> East  East  South South\n  // 0xB -> East  South South South\n  // 0xC -> South South South South\n  // 0xD -> South South South West\n  // 0xE -> South South West  West\n  // 0xF -> South West  West  West\n\n  //           The values were the signs are facing\n  //\n  //                          North\n  //\n  //      -X |                  4\n  //         |              3       5\n  //         |           2             6\n  //         |         1       [=]       7\n  //  West   |        0         |         8           East\n  //         |         F                 9\n  //         |           E             A\n  //         |              D       B\n  //      +X |                  C\n  //           ----------------------------------\n  //           +Z                              -Z\n  //\n  //                          South\n\n\n  // Were it should be placed depending on the user's position\n  //\n  //                          North\n  //\n  //      -X |                  C\n  //         |              B       D\n  //         |           A      o      E\n  //         |         9       [ ]       F\n  //  West   |        8        | |         0           East\n  //         |         7                 1\n  //         |           6             2\n  //         |              5       3\n  //      +X |                  4\n  //           ----------------------------------\n  //           +Z                              -Z\n  //\n  //                          South\n\n  // We place according to the player's position\n  double diffX = (x + 0.5) - user->pos.x; // + 0.5 to get the middle of the square\n  double diffZ = (z + 0.5) - user->pos.z; // + 0.5 to get the middle of the square\n\n  double angleDegree = ((atan2(diffZ, diffX) * 180 / M_PI + 90) / 22.5);\n\n  uint8_t metadata;\n  if (angleDegree < 0)\n  {\n    angleDegree += 16;\n  }\n  newblock = BLOCK_WALL_SIGN;\n  metadata = 6 - direction;\n  switch (direction)\n  {\n  case BLOCK_SOUTH:\n    x--;\n    break;\n  case BLOCK_NORTH:\n    x++;\n    break;\n  case BLOCK_EAST:\n    z++;\n    break;\n  case BLOCK_WEST:\n    z--;\n    break;\n  case BLOCK_TOP:\n    y++;\n    newblock = BLOCK_SIGN_POST;\n    metadata = (uint8_t)(angleDegree + 0.5);\n    break;\n  case BLOCK_BOTTOM:\n  default:\n    revertBlock(user, x, y, z, map);\n    return true;\n    break;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, metadata);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, metadata);\n\n  user->writePacket(Protocol::openSignEditor(x, y, z));\n  return false;\n}\n\nvoid BlockSign::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockSign::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n"
  },
  {
    "path": "src/blocks/sign.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockSign deals specifically with blocks that are signs and need specific functionality\n@see BlockBasic\n*/\nclass BlockSign: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_WALL_SIGN || block == BLOCK_SIGN_POST || block == ITEM_SIGN; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/snow.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"snow.h\"\n\n\nvoid BlockSnow::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockSnow::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockSnow::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockSnow::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n  this->spawnBlockItem(x, y, z, map, block, meta);\n  return false;\n}\n\nvoid BlockSnow::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return;\n  }\n\n  if (direction == BLOCK_TOP && this->isBlockEmpty(x, y - 1, z, map))\n  {\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    this->spawnBlockItem(x, y, z, map, block, 0);\n  }\n}\n\nbool BlockSnow::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);\n  return false;\n}\n\nvoid BlockSnow::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockSnow::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\n"
  },
  {
    "path": "src/blocks/snow.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockSnow deals specifically with blocks that require snow functionality such as melting, etc.\n@see BlockBasic\n*/\nclass BlockSnow: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_SNOW; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/stair.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"stair.h\"\n\n\nvoid BlockStair::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockStair::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockStair::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockStair::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n\n  this->spawnBlockItem(x, y, z, map, block, 0);\n  return false;\n}\n\nvoid BlockStair::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  /* TODO: add code to align stairs? */\n}\n\nbool BlockStair::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  //*if (!this->translateDirection(&x, &y, &z, map, direction))\n  //{\n  //  revertBlock(user, x, y, z, map);\n  //  return true;\n  //}\n\n  //direction = user->relativeToBlock(x, y, z);*/\n\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  direction = user->relativeToBlock(x, y, z);\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), char(direction));\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), char(direction));\n\n  return false;\n}\n\nvoid BlockStair::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  /* Align neighbour to this stair */\n}\n\nvoid BlockStair::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n"
  },
  {
    "path": "src/blocks/stair.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockStair deals specifically with blocks that are stairs and require different functionality\n@see BlockBasic\n*/\nclass BlockStair: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_WOODEN_STAIRS || block == BLOCK_COBBLESTONE_STAIRS; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/step.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"step.h\"\n\n\nvoid BlockStep::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockStep::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockStep::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockStep::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n\n  this->spawnBlockItem(x, y, z, map, block, meta);\n  return false;\n}\n\nvoid BlockStep::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nbool BlockStep::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  //Combine two steps\n  if (newblock == BLOCK_STEP && oldblock == BLOCK_STEP && direction == BLOCK_TOP)\n  {\n    Item item = user->inv[user->curItem + 36];\n\n    if (item.getHealth() == oldmeta)\n    {\n      ServerInstance->map(map)->setBlock(x, y, z, (char)BLOCK_DOUBLE_STEP, oldmeta);\n      ServerInstance->map(map)->sendBlockChange(x, y, z, (char)BLOCK_DOUBLE_STEP, oldmeta);\n      revertBlock(user, x, y, z, map);\n      return true;\n    }\n    else\n    {\n      revertBlock(user, x, y, z, map);\n      return true;\n    }\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  Item item = user->inv[user->curItem + 36];\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), char(item.getHealth()));\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), char(item.getHealth()));\n  return false;\n}\n\nvoid BlockStep::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockStep::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n"
  },
  {
    "path": "src/blocks/step.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n\nclass BlockStep: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_STEP || block == BLOCK_DOUBLE_STEP; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/tnt.cpp",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"default.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"constants.h\"\n#include \"logger.h\"\n\n#include \"tnt.h\"\n\nuint8_t pickint;\n\nvoid BlockTNT::rb(int32_t x,int16_t y,int32_t z,int map, User* user)\n{\n  uint8_t block, meta, count;\n  int16_t item;\n\n  ServerInstance->map(map)->getBlock(x,y,z,&block,&meta);\n\n  BLOCKDROPS[block]->getDrop(item, count, meta);\n\n  // Undestroyable blocks\n  if (block == BLOCK_AIR || block == BLOCK_BEDROCK || block == BLOCK_OBSIDIAN)\n  {\n    return;\n  }\n  else\n  {\n    record.push_back(vec(x-position.x(), y-position.y(), z-position.z()));\n    ServerInstance->map(map)->setBlock(x,y,z,0,0);\n    //ServerInstance->map(map)->sendBlockChange(x,y,z,0,0);\n  }\n  \n  // Pickup Spawn Area\n  // The integer \"pickint\" is used to spawn 1/5 of the blocks, otherwise there would be too much pickups!\n  if(pickint == 5)\n  {\n    if(count) {\n      ServerInstance->map(map)->createPickupSpawn(x, y, z, item, count, meta, user);\n      pickint=0;\n    }\n  } else {\n    pickint++;\n  }\n\n}\n\nvoid BlockTNT::explode(User* user,int32_t x,int16_t y,int32_t z,int map)\n{\n  pickint = 0;\n  if (rand() % 9 == 5) {\n    // There is a chance of 1/10 that the TNT block does'nt explode;\n    // this is more realistic ;)\n    ServerInstance->map(map)->setBlock(x,y,z,0,0);\n    ServerInstance->map(map)->sendBlockChange(x,y,z,0,0);\n    // But we want to be fair; let's create a pickup for the TNT block =)\n    ServerInstance->map(map)->createPickupSpawn(x,y,z,46,1,0,user);\n  } else {\n    int number; // Counter in the for(...){...} loops.\n    position = vec(x, y, z);\n    record.clear();\n    // Layer Y-4\n  \n    //rb(x,y-4,z,map,user);\n    \n    // Layer Y-3\n    \n    rb(x-1,y-3,z+1,map,user);\n    rb(x,y-3,z+1,map,user);\n    rb(x+1,y-3,z+1,map,user);\n    rb(x-1,y-3,z,map,user);\n    rb(x,y-3,z,map,user);\n    rb(x+1,y-3,z,map,user);\n    rb(x-1,y-3,z-1,map,user);\n    rb(x,y-3,z-1,map,user);\n    rb(x+1,y-3,z-1,map,user);\n  \n    // Layer Y-2\n  \n    for (number=-2; number<=2; number++) {\n      rb(x+number,y-2,z+1,map,user);\n      rb(x+number,y-2,z,map,user);\n      rb(x+number,y-2,z-1,map,user);\n    }\n  \n    rb(x-1,y-2,z+2,map,user);\n    rb(x,y-2,z+2,map,user);\n    rb(x+1,y-2,z+2,map,user);\n  \n    rb(x-1,y-2,z-2,map,user);\n    rb(x,y-2,z-2,map,user);\n    rb(x+1,y-2,z-2,map,user);\n  \n    // Layer Y-1\n  \n    rb(x-3,y-1,z+2,map,user);\n    rb(x-3,y-1,z+1,map,user);\n    rb(x-3,y-1,z,map,user);\n    rb(x-3,y-1,z-1,map,user);\n    rb(x-3,y-1,z-2,map,user);\n  \n    for (number=-2; number<=2; number++) {\n      rb(x-number,y-1,z+3,map,user);\n      rb(x-number,y-1,z+2,map,user);\n      rb(x-number,y-1,z+1,map,user);\n      rb(x-number,y-1,z,map,user);\n      rb(x-number,y-1,z-1,map,user);\n      rb(x-number,y-1,z-2,map,user);\n      rb(x-number,y-1,z-3,map,user);\n    }\n  \n    rb(x+3,y-1,z+2,map,user);\n    rb(x+3,y-1,z+1,map,user);\n    rb(x+3,y-1,z,map,user);\n    rb(x+3,y-1,z-1,map,user);\n    rb(x+3,y-1,z-2,map,user);\n  \n  \n    // Layer Y {+,-} 0, same as TNT block\n  \n    //rb(x-4,y,z,map,user);\n  \n    rb(x-3,y,z+2,map,user);\n    rb(x-3,y,z+1,map,user);\n    rb(x-3,y,z,map,user);\n    rb(x-3,y,z-1,map,user);\n    rb(x-3,y,z-2,map,user);\n  \n    for (number=-2; number<=2; number++) {\n      rb(x-number,y,z+3,map,user);\n      rb(x-number,y,z+2,map,user);\n      rb(x-number,y,z+1,map,user);\n      rb(x-number,y,z,map,user);\n      rb(x-number,y,z-1,map,user);\n      rb(x-number,y,z-2,map,user);\n      rb(x-number,y,z-3,map,user);\n    }\n  \n    rb(x+3,y,z+2,map,user);\n    rb(x+3,y,z+1,map,user);\n    rb(x+3,y,z,map,user);\n    rb(x+3,y,z-1,map,user);\n    rb(x+3,y,z-2,map,user);\n  \n  //rb(x+4,y,z,map,user);\n  \n  //rb(x,y,z+4,map,user);\n  //rb(x,y,z-4,map,user);\n  \n    // Layer Y+1\n  \n    rb(x-3,y+1,z+2,map,user);\n    rb(x-3,y+1,z+1,map,user);\n    rb(x-3,y+1,z,map,user);\n    rb(x-3,y+1,z-1,map,user);\n    rb(x-3,y+1,z-2,map,user);\n  \n    for (number=-2; number<=2; number++) {\n      rb(x-number,y+1,z+3,map,user);\n      rb(x-number,y+1,z+2,map,user);\n      rb(x-number,y+1,z+1,map,user);\n      rb(x-number,y+1,z,map,user);\n      rb(x-number,y+1,z-1,map,user);\n      rb(x-number,y+1,z-2,map,user);\n      rb(x-number,y+1,z-3,map,user);\n    }\n  \n    rb(x+3,y+1,z+2,map,user);\n    rb(x+3,y+1,z+1,map,user);\n    rb(x+3,y+1,z,map,user);\n    rb(x+3,y+1,z-1,map,user);\n    rb(x+3,y+1,z-2,map,user);\n  \n    // Layer Y+2\n  \n    for (number=-2; number<=2; number++) {\n      rb(x+number,y+2,z+1,map,user);\n      rb(x+number,y+2,z,map,user);\n      rb(x+number,y+2,z-1,map,user);\n    }\n  \n    rb(x-1,y+2,z+2,map,user);\n    rb(x,y+2,z+2,map,user);\n    rb(x+1,y+2,z+2,map,user);\n  \n    rb(x-1,y+2,z-2,map,user);\n    rb(x,y+2,z-2,map,user);\n    rb(x+1,y+2,z-2,map,user);\n  \n    // Layer Y+3\n  \n    rb(x-1,y+3,z+1,map,user);\n    rb(x,y+3,z+1,map,user);\n    rb(x+1,y+3,z+1,map,user);\n    rb(x-1,y+3,z,map,user);\n    rb(x,y+3,z,map,user);\n    rb(x+1,y+3,z,map,user);\n    rb(x-1,y+3,z-1,map,user);\n    rb(x,y+3,z-1,map,user);\n    rb(x+1,y+3,z-1,map,user);\n  \n\n    ServerInstance->map(user->pos.map)->sendExplosion(x, y, z, 10.0f, record, 0.0f, 0.0f, 0.0f);\n    // Layer Y+4\n  \n  //rb(x,y+4,z,map,user);\n  \n    LOG2(INFO,\"TNT Block exploded!\");\n  }\n}\n\nbool BlockTNT::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n  \n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return false;\n  }\n  \n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n  \n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n  \n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, 0);\n  \n  return false;\n}\n\nvoid BlockTNT::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  explode(user,x,y,z,map); \n}\n\nbool BlockTNT::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  //uint8_t block, metadata;\n  return true;\n}\n"
  },
  {
    "path": "src/blocks/tnt.h",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\nclass BlockTNT : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_TNT; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n  void rb(int32_t x,int16_t y,int32_t z,int map,User* user); // rb=Remove Block\n  void explode(User* user, int32_t x, int16_t y, int32_t z, int map);\nprivate:\n  std::vector<vec> record;\n  vec position;\n};\n"
  },
  {
    "path": "src/blocks/torch.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"redstoneSimulation.h\"\n#include \"vec.h\"\n\n#include \"torch.h\"\n\n\nvoid BlockTorch::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockTorch::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockTorch::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockTorch::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block, meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n\n  this->spawnBlockItem(x, y, z, map, block, 0);\n\n  if(block == BLOCK_REDSTONE_TORCH_OFF || block == BLOCK_REDSTONE_TORCH_ON)\n  {\n    ServerInstance->redstone(map)->addSimulation(vec(x,y,z));\n  }\n\n  return false;\n}\n\nvoid BlockTorch::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n  bool destroy = false;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return;\n  }\n\n  if (direction == BLOCK_TOP && meta == BLOCK_TOP && this->isBlockEmpty(x, y - 1, z, map))\n  {\n    destroy = true;\n    // Crude fix for weird sign destruction\n    uint8_t tempblock;\n    uint8_t tempmeta;\n    if (ServerInstance->map(map)->getBlock(x, y, z, &tempblock, &tempmeta) && tempblock == BLOCK_WALL_SIGN)\n    {\n      destroy = false;\n    }\n  }\n  else if (direction == BLOCK_NORTH && meta == BLOCK_SOUTH && this->isBlockEmpty(x + 1, y, z, map))\n  {\n    destroy = true;\n  }\n  else if (direction == BLOCK_SOUTH && meta == BLOCK_NORTH && this->isBlockEmpty(x - 1, y, z, map))\n  {\n    destroy = true;\n  }\n  else if (direction == BLOCK_EAST && meta == BLOCK_WEST && this->isBlockEmpty(x, y, z + 1, map))\n  {\n    destroy = true;\n  }\n  else if (direction == BLOCK_WEST && meta == BLOCK_EAST && this->isBlockEmpty(x, y, z - 1, map))\n  {\n    destroy = true;\n  }\n\n  if (destroy)\n  {\n    // Break torch and spawn torch item\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    this->spawnBlockItem(x, y, z, map, block);\n  }\n}\n\nbool BlockTorch::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n  if (direction == 0)\n  {\n    if (ServerInstance->map(map)->getBlock(x+1, y, z, &oldblock, &oldmeta) && oldblock != BLOCK_AIR)\n    {\n      direction = 2;\n    }\n    else if (ServerInstance->map(map)->getBlock(x, y, z+1, &oldblock, &oldmeta) && oldblock != BLOCK_AIR)\n    {\n      direction = 4;\n    }\n    else if (ServerInstance->map(map)->getBlock(x-1, y, z, &oldblock, &oldmeta) && oldblock != BLOCK_AIR)\n    {\n      direction = 1;\n    }\n    else if (ServerInstance->map(map)->getBlock(x, y, z-1, &oldblock, &oldmeta) && oldblock != BLOCK_AIR)\n    {\n      direction = 3;\n    }\n    else\n    {\n      direction = 5;\n    }\n   }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, direction);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, direction);\n\n  if(newblock == BLOCK_REDSTONE_TORCH_OFF || newblock == BLOCK_REDSTONE_TORCH_ON)\n  {\n    ServerInstance->redstone(map)->addSimulation(vec(x,y,z));\n  }\n\n  return false;\n}\n\nvoid BlockTorch::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n}\n\nvoid BlockTorch::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  switch (newblock)\n  {\n  case BLOCK_WATER:\n  case BLOCK_STATIONARY_WATER:\n  {\n    if (ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n    {\n      // spawn item\n      ServerInstance->map(map)->sendBlockChange(x, y, z, 0, 0);\n      ServerInstance->map(map)->setBlock(x, y, z, 0, 0);\n      this->spawnBlockItem(x, y, z, map, oldblock);\n    }\n  }\n  break;\n  case BLOCK_LAVA:\n  case BLOCK_STATIONARY_LAVA:\n  {\n    if (ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n    {\n      // destroy\n      ServerInstance->map(map)->sendBlockChange(x, y, z, 0, 0);\n      ServerInstance->map(map)->setBlock(x, y, z, 0, 0);\n    }\n  }\n  break;\n  default:\n    return;\n    break;\n  }\n}\n\nvoid BlockTorch::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  this->onNeighbourBroken(user, oldblock, x, y, z, map, direction);\n}\n"
  },
  {
    "path": "src/blocks/torch.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockTorch deals specifically with blocks that require torch functionality\n@see BlockBasic\n*/\nclass BlockTorch: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_TORCH || block == BLOCK_REDSTONE_TORCH_OFF || block == BLOCK_REDSTONE_TORCH_ON; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/tracks.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <iostream>\n\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"logger.h\"\n\n#include \"tracks.h\"\n\n\nenum\n{\n  FLAT_NS = 0,\n  FLAT_EW,\n  ASCEND_W,\n  ASCEND_E,\n  ASCEND_S,\n  ASCEND_N,\n  CORNER_SE,\n  CORNER_SW,\n  CORNER_NW,\n  CORNER_NE\n};\n\nvoid BlockTracks::onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockTracks::onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockTracks::onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockTracks::onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n\n  ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n\n  this->spawnBlockItem(x, y, z, map, block, 0);\n  return false;\n}\n\nvoid BlockTracks::onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    return;\n  }\n\n  if (this->isBlockEmpty(x, y - 1, z, map))\n  {\n    // Break torch and spawn torch item\n    ServerInstance->map(map)->sendBlockChange(x, y, z, BLOCK_AIR, 0);\n    ServerInstance->map(map)->setBlock(x, y, z, BLOCK_AIR, 0);\n    this->spawnBlockItem(x, y, z, map, block);\n  }\n}\n\nbool BlockTracks::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &block, &meta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(block))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  uint8_t metadata = FLAT_NS;\n  uint8_t elevoftrack = 2;\n\n  // WEST of placed track\n  if (searchTrack(x + 1, y, z, map, meta) != 2 && isStartPiece(x + 1, y, z, map))\n  {\n    LOG(INFO, \"Tracks\", \"WEST\");\n    metadata = FLAT_EW;\n    elevoftrack = searchTrack(x + 1, y, z, map, meta);\n\n    if (meta == FLAT_NS && elevoftrack == 0)\n    {\n      ServerInstance->map(map)->setBlock(x + 1, y, z, (char)newblock, FLAT_EW);\n      ServerInstance->map(map)->sendBlockChange(x + 1, y, z, (char)newblock, FLAT_EW);\n    }\n\n    // Rising & falling tracks\n    if (isTrack(x + 1, y + 1, z, map, meta) && isStartPiece(x + 1, y + 1, z, map)) // Rising & falling tracks\n    {\n      metadata = ASCEND_W;\n    }\n    else if (isTrack(x + 1, y - 1, z, map, meta) && isStartPiece(x + 1, y - 1, z, map)) // Rising & falling tracks\n    {\n      ServerInstance->map(map)->setBlock(x + 1, y - 1, z, (char)newblock, ASCEND_E);\n      ServerInstance->map(map)->sendBlockChange(x + 1, y - 1, z, (char)newblock, ASCEND_E);\n    }\n\n    // Change previous track, Turns\n    if (searchTrack(x + 1, y, z - 1, map, meta) != 2 && isStartPiece(x + 1, y, z, map) && meta != FLAT_EW) // Left\n    {\n      ServerInstance->map(map)->setBlock(x + 1, y + elevoftrack, z, (char)newblock, CORNER_NW);\n      ServerInstance->map(map)->sendBlockChange(x + 1, y + elevoftrack, z, (char)newblock, CORNER_NW);\n    }\n    if (searchTrack(x + 1, y, z + 1, map, meta) != 2 && isStartPiece(x + 1, y, z, map) && meta != FLAT_EW) // Right\n    {\n      ServerInstance->map(map)->setBlock(x + 1, y + elevoftrack, z, (char)newblock, CORNER_SW);\n      ServerInstance->map(map)->sendBlockChange(x + 1, y + elevoftrack, z, (char)newblock, CORNER_SW);\n    }\n\n    // Make track you just placed a corner\n    if (isTrack(x, y, z - 1, map, meta) && isStartPiece(x, y, z - 1, map))\n    {\n      metadata = CORNER_NE;\n    }\n    if (isTrack(x, y, z + 1, map, meta) && isStartPiece(x, y, z + 1, map))\n    {\n      metadata = CORNER_SE;\n    }\n  }\n\n  // EAST of placed track\n  else if (searchTrack(x - 1, y, z, map, meta) != 2 && isStartPiece(x - 1, y, z, map))\n  {\n    LOG(INFO, \"Tracks\", \"EAST\");\n    metadata = FLAT_EW;\n    elevoftrack = searchTrack(x - 1, y, z, map, meta);\n\n\n    if (meta == FLAT_NS && elevoftrack == 0)\n    {\n      ServerInstance->map(map)->setBlock(x - 1, y, z, (char)newblock, FLAT_EW);\n      ServerInstance->map(map)->sendBlockChange(x - 1, y, z, (char)newblock, FLAT_EW);\n    }\n\n    // Rising & falling tracks\n    if (isTrack(x - 1, y + 1, z, map, meta) && isStartPiece(x - 1, y + 1, z, map))\n    {\n      metadata = ASCEND_E;\n      if (meta != ASCEND_E || meta != CORNER_NW || meta != CORNER_SW)\n      {\n        ServerInstance->map(map)->setBlock(x - 1, y + 1, z, (char)newblock, FLAT_EW);\n        ServerInstance->map(map)->sendBlockChange(x - 1, y + 1, z, (char)newblock, FLAT_EW);\n      }\n    }\n    else if (isTrack(x - 1, y - 1, z, map, meta) && isStartPiece(x - 1, y - 1, z, map))\n    {\n      ServerInstance->map(map)->setBlock(x - 1, y - 1, z, (char)newblock, ASCEND_W);\n      ServerInstance->map(map)->sendBlockChange(x - 1, y - 1, z, (char)newblock, ASCEND_W);\n    }\n\n    // Change previous track, Turns\n    if (searchTrack(x - 1, y, z - 1, map, meta) != 2 && isStartPiece(x - 1, y, z, map) && meta != FLAT_EW) // Right\n    {\n      ServerInstance->map(map)->setBlock(x - 1, y + elevoftrack, z, (char)newblock, CORNER_NE);\n      ServerInstance->map(map)->sendBlockChange(x - 1, y + elevoftrack, z, (char)newblock, CORNER_NE);\n    }\n    if (searchTrack(x - 1, y, z + 1, map, meta) != 2 && isStartPiece(x - 1, y, z, map) && meta != FLAT_EW) // Left\n    {\n      ServerInstance->map(map)->setBlock(x - 1, y + elevoftrack, z, (char)newblock, CORNER_SE);\n      ServerInstance->map(map)->sendBlockChange(x - 1, y + elevoftrack, z, (char)newblock, CORNER_SE);\n    }\n\n    // Make track you just placed a corner\n    if (isTrack(x, y, z - 1, map, meta) && isStartPiece(x, y, z - 1, map))\n    {\n      metadata = CORNER_NW;\n    }\n    if (isTrack(x, y, z + 1, map, meta) && isStartPiece(x, y, z + 1, map))\n    {\n      metadata = CORNER_SW;\n    }\n\n  }\n\n  // SOUTH of placed track\n  else if (searchTrack(x, y, z - 1, map, meta) != 2 && isStartPiece(x, y, z - 1, map))\n  {\n    LOG(INFO, \"Tracks\", \"SOUTH\");\n    metadata = FLAT_NS;\n    elevoftrack = searchTrack(x, y, z - 1, map, meta); // Elevation of found track\n\n    if (meta == FLAT_EW && elevoftrack == 0)\n    {\n      ServerInstance->map(map)->setBlock(x, y, z - 1, (char)newblock, FLAT_NS);\n      ServerInstance->map(map)->sendBlockChange(x, y, z - 1, (char)newblock, FLAT_NS);\n    }\n\n    // Rising & falling tracks\n    if (isTrack(x, y + 1, z - 1, map, meta) && isStartPiece(x, y + 1, z - 1, map)) // Rising & falling tracks\n    {\n      metadata = ASCEND_S;\n    }\n    else if (isTrack(x, y - 1, z - 1, map, meta) && isStartPiece(x, y - 1, z - 1, map)) // Rising & falling tracks\n    {\n      ServerInstance->map(map)->setBlock(x, y - 1, z - 1, (char)newblock, ASCEND_N);\n      ServerInstance->map(map)->sendBlockChange(x, y - 1, z - 1, (char)newblock, ASCEND_N);\n    }\n\n    // Change previous track, Turns\n    if (searchTrack(x - 1, y, z - 1, map, meta) != 2 && isStartPiece(x, y, z - 1, map) && meta != FLAT_NS) // Left\n    {\n      ServerInstance->map(map)->setBlock(x, y + elevoftrack, z - 1, (char)newblock, CORNER_SW);\n      ServerInstance->map(map)->sendBlockChange(x, y + elevoftrack, z - 1, (char)newblock, CORNER_SW);\n    }\n    if (searchTrack(x + 1, y, z - 1, map, meta) != 2 && isStartPiece(x, y, z - 1, map) && meta != FLAT_NS) // Right\n    {\n      ServerInstance->map(map)->setBlock(x, y + elevoftrack, z - 1, (char)newblock, CORNER_SE);\n      ServerInstance->map(map)->sendBlockChange(x, y + elevoftrack, z - 1, (char)newblock, CORNER_SE);\n    }\n\n    // Make track you just placed a corner\n    if (isTrack(x + 1, y, z, map, meta) && isStartPiece(x + 1, y, z, map))\n    {\n      metadata = CORNER_NE;\n    }\n    if (isTrack(x - 1, y, z, map, meta) && isStartPiece(x - 1, y, z, map))\n    {\n      metadata = CORNER_NW;\n    }\n  }\n\n  // NORTH of placed track\n  else if (searchTrack(x, y, z + 1, map, meta) != 2 && isStartPiece(x, y, z + 1, map))\n  {\n    LOG(INFO, \"Tracks\", \"NORTH\");\n    metadata = FLAT_NS;\n    elevoftrack = searchTrack(x, y, z + 1, map, meta);\n\n\n    if (meta == FLAT_EW && elevoftrack == 0)\n    {\n      ServerInstance->map(map)->setBlock(x, y, z + 1, (char)newblock, FLAT_NS);\n      ServerInstance->map(map)->sendBlockChange(x, y, z + 1, (char)newblock, FLAT_NS);\n    }\n\n    // Rising & falling tracks\n    if (isTrack(x, y - 1, z + 1, map, meta) && isStartPiece(x, y - 1, z + 1, map)) // Rising & falling tracks\n    {\n      ServerInstance->map(map)->setBlock(x, y - 1, z + 1, (char)newblock, ASCEND_S);\n      ServerInstance->map(map)->sendBlockChange(x, y - 1, z + 1, (char)newblock, ASCEND_S);\n    }\n    else if (isTrack(x, y + 1, z + 1, map, meta) && isStartPiece(x, y + 1, z + 1, map)) // Rising & falling tracks\n    {\n      metadata = ASCEND_N;\n    }\n\n    // Change previous track, Turns\n    if (searchTrack(x + 1, y, z + 1, map, meta) != 2 && isStartPiece(x, y, z + 1, map) && meta != FLAT_NS) // Left\n    {\n      ServerInstance->map(map)->setBlock(x, y + elevoftrack, z + 1, (char)newblock, CORNER_NE);\n      ServerInstance->map(map)->sendBlockChange(x, y + elevoftrack, z + 1, (char)newblock, CORNER_NE);\n    }\n    if (searchTrack(x - 1, y, z + 1, map, meta) != 2 && isStartPiece(x, y, z + 1, map)  && meta != FLAT_NS) // Right\n    {\n      ServerInstance->map(map)->setBlock(x, y + elevoftrack, z + 1, (char)newblock, CORNER_NW);\n      ServerInstance->map(map)->sendBlockChange(x, y + elevoftrack, z + 1, (char)newblock, CORNER_NW);\n    }\n\n    // Make track you just placed a corner\n    if (isTrack(x + 1, y, z, map, meta) && isStartPiece(x + 1, y, z, map))\n    {\n      metadata = CORNER_SE;\n    }\n    if (isTrack(x - 1, y, z, map, meta) && isStartPiece(x - 1, y, z, map))\n    {\n      metadata = CORNER_SW;\n    }\n\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, metadata);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, metadata);\n  return false;\n}\n\nvoid BlockTracks::onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockTracks::onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nvoid BlockTracks::onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n\n}\n\nbool BlockTracks::isTrack(int32_t x, int16_t y, int32_t z, int map, uint8_t& meta)\n{\n  uint8_t block;\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n  return (block == BLOCK_MINECART_TRACKS);\n}\n\nbool BlockTracks::isStartPiece(int32_t x, int16_t y, int32_t z, int map)\n{\n  uint8_t block;\n  uint8_t meta;\n  int32_t x1, x2, z1, z2;\n  x1 = x2 = x;\n  z1 = z2 = z;\n\n  int16_t y1, y2;\n  y1 = y2 = y;\n\n  ServerInstance->map(map)->getBlock(x, y, z, &block, &meta);\n  switch (meta)\n  {\n  case FLAT_EW:\n  {\n    x1--;\n    x2++;\n  }\n  break;\n  case FLAT_NS:\n  {\n    z1--;\n    z2++;\n  }\n  break;\n  case CORNER_SE:\n  {\n    x1++;\n    z2++;\n  }\n  break;\n  case CORNER_SW:\n  {\n    z1++;\n    x2--;\n  }\n  break;\n  case CORNER_NE:\n  {\n    x1++;\n    z2--;\n  }\n  break;\n  case CORNER_NW:\n  {\n    x1--;\n    z2--;\n  }\n  break;\n  case ASCEND_E:\n  {\n    y1++;\n    x1--;\n    x2++;\n  }\n  break;\n  case ASCEND_N:\n  {\n    y1++;\n    z1++;\n    z2--;\n  }\n  break;\n  case ASCEND_S:\n  {\n    y1++;\n    z1--;\n    z2++;\n  }\n  break;\n  case ASCEND_W:\n  {\n    y1++;\n    x1++;\n    x2--;\n  }\n  break;\n  }\n\n  if ((ServerInstance->map(map)->getBlock(x1, y1, z1, &block, &meta) && block != BLOCK_MINECART_TRACKS) ||\n      (ServerInstance->map(map)->getBlock(x2, y2, z2, &block, &meta) && block != BLOCK_MINECART_TRACKS))\n  {\n    return true;\n  }\n  else\n  {\n    return false;\n  }\n}\n\nint BlockTracks::searchTrack(int32_t x, int16_t y, int32_t z, int map, uint8_t& meta)\n{\n  if (isTrack(x, y + 1, z, map, meta))\n  {\n    return 1;\n  }\n  else if (isTrack(x, y - 1, z, map, meta))\n  {\n    return -1;\n  }\n  else if (isTrack(x, y, z, map, meta))\n  {\n    return 0;\n  }\n\n  return 2;\n}\n"
  },
  {
    "path": "src/blocks/tracks.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\nstruct TrackData\n{\n  uint32_t x;\n  uint16_t y;\n  uint32_t z;\n};\n\n/** BlockTracks deals specifically with minecart tracks\n@see BlockBasic\n*/\nclass BlockTracks: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_MINECART_TRACKS; }\n\n  void onStartedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onStoppedDigging(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onBroken(User* user, int8_t status, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourBroken(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onReplace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\n  void onNeighbourMove(User* user, int16_t oldblock, int32_t x, int16_t y, int32_t z, int map,  int8_t direction);\nprivate:\n  TrackData trackLog[2];\n  bool isTrack(int32_t x, int16_t y, int32_t z, int map,  uint8_t& meta);\n  bool isStartPiece(int32_t x, int16_t y, int32_t z, int map);\n  int searchTrack(int32_t x, int16_t y, int32_t z, int map, uint8_t& meta);\n};\n"
  },
  {
    "path": "src/blocks/wood.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"wood.h\"\n\n\nbool BlockWood::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  Item item = user->inv[user->curItem + 36];\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), char(item.getHealth()));\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), char(item.getHealth()));\n  return false;\n}\n\nbool BlockWood::spawnBlockItem(const int32_t x, const int16_t y, const int32_t z, int map, const uint8_t block, const uint8_t meta)\n{\n  DropPtr drop;\n  int16_t item; uint8_t count, item_meta;\n  if (block == BLOCK_LOG)\n  {\n    item_meta = meta&3;\n  }\n  else if (block == BLOCK_LOG2)\n  {\n    item_meta = meta&1;\n  }\n  BLOCKDROPS[block]->getDrop(item, count, item_meta);\n  if (count)\n  {\n    ServerInstance->map(map)->createPickupSpawn(x, y, z, item, count, item_meta, NULL);\n    return true;\n  }\n  return false;\n}"
  },
  {
    "path": "src/blocks/wood.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\nclass User;\n\n/** The BlockDefault type comprises of the functionality seen in most of the\nblocktypes in the game. These functions are reused and mixed with multiple\ndifferent blocks. */\n\nclass BlockWood: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_LOG || block == BLOCK_LOG2; }\n  bool spawnBlockItem(const int32_t x, const int16_t y, const int32_t z, const int map, const uint8_t block, uint8_t meta = 0);\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/wool.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"wool.h\"\n\nbool BlockWool::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  Item item = user->inv[user->curItem + 36];\n\n  ServerInstance->map(map)->setBlock(x, y, z, char(newblock), char(item.getHealth()));\n  ServerInstance->map(map)->sendBlockChange(x, y, z, char(newblock), char(item.getHealth()));\n  return false;\n}\n"
  },
  {
    "path": "src/blocks/wool.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\nclass User;\n\n/** The BlockDefault type comprises of the functionality seen in most of the\nblocktypes in the game. These functions are reused and mixed with multiple\ndifferent blocks. */\n\nclass BlockWool: public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_WOOL; }\n\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n};\n\n"
  },
  {
    "path": "src/blocks/workbench.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"mineserver.h\"\n#include \"map.h\"\n\n#include \"workbench.h\"\n\n\nbool BlockWorkbench::onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction)\n{\n  uint8_t oldblock;\n  uint8_t oldmeta;\n\n  if (!ServerInstance->map(map)->getBlock(x, y, z, &oldblock, &oldmeta))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* Check block below allows blocks placed on top */\n  if (!this->isBlockStackable(oldblock))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  /* move the x,y,z coords dependent upon placement direction */\n  if (!this->translateDirection(&x, &y, &z, map, direction))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (this->isUserOnBlock(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  if (!this->isBlockEmpty(x, y, z, map))\n  {\n    revertBlock(user, x, y, z, map);\n    return true;\n  }\n\n  ServerInstance->map(map)->setBlock(x, y, z, (char)newblock, 0);\n  ServerInstance->map(map)->sendBlockChange(x, y, z, (char)newblock, 0);\n  return false;\n}\n\nbool BlockWorkbench::onInteract(User* user, int32_t x, int16_t y, int32_t z, int map)\n{\n  ServerInstance->inventory()->windowOpen(user, WINDOW_CRAFTING_TABLE, x, y, z);\n  return true;\n}\n"
  },
  {
    "path": "src/blocks/workbench.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include \"basic.h\"\n\nclass User;\n\n/** BlockWorkbench deals specifically with Workbench interaction.\nIt does not handle crafting, only right click interaction.\n@see BlockBasic\n*/\n\nclass BlockWorkbench : public BlockBasic\n{\npublic:\n  inline bool affectedBlock(int block) const { return block == BLOCK_WORKBENCH; }\n\n  bool onPlace(User* user, int16_t newblock, int32_t x, int16_t y, int32_t z, int map, int8_t direction);\n  bool onInteract(User* user, int32_t x, int16_t y, int32_t z, int map);\n};\n"
  },
  {
    "path": "src/chat.cpp",
    "content": "/*\n  Copyright (c) 2013, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <ctime>\n#include <iostream>\n#include <fstream>\n\n#include \"constants.h\"\n#include \"config.h\"\n#include \"user.h\"\n#include \"logger.h\"\n#include \"mineserver.h\"\n#include \"permissions.h\"\n#include \"tools.h\"\n#include \"plugin.h\"\n#include \"utf8.h\"\n\n#include \"chat.h\"\n\n#include \"protocol.h\"\n\nChat::Chat()\n{\n}\n\nChat::~Chat()\n{\n}\n\nbool Chat::sendUserlist(User* user)\n{\n  sendMsg(user, MC_COLOR_BLUE + \"[ \" + dtos(User::all().size()) + \" / \" + dtos(ServerInstance->config()->iData(\"system.user_limit\")) + \" players online ]\", USER);\n  std::string playerDesc;\n\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if (!(*it)->logged)\n    {\n      continue;\n    }\n    playerDesc += (*it)->nick;\n    if ((*it)->muted)\n    {\n      playerDesc += MC_COLOR_YELLOW + \" (muted)\";\n    }\n    if ((*it)->dnd)\n    {\n      playerDesc += MC_COLOR_YELLOW + \" (dnd)\";\n    }\n    playerDesc += \", \";\n  }\n  sendMsg(user, playerDesc, USER);\n\n  return true;\n}\n\nstd::deque<std::string> Chat::parseCmd(std::string cmd)\n{\n  int del;\n  std::deque<std::string> temp;\n\n  while (cmd.length() > 0)\n  {\n    while (cmd[0] == ' ')\n    {\n      cmd = cmd.substr(1);\n    }\n\n    del = cmd.find(' ');\n\n    if (del > -1)\n    {\n      temp.push_back(cmd.substr(0, del));\n      cmd = cmd.substr(del + 1);\n    }\n    else\n    {\n      temp.push_back(cmd);\n      break;\n    }\n  }\n\n  if (temp.empty())\n  {\n    temp.push_back(\"empty\");\n  }\n\n  return temp;\n}\n\nbool Chat::handleMsg(User* user, std::string msg)\n{\n  if (msg.empty()) // If the message is empty handle it as if there is no message.\n  {\n    return true;\n  }\n\n  // Timestamp\n  time_t rawTime = time(NULL);\n  struct tm* Tm  = localtime(&rawTime);\n  std::string timeStamp(asctime(Tm));\n  timeStamp = timeStamp.substr(11, 5);\n\n  runCallbackUntilFalse(\"PlayerChatPre\",user->nick.c_str(), rawTime, msg.c_str());\n  if (callbackReturnValue)\n  {\n    return false;\n  }\n  runAllCallback(\"PlayerChatPost\",user->nick.c_str(), rawTime, msg.c_str());\n  char prefix = msg[0];\n\n  switch (prefix)\n  {\n    // Servermsg (Admin-only)\n  case SERVERMSGPREFIX:\n    if (IS_ADMIN(user->permissions))\n    {\n      handleServerMsg(user, msg, timeStamp);\n    }\n    break;\n\n    // Admin message\n  case ADMINCHATPREFIX:\n    if (IS_ADMIN(user->permissions))\n    {\n      handleAdminChatMsg(user, msg, timeStamp);\n    }\n    break;\n\n  case CHATCMDPREFIX:\n    handleCommand(user, msg, timeStamp);\n    break;\n    // Normal chat message\n  default:\n    handleChatMsg(user, msg, timeStamp);\n    break;\n  }\n\n  return true;\n}\n\nvoid Chat::handleCommand(User* user, std::string msg, const std::string& timeStamp)\n{\n  std::deque<std::string> cmd = parseCmd(msg.substr(1));\n\n  if (!cmd.size() || !cmd[0].size())\n  {\n    return;\n  }\n\n  std::string command = cmd[0];\n  cmd.pop_front();\n\n  //Converting to char* array for plugins\n  char** param = new char *[cmd.size()];\n  for (uint32_t i = 0; i < cmd.size(); i++)\n  {\n    param[i] = (char*)cmd[i].c_str();\n  }\n\n  // If hardcoded auth command, ignore default password \"CHANGEME\"\n  if (command == \"auth\" && cmd[0] != \"CHANGEME\" && cmd[0] == ServerInstance->config()->sData(\"system.admin.password\"))\n  {\n    user->serverAdmin = true;\n    SET_ADMIN(user->permissions);\n    msg = MC_COLOR_RED + \"[!] \" + MC_COLOR_GREEN + \"You have been authed as admin!\";\n    sendMsg(user, msg, USER);\n  }\n  else\n  {\n    runAllCallback(\"PlayerChatCommand\",user->nick.c_str(), command.c_str(), cmd.size(), (const char**)param);\n  }\n\n  delete [] param;\n\n}\n\n\nvoid Chat::handleServerMsg(User* user, std::string msg, const std::string& timeStamp)\n{\n  // Decorate server message\n  LOG2(INFO, \"[!] \" + msg.substr(1));\n  msg = MC_COLOR_RED + \"[!] \" + MC_COLOR_GREEN + msg.substr(1);\n  this->sendMsg(user, msg, ALL);\n}\n\nvoid Chat::handleAdminChatMsg(User* user, std::string msg, const std::string& timeStamp)\n{\n  LOG2(INFO, \"[@] <\" + user->nick + \"> \" + msg.substr(1));\n  msg = timeStamp +  MC_COLOR_RED + \" [@]\" + MC_COLOR_WHITE + \" <\" + MC_COLOR_DARK_MAGENTA + user->nick + MC_COLOR_WHITE + \"> \" + msg.substr(1);\n  this->sendMsg(user, msg, ADMINS);\n}\n\nvoid Chat::handleChatMsg(User* user, std::string msg, const std::string& timeStamp)\n{\n  if (user->isAbleToCommunicate(\"chat\") == false)\n  {\n    return;\n  }\n\n  // Check for Admins or Server Console\n  if (user->UID == SERVER_CONSOLE_UID)\n  {\n    LOG2(INFO, user->nick + \" \" + msg);\n    msg = timeStamp + \" \" + MC_COLOR_RED + user->nick + MC_COLOR_WHITE + \" \" + msg;\n  }\n  else if (IS_ADMIN(user->permissions))\n  {\n    LOG2(INFO, \"<\" + user->nick + \"> \" + msg);\n    msg = timeStamp + \" <\" + MC_COLOR_DARK_MAGENTA + user->nick + MC_COLOR_WHITE + \"> \" + msg;\n  }\n  else\n  {\n    LOG2(INFO, \"<\" + user->nick + \"> \" + msg);\n    msg = timeStamp + \" <\" + user->nick + \"> \" + msg;\n  }\n\n  this->sendMsg(user, msg, ALL);\n}\n\nbool Chat::sendMsg(User* user, std::string msg, MessageTarget action)\n{\n  Packet pkt = Protocol::chatMsg(\"{\\\"text\\\": \\\"\"+json_esc(msg)+\"\\\"}\");\n\n  switch (action)\n  {\n  case ALL:\n    user->sendAll(pkt);\n    break;\n\n  case USER:\n    user->writePacket(pkt);\n    break;\n\n  case ADMINS:\n    user->sendAdmins(pkt);\n    break;\n\n  case OPS:\n    user->sendOps(pkt);\n    break;\n\n  case GUESTS:\n    user->sendGuests(pkt);\n    break;\n\n  case OTHERS:\n    user->sendOthers(pkt);\n    break;\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "src/chat.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _CHAT_H\n#define _CHAT_H\n\n#include <deque>\n#include <string>\n\nclass User;\n\nclass Chat\n{\npublic:\n  enum MessageTarget\n  {\n    ALL,\n    USER,\n    OTHERS,\n    ADMINS,\n    OPS,\n    GUESTS\n  };\n\n  Chat();\n  ~Chat();\n\n  bool handleMsg(User* user, std::string msg);\n  void handleServerMsg(User* user, std::string msg, const std::string& timeStamp);\n  void handleAdminChatMsg(User* user, std::string msg, const std::string& timeStamp);\n  void handleChatMsg(User* user, std::string msg, const std::string& timeStamp);\n\n  bool sendMsg(User* user, std::string msg, MessageTarget action = ALL);\n  bool sendUserlist(User* user);\n  void sendHelp(User* user, std::deque<std::string> args);\n\n  void handleCommand(User* user, std::string msg, const std::string& timeStamp);\n\nprivate:\n  std::deque<std::string> parseCmd(std::string cmd);\n  std::string adminPassword;\n};\n\n#endif\n"
  },
  {
    "path": "src/chunkmap.h",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _CHUNKMAP_H\n#define _CHUNKMAP_H\n\n#include <set>\n#include <list>\n#include <vector>\n#include <ctime>\n\n#include <memory>\n#include <unordered_map>\n\n#include \"packets.h\"\n#include \"user.h\"\n#include \"nbt.h\"\n\nclass NBT_Value;\n\nstruct spawnedItem\n{\n  int EID;\n  int16_t item;\n  char count;\n  int16_t health;\n  vec pos;\n  time_t spawnedAt;\n  uint32_t spawnedBy;\n\n  spawnedItem() : spawnedAt(std::time(NULL)), spawnedBy(0)\n  {\n  }\n};\n\nclass chestData;\ntypedef std::shared_ptr<std::vector<ItemPtr> > ItemVectorPtr;\ntypedef std::shared_ptr<chestData>   chestDataPtr;\n\n/** holds items and coordinates for small and large chests\n * note: large chests are in testing\n */\nclass chestData\n{\npublic:\n  int32_t x() { return m_x; }\n  void x(int32_t newx) { m_x = newx; }\n  int32_t y() { return m_y; }\n  void y(int32_t newy) { m_y = newy; }\n  int32_t z() { return m_z; }\n  void z(int32_t newz) { m_z = newz; }\n\n  bool isConnectionChecked() { return connection_checked; };\n  void setConnectionCheck() { connection_checked = true; };\n  bool getTop() { return connected_top; };\n\n  vec getConnectedLoc() { return connected_loc; };\n  chestDataPtr getConnectedData() { return connected_chest; };\n\n  // Connect two chests together\n  void connect(vec loc, chestDataPtr& chest, bool top) {    \n    if(connected_chest.get() != nullptr) return;\n\n    connected_top = top;\n    connected_chest = chest;\n    connected_loc = loc;  \n    connection_checked = true;\n  }\n  void clearConnection() { connected_chest.reset(); connected_loc = vec(0,0,0); }\n\n  bool large() { return connected_chest.get() != nullptr; }\n  \n\n  chestData():      \n      connection_checked(false)\n  {\n    this->items(ItemVectorPtr(new std::vector<ItemPtr>()));\n    while(items()->size() < 27)\n      items()->push_back(ItemPtr(new Item));\n  }\n\n  ~chestData()\n  { }\n\n  size_t size()\n  {\n    return items()->size();\n  }\n\n  ItemVectorPtr items() { return m_items; }\n  void items(ItemVectorPtr itemVectorPtr)\n  {\n    m_items = itemVectorPtr;\n  }\n\n\nprivate:\n  int32_t m_x;\n  int32_t m_y;\n  int32_t m_z;\n  vec connected_loc;\n  chestDataPtr connected_chest;\n  bool connected_top; // Is this the \"top part\" inventory\n  bool connection_checked;\n  ItemVectorPtr m_items; /// pointer makes sharing between two connected chest blocks easier\n};\n\nstruct signData\n{\n  int32_t x;\n  int32_t y;\n  int32_t z;\n  std::string text1;\n  std::string text2;\n  std::string text3;\n  std::string text4;\n};\n\nstruct furnaceData\n{\n  int32_t x;\n  int32_t y;\n  int32_t z;\n  Item items[3];\n  int16_t burnTime;\n  int16_t cookTime;\n  int32_t map;\n};\n\n// The following predicate allows for finding *Data members based on their coordinates.\ntemplate <typename T>\nstruct DataFinder\n{\n  DataFinder(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z) { }\n  inline bool operator()(const std::shared_ptr<T> & t) const { return t->x == x && t->y == y && t->z == z; }\nprivate:\n  int32_t x;\n  int32_t y;\n  int32_t z;\n};\n\ntypedef std::shared_ptr<signData>    signDataPtr;\ntypedef std::shared_ptr<furnaceData> furnaceDataPtr;\n\nvoid removeFurnace(furnaceDataPtr data);\n\n/** holds chunk data (0..15 16x16x16 blocks)\n */\nstruct sChunk\n{\n  uint8_t blocks[16 * 16 * 256];\n  uint8_t addblocks[16 * 16 * 256 / 2];\n  uint8_t data[16 * 16 * 256 / 2];\n  uint8_t blocklight[16 * 16 * 256 / 2];\n  uint8_t skylight[16 * 16 * 256 / 2];\n  //int32_t heightmap[16*16];\n  uint8_t biome[16*16];\n\n  //Basic block data (8bits/block)\n  //uint8_t* blocks;\n  //Additional block id data for id > 255 (4bits/block)\n  //uint8_t* addblocks;\n  //Metadata (4bits/block)\n  //uint8_t* data;\n  //block light data (4bits/block)\n  //uint8_t* blocklight;\n  //skylight data (4bits/block)\n  //uint8_t* skylight;\n  //16x16 heightmap\n  int32_t* heightmap;\n  //16x16 biome array\n  //uint8_t* biome;\n\n  //Chunk coordinates\n  int32_t x;\n  int32_t z;\n\n  //Bitmap of the present 16x16x16 chunks, 0xffff would mean 0..15 chunks are present\n  uint16_t chunks_present;\n\n  uint16_t addblocks_present;\n\n  int refCount;\n  bool lightRegen;\n  bool changed;\n  time_t lastused;\n\n  NBT_Value* nbt;\n\n  std::set<User*>           users;\n  std::vector<spawnedItem*> items;\n\n  std::vector<chestDataPtr>   chests;\n  std::vector<signDataPtr>    signs;\n  std::vector<furnaceDataPtr> furnaces;\n\n  sChunk() :// blocks(NULL), addblocks(NULL), data(NULL), blocklight(NULL), skylight(NULL),\n    chunks_present(0), addblocks_present(0), refCount(0), lightRegen(false), changed(false), lastused(0), nbt(NULL)\n  {\n  }\n\n  ~sChunk()\n  {\n    if (!furnaces.empty())\n    {\n      for (std::vector<furnaceDataPtr>::iterator furnace_it = furnaces.begin(); furnace_it != furnaces.end(); ++furnace_it)\n      {\n        removeFurnace(*furnace_it);\n      }\n      furnaces.clear();\n    }\n\n    delete nbt;\n    /*\n    delete[] blocks;\n    delete[] addblocks;\n    delete[] data;\n    delete[] blocklight;\n    delete[] skylight;*/\n  }\n\n  bool hasUser(User* user) const\n  {\n    return users.count(user) != 0;\n  }\n\n  void sendPacket(const Packet& packet, User* nosend = NULL)\n  {\n    for (std::set<User*>::iterator it = users.begin(); it != users.end(); ++it)\n    {\n      if ((*it) != nosend && (*it)->logged)\n      {\n        (*it)->writePacket(packet);\n      }\n    }\n  }\n\n  static bool userBoundary(sChunk* left, std::list<User*>& lusers, sChunk* right, std::list<User*>& rusers)\n  {\n    bool diff = false;\n\n    for (std::set<User*>::const_iterator it = left->users.begin(); it != left->users.end(); ++it)\n    {\n      if (right->users.count(*it) == 0)\n      {\n        lusers.push_front(*it);\n        diff = true;\n      }\n    }\n\n    for (std::set<User*>::const_iterator it = right->users.begin(); it != right->users.end(); ++it)\n    {\n      if (left->users.count(*it) == 0)\n      {\n        rusers.push_front(*it);\n        diff = true;\n      }\n    }\n\n    return diff;\n  }\n};\n\n/*  STL does not yet come with a hash_combine(), so I'm lifting this\n *  implementation from boost. It creates a hash function for every\n *  pair of hashable types. For further generalizations, see boost/functional/hash.\n */\n\ntemplate <class T>\ninline void hash_combine(std::size_t & seed, T const & v)\n{\n  std::hash<T> hasher;\n  seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);\n}\n\ntemplate<typename S, typename T>\nstruct PairHash : public std::unary_function<std::pair<S, T>, size_t>\n{\n  inline size_t operator()(const std::pair<S, T> & v) const\n  {\n    std::size_t seed = 0;\n    hash_combine(seed, v.first);\n    hash_combine(seed, v.second);\n    return seed;\n  }\n};\n\ntypedef std::pair<int, int> Coords;\ntypedef std::unordered_map<Coords, sChunk*, PairHash<int, int> > ChunkMap;\n\n\n#endif\n"
  },
  {
    "path": "src/cliScreen.cpp",
    "content": "/*\n   Copyright (c) 2011, Kasper F. Brandt\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"cliScreen.h\"\n\n#include <iostream>\n#include <sstream>\n\n#include <cstdio>\n\n#ifndef _WIN32\n#include <poll.h>\n#include <unistd.h>\n#endif\n\n#include \"chat.h\"\n#include \"constants.h\"\n#include \"mineserver.h\"\n#include \"plugin.h\"\n\n#ifdef WIN32\nDWORD WINAPI CliScreen::_stdinThreadProc(LPVOID lpParameter)\n{\n  return ((CliScreen*)lpParameter)->stdinThreadProc();\n}\n\nDWORD WINAPI CliScreen::stdinThreadProc()\n{\n  while (true)\n  {\n    std::string s;\n    std::getline(std::cin, s);\n\n    if (std::cin.rdstate() != std::ios::goodbit)\n    {\n      EnterCriticalSection(&ccAccess);\n      currentCommand.clear();\n      LeaveCriticalSection(&ccAccess);\n      return -1;\n    }\n\n    EnterCriticalSection(&ccAccess);\n    currentCommand += s + \"\\n\";\n    _hasCommand = true;\n    LeaveCriticalSection(&ccAccess);\n  }\n}\n#endif\n\nvoid CliScreen::init(std::string version)\n{\n#ifdef WIN32\n  _hasCommand = false;\n  InitializeCriticalSection(&ccAccess);\n  stdinThread = CreateThread(NULL, 0, _stdinThreadProc, (void*)this, 0, NULL);\n#endif\n\n  addCallback(\"LogPost\",(funcPointer)&CliScreen::LogEvent);\n  addCallback(\"Timer200\",(funcPointer)&CliScreen::CheckForCommand);\n}\n\nvoid CliScreen::end()\n{\n#ifdef WIN32\n  TerminateThread(stdinThread, 0);\n  DeleteCriticalSection(&ccAccess);\n#endif\n}\n\nvoid CliScreen::log(LogType::LogType type, const std::string& source, const std::string& message)\n{\n  std::cout << \"[\" << currentTimestamp(true) << \"] \" << source << \": \" << message << std::endl;\n}\n\nvoid CliScreen::updatePlayerList(std::vector<User*> users)\n{\n}\n\nbool CliScreen::hasCommand()\n{\n#ifdef WIN32\n  return _hasCommand;\n#else\n  char readchar;\n  pollfd stdinfd[1];\n\n  while (true)\n  {\n    stdinfd[0].fd = fileno(stdin);\n    stdinfd[0].events = POLLIN;\n\n    if (!poll(stdinfd, 1, 0))\n    {\n      return false;\n    }\n\n    if (read(STDIN_FILENO, &readchar, 1) == -1)\n    {\n      return false;\n    }\n\n    if (readchar == '\\n')\n    {\n      return true;\n    }\n    else\n    {\n      currentCommand += readchar;\n    }\n  }\n#endif\n}\n\nbool CliScreen::CheckForCommand()\n{\n  if (ServerInstance->screen()->hasCommand())\n  {\n    // Now handle this command as normal\n    User serverUser(-1, SERVER_CONSOLE_UID);\n    serverUser.changeNick(\"[Server]\");\n    ServerInstance->chat()->handleMsg(&serverUser, ServerInstance->screen()->getCommand());\n  }\n\n  return false;\n}\n\nbool CliScreen::LogEvent(int type, const char* source, const char* message)\n{\n  ServerInstance->screen()->log((LogType::LogType)type, std::string(source), std::string(message));\n  return true;\n}\n\nstd::string CliScreen::getCommand()\n{\n  std::string command;\n#ifdef WIN32\n  EnterCriticalSection(&ccAccess);\n  //Get first line from currentCommand, and remove it\n  std::istringstream is;\n  is.str(currentCommand);\n  std::getline(is, command);\n  currentCommand = std::string((std::istreambuf_iterator<char>(is)),\n                               std::istreambuf_iterator<char>());\n  _hasCommand = !currentCommand.empty();\n  LeaveCriticalSection(&ccAccess);\n#else\n  command = currentCommand;\n  currentCommand.clear();\n#endif\n  return command;\n}\n"
  },
  {
    "path": "src/cliScreen.h",
    "content": "/*\n   Copyright (c) 2011, Kasper F. Brandt\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _CLISCREEN_H\n#define _CLISCREEN_H\n\n#include <string>\n#include <vector>\n\n#ifdef __WIN32__\n#include <windows.h>\n#endif\n\n#include \"screenBase.h\"\n#include \"logtype.h\"\n\nclass CliScreen : public Screen\n{\npublic:\n  void init(std::string version);\n  void log(LogType::LogType type, const std::string& source, const std::string& message);\n  void updatePlayerList(std::vector<User*> users);\n  void end();\n  bool hasCommand();\n  std::string getCommand();\n\n  static bool CheckForCommand();\n  static bool LogEvent(int type, const char* source, const char* message);\n\nprivate:\n  std::string currentCommand;\n#ifdef _WIN32\n  bool _hasCommand;\n  static DWORD WINAPI _stdinThreadProc(LPVOID lpParameter);\n  DWORD WINAPI stdinThreadProc();\n  CRITICAL_SECTION ccAccess;\n  HANDLE stdinThread;\n#endif\n};\n\n#endif //_CLISCREEN_H\n"
  },
  {
    "path": "src/config/lexer.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string>\n#include <stack>\n#include <utility>\n#include <iostream>\n\n#include \"scanner.h\"\n#include \"lexer.h\"\n\n\nvoid ConfigLexer::put_token(int type, const std::string& data)\n{\n  TokenPtr tmp(new Token);\n  tmp->first = type;\n  tmp->second = data;\n  m_tokenStack.push(tmp);\n}\n\nbool ConfigLexer::get_token(int& type, std::string& data)\n{\n  type = 0;\n  data.clear();\n\n  if (!m_tokenStack.empty())\n  {\n    TokenPtr tmp = m_tokenStack.top();\n    type = tmp->first;\n    data = tmp->second;\n    m_tokenStack.pop();\n    return true;\n  }\n\n  char buf = m_scanner.get();\n\n  // Skip past spaces and newlines\n  while ((buf == ' ') || (buf == '\\n') || (buf == '\\r') || (buf == '\\t'))\n  {\n    m_scanner.move(1);\n    buf = m_scanner.get();\n  }\n\n  // Nothing left to parse! Bail out!\n  if (m_scanner.left() <= 0)\n  {\n    return false;\n  }\n\n  // Entity\n  // Always starts with a letter, can contain only letters, numbers, periods and underscores\n  if (((buf >= 'a') && (buf <= 'z')) || ((buf >= 'A') && (buf <= 'Z')))\n  {\n    while (((buf >= 'a') && (buf <= 'z')) || ((buf >= 'A') && (buf <= 'Z')) || ((buf >= '0') && (buf <= '9')) || (buf == '.') || (buf == '_'))\n    {\n      data += buf;\n      m_scanner.move(1);\n      buf = m_scanner.get();\n    }\n\n    // Check for boolean literal is true and false\n    // This prevents us using true and false as identifiers.\n    if (data == \"true\" || data == \"false\")\n    {\n      type = CONFIG_TOKEN_BOOLEAN;\n    }\n    else\n    {\n      type = CONFIG_TOKEN_ENTITY;\n    }\n\n    return true;\n  }\n  // Number\n  // Always starts with a digit, may contain at most one decimal point\n  else if ((buf >= '0') && (buf <= '9'))\n  {\n    bool found = false;\n\n    while (((buf >= '0') && (buf <= '9')) || ((buf == '.') && (found == false)) || (buf == '_'))\n    {\n      if (buf == '.')\n      {\n        found = true;\n      }\n\n      if (buf != '_')\n      {\n        data += buf;\n      }\n\n      m_scanner.move(1);\n      buf = m_scanner.get();\n    }\n\n    type = CONFIG_TOKEN_NUMBER;\n    return true;\n  }\n  // Assignment operator\n  else if (buf == '=')\n  {\n    type = CONFIG_TOKEN_OPERATOR_ASSIGN;\n    m_scanner.move(1);\n    return true;\n  }\n  // Addition operator\n  else if ((buf == '+') && (m_scanner.at(m_scanner.pos() + 1) == '='))\n  {\n    type = CONFIG_TOKEN_OPERATOR_APPEND;\n    m_scanner.move(2);\n    return true;\n  }\n  // Quoted string\n  else if ((buf == '\"') || (buf == '\\''))\n  {\n    // Save the type of quote\n    int quote = buf;\n\n    // Move forward one character\n    m_scanner.move(1);\n\n    // Parse the string and any escape characters\n    char temp;\n    while (m_scanner.left() > 0)\n    {\n      // Avoid a couple of get() calls\n      temp = m_scanner.get();\n\n      // We've found the end of the string\n      if (temp == quote)\n      {\n        // Time to stop parsing!\n        break;\n      }\n\n      // This is used to escape other characters or itself\n      if (temp == '\\\\')\n      {\n        // Skip past the slash\n        m_scanner.move(1);\n\n        // Get the next character regardless of what it is\n        temp = m_scanner.get();\n\n        // Control characters (more can/will be added)\n        switch (temp)\n        {\n          // New line\n        case 'n':\n          temp = '\\n';\n          break;\n        }\n      }\n\n      // Add the character to the data string\n      data += temp;\n\n      // Move forward one\n      m_scanner.move(1);\n    }\n\n    // Skip past the ending quote\n    m_scanner.move(1);\n\n    // Record where the scanner was at before\n    int old_pos = m_scanner.pos();\n    // Skip past any whitespace\n    buf = m_scanner.get();\n    while ((buf == ' ') || (buf == '\\n') || (buf == '\\r') || (buf == '\\t'))\n    {\n      m_scanner.move(1);\n      buf = m_scanner.get();\n    }\n\n    // A quoted string followed by a colon is a label\n    if (buf == ':')\n    {\n      type = CONFIG_TOKEN_LABEL;\n      m_scanner.move(1);\n    }\n    else\n    {\n      type = CONFIG_TOKEN_STRING;\n      m_scanner.move(0 - (m_scanner.pos() - old_pos));\n    }\n\n    return true;\n  }\n  // End of statement\n  else if (buf == ';')\n  {\n    type = CONFIG_TOKEN_TERMINATOR;\n    m_scanner.move(1);\n    return true;\n  }\n  // Delimiter for naming list items\n  else if (buf == ':')\n  {\n    type = CONFIG_TOKEN_LIST_DELIMITER;\n    m_scanner.move(1);\n    return true;\n  }\n  // Delimiter for separating list items\n  else if (buf == ',')\n  {\n    type = CONFIG_TOKEN_LIST_DELIMITER;\n    m_scanner.move(1);\n    return true;\n  }\n  // Start of list\n  else if (buf == '(')\n  {\n    type = CONFIG_TOKEN_LIST_OPEN;\n    m_scanner.move(1);\n    return true;\n  }\n  // End of list\n  else if (buf == ')')\n  {\n    type = CONFIG_TOKEN_LIST_CLOSE;\n    m_scanner.move(1);\n    return true;\n  }\n  // Skip commented characters\n  else if (buf == '#')\n  {\n    while (buf != '\\n')\n    {\n      m_scanner.move(1);\n      buf = m_scanner.get();\n    }\n\n    return get_token(type, data);\n  }\n  // Unknown data, throw warnings everywhere!\n  else\n  {\n    type = 0;\n    m_scanner.move(1);\n    return true;\n  }\n}\n"
  },
  {
    "path": "src/config/lexer.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _CONFIG_LEXER_H\n#define _CONFIG_LEXER_H\n\n#include <string>\n#include <stack>\n#include <utility>\n\n#include <memory>\n\nenum {\n  CONFIG_TOKEN_ENTITY = 1,\n  CONFIG_TOKEN_LABEL = 2,\n  CONFIG_TOKEN_NUMBER = 3,\n  CONFIG_TOKEN_STRING = 4,\n  CONFIG_TOKEN_BOOLEAN = 5,\n\n  CONFIG_TOKEN_LIST_OPEN = 10,\n  CONFIG_TOKEN_LIST_CLOSE = 11,\n  CONFIG_TOKEN_LIST_DELIMITER = 12,\n  CONFIG_TOKEN_LIST_LABEL = 13,\n\n  CONFIG_TOKEN_OPERATOR_ASSIGN = 20,\n  CONFIG_TOKEN_OPERATOR_APPEND = 21,\n\n  CONFIG_TOKEN_TERMINATOR = 30\n};\n\nclass ConfigScanner;\n\nclass ConfigLexer\n{\n  typedef std::pair<int, std::string> Token;\n  typedef std::shared_ptr<Token> TokenPtr;\n\npublic:\n  ConfigLexer(ConfigScanner& scanner) : m_scanner(scanner) { }\n\n  bool get_token(int& type, std::string& data);\n  void put_token(int type, const std::string& data);\n\nprivate:\n  ConfigScanner& m_scanner;\n  std::stack<TokenPtr> m_tokenStack;\n};\n\n#endif\n"
  },
  {
    "path": "src/config/node.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string>\n#include <sstream>\n#include <map>\n#include <list>\n#include <iostream>\n\n#include \"node.h\"\n\nConfigNode::ConfigNode()\n  :\n  m_type(0),\n  m_index(0),\n  m_nData(0)\n{\n}\n\nstd::list<std::string> ConfigNode::keys(int type) const\n{\n  std::list<std::string> keys;\n\n  for (Map::const_iterator it = m_list.begin(); it != m_list.end(); ++it)\n  {\n    if (type == CONFIG_NODE_UNDEFINED || it->second->type() == type)\n    {\n      keys.push_back(it->first);\n    }\n\n    if (it->second->type() == CONFIG_NODE_LIST)\n    {\n      std::list<std::string> tmp_list = it->second->keys(type);\n      for (std::list<std::string>::const_iterator tmp_iter = tmp_list.begin(); tmp_iter != tmp_list.end(); ++tmp_iter)\n      {\n        keys.push_back(it->first + \".\" + *tmp_iter);\n      }\n    }\n  }\n\n  return keys;\n}\n\nbool ConfigNode::has(const std::string& key) const\n{\n  if (m_type != CONFIG_NODE_LIST)\n  {\n    return false;\n  }\n\n  const size_t pos = key.find('.');\n\n  if (pos != std::string::npos)\n  {\n    const std::string keyA(key.substr(0, pos));\n    const std::string keyB(key.substr(pos + 1));\n\n    const Map::const_iterator it = m_list.find(keyA);\n    return it == m_list.end() ? false : it->second->has(keyB);\n  }\n  else\n  {\n    return m_list.count(key) > 0;\n  }\n}\n\nConfigNode::Ptr ConfigNode::get(const std::string& key, bool createMissing)\n{\n  if (m_type != CONFIG_NODE_LIST)\n  {\n    return Ptr();\n  }\n\n  size_t pos = key.find('.');\n\n  if (pos != std::string::npos)\n  {\n    std::string keyA(key.substr(0, pos));\n    std::string keyB(key.substr(pos + 1));\n\n    const Map::const_iterator it = m_list.find(keyA);\n\n    if (it != m_list.end())\n    {\n      return it->second->get(keyB, createMissing);\n    }\n    else if (createMissing == false)\n    {\n      return Ptr();\n    }\n    else\n    {\n      return m_list.insert(Map::value_type(keyA, std::shared_ptr<ConfigNode>(new ConfigNode))).first->second->get(keyB, createMissing);\n    }\n  }\n  else\n  {\n    const Map::const_iterator it = m_list.find(key);\n\n    if (it != m_list.end())\n    {\n      return it->second;\n    }\n    else if (createMissing == false)\n    {\n      return Ptr();\n    }\n    else\n    {\n      return m_list.insert(Map::value_type(key, Map::mapped_type(new ConfigNode))).first->second;\n    }\n  }\n}\n\nbool ConfigNode::set(const std::string& key, ConfigNode::Ptr ptr, bool createMissing)\n{\n  m_type = CONFIG_NODE_LIST;\n\n  const size_t pos = key.find('.');\n\n  if (pos != std::string::npos)\n  {\n    const std::string keyA(key.substr(0, pos));\n    const std::string keyB(key.substr(pos + 1));\n\n    const Map::const_iterator it = m_list.find(keyA);\n\n    if (it == m_list.end())\n    {\n      if (createMissing == false)\n      {\n        return false;\n      }\n      else\n      {\n        return m_list.insert(Map::value_type(keyA, Map::mapped_type(new ConfigNode))).first->second->set(keyB, ptr, createMissing);\n      }\n    }\n    else\n    {\n      return it->second->set(keyB, ptr, createMissing);\n    }\n  }\n  else\n  {\n    ++m_index;\n    m_list[key] = ptr;\n    return true;\n  }\n}\n\nbool ConfigNode::add(ConfigNode::Ptr ptr)\n{\n  std::stringstream ss;\n  ss << m_index;\n\n  return set(ss.str(), ptr);\n}\n\nvoid ConfigNode::clear()\n{\n  m_type = 0;\n  m_nData = 0;\n  m_sData.clear();\n  m_list.clear();\n}\n\nvoid ConfigNode::dump(int indent) const\n{\n  for (int i = 0; i < indent; i++)\n  {\n    std::cout << \"  \";\n  }\n\n  switch (m_type)\n  {\n  case CONFIG_NODE_UNDEFINED:\n  {\n    std::cout << \"undefined\\n\";\n    break;\n  }\n\n  case CONFIG_NODE_LIST:\n  {\n    std::cout << \"list:\\n\";\n\n    for (Map::const_iterator it = m_list.begin(); it != m_list.end(); ++it)\n    {\n      for (int i = 0; i < indent + 1; ++i)\n      {\n        std::cout << \"  \";\n      }\n      std::cout << it->first << \" =>\\n\";\n      it->second->dump(indent + 1);\n    }\n\n    break;\n  }\n\n  case CONFIG_NODE_BOOLEAN:\n  {\n    std::cout << \"boolean: \" << ((m_nData == 0) ? \"true\" : \"false\") << \"\\n\";\n    break;\n  }\n\n  case CONFIG_NODE_NUMBER:\n  {\n    std::cout << \"number: \" << m_nData << \"\\n\";\n    break;\n  }\n\n  case CONFIG_NODE_STRING:\n  {\n    std::cout << \"string: \" << m_sData << \"\\n\";\n    break;\n  }\n\n  default:\n  {\n    std::cout << \"unknown\\n\";\n    break;\n  }\n  }\n}\n"
  },
  {
    "path": "src/config/node.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _CONFIG_NODE_H\n#define _CONFIG_NODE_H\n\n#include <string>\n#include <map>\n#include <list>\n\n#include <memory>\n\n#include <stdint.h>\n\n#define CONFIG_NODE_UNDEFINED 0\n#define CONFIG_NODE_LIST 1\n#define CONFIG_NODE_BOOLEAN 2\n#define CONFIG_NODE_NUMBER 3\n#define CONFIG_NODE_STRING 4\n\nclass ConfigNode\n{\npublic:\n\n  typedef std::shared_ptr<ConfigNode> Ptr;\n  typedef std::map<std::string, Ptr> Map;\n\n  ConfigNode();\n\n  inline bool bData() const\n  {\n    return m_type == CONFIG_NODE_BOOLEAN ? (m_nData != 0) : false;\n  }\n\n  inline int iData() const\n  {\n    return m_type == CONFIG_NODE_NUMBER ? (int)m_nData : 0;\n  }\n\n  inline int64_t lData() const\n  {\n    return m_type == CONFIG_NODE_NUMBER ? (int64_t)m_nData : 0;\n  }\n\n  inline float fData() const\n  {\n    return m_type == CONFIG_NODE_NUMBER ? (float)m_nData : 0;\n  }\n\n  inline double dData() const\n  {\n    return m_type == CONFIG_NODE_NUMBER ? m_nData : 0;\n  }\n\n  inline std::string sData() const\n  {\n    return m_type == CONFIG_NODE_STRING ? m_sData : \"\";\n  }\n\n  inline void setData(bool data)\n  {\n    m_type = CONFIG_NODE_BOOLEAN;\n    m_nData = data ? 1 : 0;\n  }\n\n  inline void setData(int data)\n  {\n    m_type = CONFIG_NODE_NUMBER;\n    m_nData = data;\n  }\n\n  inline void setData(int64_t data)\n  {\n    m_type = CONFIG_NODE_NUMBER;\n    m_nData = double(data);\n  }\n\n  inline void setData(float data)\n  {\n    m_type = CONFIG_NODE_NUMBER;\n    m_nData = double(data);\n  }\n\n  inline void setData(double data)\n  {\n    m_type = CONFIG_NODE_NUMBER;\n    m_nData = double(data);\n  }\n\n  inline void setData(const std::string& data)\n  {\n    m_type = CONFIG_NODE_STRING;\n    m_sData = data;\n  }\n\n  std::list<std::string> keys(int type = CONFIG_NODE_UNDEFINED) const;\n\n  inline int type() const\n  {\n    return m_type;\n  }\n\n  inline void setType(int type)\n  {\n    m_type = type;\n  }\n\n  bool has(const std::string& key) const;\n  Ptr  get(const std::string& key, bool createMissing = true);\n  bool set(const std::string& key, Ptr ptr, bool createMissing = true);\n  bool add(Ptr ptr);\n  void clear();\n  void dump(int indent = 0) const;\n\nprivate:\n  int m_type;\n  int m_index;\n  double m_nData;\n  std::string m_sData;\n  Map m_list;\n};\n\n#endif\n"
  },
  {
    "path": "src/config/parser.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string>\n#include <map>\n#include <stack>\n#include <iostream>\n#include <cstdlib>\n#include <fstream>\n#include <sstream>\n#include <sys/stat.h>\n\n#include \"scanner.h\"\n#include \"lexer.h\"\n#include \"parser.h\"\n#include \"node.h\"\n\n#include \"tools.h\"\n\nConfigParser::ConfigParser()\n  : m_includes(0)\n{\n}\n\nbool ConfigParser::parse(const std::string& file, ConfigNode::Ptr ptr)\n{\n  std::ifstream ifs(file.c_str(), std::ios_base::binary);\n\n  std::cout << \"Parser opening file \" << file << std::endl;\n  if (!ifs)\n  {\n    std::cerr << \"Couldn't open file: \" << file << \"\\n\";\n    return false;\n  }\n\n  return parse(ifs, ptr);\n}\n\nbool ConfigParser::parse(std::istream& data, ConfigNode::Ptr ptr)\n{\n  ConfigScanner scanner;\n  ConfigLexer lexer(scanner);\n  ConfigNode::Ptr root = ptr;\n\n  data.seekg(0, std::ios::end);\n  const size_t data_size = size_t(data.tellg());\n  data.seekg(0, std::ios::beg);\n\n  char* buf = new char[data_size];\n  data.read(buf, data_size);\n  std::string data_str(buf, data_size);\n  delete[] buf;\n\n  if (!scanner.read(data_str))\n  {\n    std::cerr << \"Couldn't read data!\\n\";\n    return false;\n  }\n\n  int token_type;\n  std::string token_data;\n  std::string token_label;\n  std::stack<ConfigNode::Ptr> nodeStack;\n  ConfigNode::Ptr currentNode = root;\n  nodeStack.push(currentNode);\n\n  while (lexer.get_token(token_type, token_data))\n  {\n    if (!token_type)\n    {\n      std::cerr << \"Unrecognised data!\\n\";\n      return false;\n    }\n\n    // Include other files only if we're in the root node\n    if (token_type == CONFIG_TOKEN_ENTITY && token_data == \"include\" && currentNode == root)\n    {\n      int tmp_type;\n      std::string tmp_data;\n\n      lexer.get_token(tmp_type, tmp_data);\n      if (tmp_type == CONFIG_TOKEN_STRING)\n      {\n        if (m_includes >= MAX_INCLUDES)\n        {\n          std::cerr << \"reached maximum number of include directives: \" << m_includes << \"\\n\";\n          return false;\n        }\n\n        // allow only filename without path\n        if ((tmp_data.find('/')  != std::string::npos)\n            || (tmp_data.find('\\\\') != std::string::npos))\n        {\n          std::cerr << \"include directive accepts only filename: \" << tmp_data << \"\\n\";\n          return false;\n        }\n\n        // prepend home path\n        const std::string var  = \"system.path.home\";\n        const ConfigNode::Ptr node = root->get(var, false);\n        std::string home;\n        if (!node || (home = node->sData()).empty())\n        {\n          std::cerr << \"include directive is not allowed before: \" << var << \"\\n\";\n          return false;\n        }\n\n        tmp_data = relativeToAbsolute(home) + PATH_SEPARATOR + tmp_data;\n\n        if (!parse(tmp_data, root))\n        {\n          return false;\n        }\n        m_includes++;\n\n        continue;\n      }\n      else\n      {\n        lexer.put_token(tmp_type, tmp_data);\n      }\n    }\n\n    if (token_type == CONFIG_TOKEN_ENTITY || token_type == CONFIG_TOKEN_LABEL)\n    {\n      token_label = token_data;\n    }\n\n    else if (token_type == CONFIG_TOKEN_OPERATOR_ASSIGN)\n    {\n      if (currentNode != root)\n      {\n        currentNode->clear();\n      }\n    }\n\n    else if (token_type == CONFIG_TOKEN_BOOLEAN)\n    {\n      ConfigNode::Ptr newNode(!token_label.empty() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));\n\n      newNode->setData(token_data == \"true\");\n\n      if (!token_label.empty())\n      {\n        currentNode->set(token_label, newNode, true);\n        token_label.clear();\n      }\n      else\n      {\n        currentNode->add(newNode);\n      }\n    }\n\n    else if (token_type == CONFIG_TOKEN_STRING)\n    {\n      ConfigNode::Ptr newNode(!token_label.empty() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));\n\n      newNode->setData(token_data);\n\n      if (!token_label.empty())\n      {\n        currentNode->set(token_label, newNode, true);\n        token_label.clear();\n      }\n      else\n      {\n        currentNode->add(newNode);\n      }\n    }\n\n    else if (token_type == CONFIG_TOKEN_NUMBER)\n    {\n      ConfigNode::Ptr newNode(token_label.size() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));\n\n      newNode->setData((double)::atof(token_data.c_str()));\n\n      if (!token_label.empty())\n      {\n        currentNode->set(token_label, newNode, true);\n        token_label.clear();\n      }\n      else\n      {\n        currentNode->add(newNode);\n      }\n    }\n\n    else if (token_type == CONFIG_TOKEN_LIST_OPEN)\n    {\n      ConfigNode::Ptr newNode(token_label.size() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode));\n\n      newNode->setType(CONFIG_NODE_LIST);\n\n      if (!token_label.empty())\n      {\n        currentNode->set(token_label, newNode, true);\n\n        newNode = currentNode->get(token_label, true);\n\n        token_label.clear();\n      }\n      else\n      {\n        currentNode->add(newNode);\n      }\n\n      nodeStack.push(currentNode);\n      currentNode = newNode;\n    }\n\n    else if (token_type == CONFIG_TOKEN_LIST_CLOSE)\n    {\n      currentNode = nodeStack.top();\n      nodeStack.pop();\n    }\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "src/config/parser.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _CONFIG_PARSER_H\n#define _CONFIG_PARSER_H\n\n#include <string>\n#include <stdint.h>\n\n#include <memory>\n\nenum\n{\n  MAX_FILESIZE = 1*1024*1024,   //!< maximum allowed file size\n  MAX_INCLUDES = 16             //!< maximum allowed number of inclusions\n};\n\nclass ConfigNode;\n\nclass ConfigParser\n{\npublic:\n  ConfigParser();\n\npublic:\n  bool parse(const std::string& file, std::shared_ptr<ConfigNode> ptr);\n  bool parse(std::istream& data, std::shared_ptr<ConfigNode> ptr);\n\nprivate:\n  uint32_t m_includes;\n};\n\n#endif\n"
  },
  {
    "path": "src/config/scanner.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string>\n\n#include \"scanner.h\"\n\nConfigScanner::ConfigScanner() : m_pos(0)\n{\n}\n\nbool ConfigScanner::read(const std::string& buf)\n{\n  if (buf.empty())\n  {\n    return false;\n  }\n\n  m_data = buf;\n\n  return true;\n}\n\nint ConfigScanner::move(int len)\n{\n  if (m_pos + len > int(m_data.length()))\n  {\n    len = int(m_data.length()) - m_pos;\n  }\n\n  if (m_pos + len < 0)\n  {\n    len = -m_pos;\n  }\n\n  m_pos += len;\n\n  return len;\n}\n"
  },
  {
    "path": "src/config/scanner.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <string>\n\n#ifndef _CONFIG_SCANNER_H\n#define _CONFIG_SCANNER_H\n\nclass ConfigScanner\n{\npublic:\n  ConfigScanner();\n\n  bool read(const std::string& buf);\n\n  int move(int len);\n\n  inline size_t size() const       { return m_data.length(); }\n  inline int left() const          { return m_data.length() - m_pos; }\n  inline char get() const          { return m_data[m_pos]; }\n  inline char at(size_t pos) const { return pos < m_data.length() ? m_data[pos] : -1; }\n  inline size_t pos() const        { return m_pos; }\n\nprivate:\n  std::string m_data;\n  int m_pos;\n};\n\n#endif\n"
  },
  {
    "path": "src/config.h",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _CONFIG_H\n#define _CONFIG_H\n\n#include <string>\n#include <list>\n#include <stdint.h>\n\n#include \"config/parser.h\"\n#include \"config/node.h\"\n\nclass ConfigParser;\n\nclass Config\n{\npublic:\n  Config()\n  :\n  m_parser(new ConfigParser),\n  m_root(new ConfigNode)\n  {\n  }\n\n  inline bool load(const std::string& file) const\n  {\n    return m_parser->parse(file, m_root);\n  }\n\n  inline bool load(std::istream& data) const\n  {\n    return m_parser->parse(data, m_root);\n  }\n\n  inline void dump() const\n  {\n    m_root->dump();\n  }\n\n  inline ConfigNode::Ptr root() const\n  {\n    return m_root;\n  }\n\n  inline int iData(const std::string& key)\n  {\n    return m_root->has(key) ? m_root->get(key, false)->iData() : 0;\n  }\n\n  inline int64_t lData(const std::string& key)\n  {\n    return m_root->has(key) ? m_root->get(key, false)->lData() : 0;\n  }\n\n  inline float fData(const std::string& key)\n  {\n    return m_root->has(key) ? m_root->get(key, false)->fData() : 0;\n  }\n\n  inline double dData(const std::string& key)\n  {\n    return m_root->has(key) ? m_root->get(key, false)->dData() : 0;\n  }\n\n  inline std::string sData(const std::string& key)\n  {\n    return m_root->has(key) ? m_root->get(key, false)->sData() : \"\";\n  }\n\n  inline bool bData(const std::string& key)\n  {\n    return m_root->has(key) ? m_root->get(key, false)->bData() : false;\n  }\n\n  inline ConfigNode::Ptr mData(const std::string& key)\n  {\n    return m_root->has(key) ? m_root->get(key, false) : ConfigNode::Ptr();\n  }\n\n  inline bool has(const std::string& key) const\n  {\n    return m_root->has(key);\n  }\n\n  inline int type(const std::string& key) const\n  {\n    return m_root->has(key) ? m_root->get(key)->type() : CONFIG_NODE_UNDEFINED;\n  }\n\n  inline std::list<std::string> keys(int type = CONFIG_NODE_UNDEFINED) const\n  {\n    return m_root->keys();\n  }\n\n  std::string config_path;\n\nprivate:\n  std::shared_ptr<ConfigParser> m_parser;\n  ConfigNode::Ptr m_root;\n};\n\n#endif\n"
  },
  {
    "path": "src/configure.h.in",
    "content": "//\n// defines provided by configuration (cmake)\n//\n\n#ifndef _CONFIGURE_H\n#define _CONFIGURE_H\n\n\n// directory names\n#cmakedefine CONFIG_DIR_BIN   \"@CONFIG_DIR_BIN@\"\n#cmakedefine CONFIG_DIR_ETC   \"@CONFIG_DIR_ETC@\"\n#cmakedefine CONFIG_DIR_LIB   \"@CONFIG_DIR_LIB@\"\n#cmakedefine CONFIG_DIR_SHARE \"@CONFIG_DIR_SHARE@\"\n#cmakedefine CONFIG_DIR_DISTSOURCE \"@CONFIG_DIR_DISTSOURCE@\"\n\n// Version strings\n#define VERSION_MAJOR \"@mineserver_MAJOR_VERSION@\"\n#define VERSION_MINOR \"@mineserver_MINOR_VERSION@\"\n#define VERSION_PATCH \"@mineserver_PATCH_LEVEL@\"\n#define VERSION_GIT_SHORT \"@VERSION_GIT@\"\n#define VERSION_GIT \"@VERSION_STR@\"\n#define VERSION_SIMPLE \"@mineserver_VERSION_SIMPLE@\"\n#define VERSION_COMPLETE \"@mineserver_VERSION_COMPLETE@\"\n\n// Windows specific fixes\n/*\n#ifdef WIN32\n#define unlink _unlink\n#define close closesocket\n#define getpid GetCurrentProcessId\n#endif\n*/\n\n// Justasic:\n// Check to see if we have the proper includes for our signal handler\n// if we do then include them as well\n#cmakedefine HAVE_BACKTRACE 1\n#cmakedefine HAVE_SYS_UTSNAME_H 1\n\n#ifdef HAVE_BACKTRACE\n# include <execinfo.h>\n#endif\n\n#ifdef HAVE_SYS_UTSNAME_H\n# include <sys/utsname.h>\n#endif\n\n#endif // _CONFIGURE_H\n"
  },
  {
    "path": "src/constants.cpp",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <map>\n\n#include \"constants.h\"\n#include \"random.h\"\n\nstd::map<uint8_t, DropPtr> BLOCKDROPS;\n\nconst unsigned int SERVER_CONSOLE_UID = -1;\n\nconst std::string VERSION = \"0.2.0 (Alpha)\";\n\nconst int PROTOCOL_VERSION = 47;\nconst std::string MINECRAFT_VERSION = \"1.8.9\";\n\nconst char COMMENTPREFIX  = '#';\n\n// Configuration\nconst std::string CONFIG_FILE = \"config.cfg\";\n\n// PID file\nconst std::string PID_FILE = \"mineserver.pid\";\n\n//allocate 1 MB for chunk files\nconst int ALLOCATE_NBTFILE = 1048576;\n\nconst int kMaxChatMessageLength = 119;\n\nvoid initConstants()\n{\n  // Block drops (10000 = 100%)\n\n  // Blocks that always drop one item\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_STONE, DropPtr(new Drop(BLOCK_COBBLESTONE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_GRASS, DropPtr(new Drop(BLOCK_DIRT, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_DIRT, DropPtr(new Drop(BLOCK_DIRT, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_COBBLESTONE, DropPtr(new Drop(BLOCK_COBBLESTONE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_PLANK, DropPtr(new Drop(BLOCK_PLANK, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_SAPLING, DropPtr(new Drop(BLOCK_SAPLING, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_SAND, DropPtr(new Drop(BLOCK_SAND, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_COAL_ORE, DropPtr(new Drop(ITEM_COAL, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_IRON_ORE, DropPtr(new Drop(BLOCK_IRON_ORE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_GOLD_ORE, DropPtr(new Drop(BLOCK_GOLD_ORE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_DIAMOND_ORE, DropPtr(new Drop(ITEM_DIAMOND, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_LOG, DropPtr(new Drop(BLOCK_LOG, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_LOG2, DropPtr(new Drop(BLOCK_LOG2, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_WOOL, DropPtr(new Drop(BLOCK_WOOL, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_WOODEN_STAIRS, DropPtr(new Drop(BLOCK_PLANK, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_RED_ROSE, DropPtr(new Drop(BLOCK_RED_ROSE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_YELLOW_FLOWER, DropPtr(new Drop(BLOCK_YELLOW_FLOWER, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_BROWN_MUSHROOM, DropPtr(new Drop(BLOCK_BROWN_MUSHROOM, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_RED_MUSHROOM, DropPtr(new Drop(BLOCK_RED_MUSHROOM, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_LADDER, DropPtr(new Drop(BLOCK_LADDER, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_CACTUS, DropPtr(new Drop(BLOCK_CACTUS, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_REED, DropPtr(new Drop(ITEM_REED, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_PUMPKIN, DropPtr(new Drop(BLOCK_PUMPKIN, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_TORCH, DropPtr(new Drop(BLOCK_TORCH, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_REDSTONE_TORCH_OFF, DropPtr(new Drop(BLOCK_REDSTONE_TORCH_ON, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_REDSTONE_TORCH_ON, DropPtr(new Drop(BLOCK_REDSTONE_TORCH_ON, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_REDSTONE_WIRE, DropPtr(new Drop(BLOCK_REDSTONE_WIRE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_LEVER, DropPtr(new Drop(BLOCK_LEVER, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_GLOWSTONE, DropPtr(new Drop(ITEM_GLOWSTONE_DUST, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_BRICK, DropPtr(new Drop(ITEM_CLAY_BRICK, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_JUKEBOX, DropPtr(new Drop(BLOCK_JUKEBOX, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_NETHERSTONE, DropPtr(new Drop(BLOCK_NETHERSTONE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_SLOW_SAND, DropPtr(new Drop(BLOCK_SLOW_SAND, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_JACK_O_LANTERN, DropPtr(new Drop(BLOCK_JACK_O_LANTERN, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_MINECART_TRACKS, DropPtr(new Drop(BLOCK_MINECART_TRACKS, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_MOSSY_COBBLESTONE, DropPtr(new Drop(BLOCK_MOSSY_COBBLESTONE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_OBSIDIAN, DropPtr(new Drop(BLOCK_OBSIDIAN, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_STEP, DropPtr(new Drop(BLOCK_STEP, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_WOODEN_DOOR, DropPtr(new Drop(ITEM_WOODEN_DOOR, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_IRON_DOOR, DropPtr(new Drop(ITEM_IRON_DOOR, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_SNOW, DropPtr(new Drop(ITEM_SNOWBALL, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_IRON_BLOCK, DropPtr(new Drop(BLOCK_IRON_BLOCK, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_GOLD_BLOCK, DropPtr(new Drop(BLOCK_GOLD_BLOCK, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_DIAMOND_BLOCK, DropPtr(new Drop(BLOCK_DIAMOND_BLOCK, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_LAPIS_BLOCK, DropPtr(new Drop(BLOCK_LAPIS_BLOCK, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_BED, DropPtr(new Drop(ITEM_BED, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_FURNACE, DropPtr(new Drop(BLOCK_FURNACE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_BURNING_FURNACE, DropPtr(new Drop(BLOCK_FURNACE, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_CHEST, DropPtr(new Drop(BLOCK_CHEST, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_WORKBENCH, DropPtr(new Drop(BLOCK_WORKBENCH, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_SIGN_POST, DropPtr(new Drop(ITEM_SIGN, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_WALL_SIGN, DropPtr(new Drop(ITEM_SIGN, 10000, 1))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_BREWING_STAND, DropPtr(new Drop(ITEM_BREWING_STAND, 10000, 1))));\n  \n\n  // Always drop but give more than one item\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_REDSTONE_ORE, DropPtr(new Drop(ITEM_REDSTONE, 10000, 4))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_CLAY, DropPtr(new Drop(ITEM_CLAY_BALLS, 10000, 4))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_SNOW_BLOCK, DropPtr(new Drop(ITEM_SNOWBALL, 10000, 4))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_DOUBLE_STEP, DropPtr(new Drop(BLOCK_STEP, 10000, 2))));\n\n  // Blocks that drop items by chance\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_GRAVEL, DropPtr(new Drop(ITEM_FLINT, 850, 1, 0, DropPtr(new Drop(BLOCK_GRAVEL, 10000, 1))))));\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_LEAVES, DropPtr(new Drop(BLOCK_SAPLING, 1200, 1))));\n\n  // Blocks that drop nothing:\n  // BLOCK_TNT, BLOCK_GLASS, BLOCK_MOB_SPAWNER\n\n  // Blocks that drop items with metadata\n  BLOCKDROPS.insert(std::pair<uint8_t, DropPtr>(BLOCK_LAPIS_ORE, DropPtr(new Drop(ITEM_DYE, 10000, 1, DYE_LAPIS_LAZULI))));\n}\n\nvoid Drop::getDrop(int16_t& item, uint8_t& count, uint8_t& meta)\n{\n  Drop *cur = this;\n  while (cur)\n  {\n    if (cur->probability >= uniformUINT(0, 9999))\n    {\n      item = cur->item_id;\n      count = cur->count;\n      if (cur->meta != -1) meta = (uint8_t)cur->meta;\n      return;\n    }\n    else\n    {\n      cur = cur->alt_drop.get();\n    }\n  }\n  count = 0;\n}\n"
  },
  {
    "path": "src/constants.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _CONSTANTS_H\n#define _CONSTANTS_H\n\n#include <map>\n#include <string>\n#include <stdint.h>\n#include <iostream>\n\n#include <memory>\n\n// configuration from build system\n#include \"configure.h\"\n#include \"constants_num.h\"\n#include \"extern.h\"\n\n//\n// Drops from blocks\n//\nstruct Drop;\ntypedef std::shared_ptr<Drop> DropPtr;\n\nstruct Drop\n{\n  uint16_t item_id;\n  uint32_t probability;\n  uint8_t count;\n  int16_t meta;\n  DropPtr alt_drop;\n\n  explicit Drop(uint16_t _item_id = 0, uint32_t _probability = 0, uint8_t _count = 0, int16_t _meta = -1, DropPtr _alt_drop = DropPtr())\n    :\n    item_id(_item_id),\n    probability(_probability),\n    count(_count),\n    meta(_meta),\n    alt_drop(_alt_drop)\n  {\n  }\n\n  void getDrop(int16_t& item, uint8_t& count, uint8_t& meta);\n};\n\nextern void initConstants();\n\nextern std::map<uint8_t, DropPtr> BLOCKDROPS;\n\n// Chat prefixes\nenum\n{\n  SERVERMSGPREFIX = '%',\n  CHATCMDPREFIX   = '/',\n  ADMINCHATPREFIX = '&'\n};\n\nextern const unsigned int SERVER_CONSOLE_UID;\n\nextern const std::string VERSION;\n\nextern const int PROTOCOL_VERSION;\nextern const std::string MINECRAFT_VERSION;\n\nextern const char COMMENTPREFIX;\n\n// Configuration\nextern const std::string CONFIG_FILE;\n\n// PID file\nextern const std::string PID_FILE;\n\n//allocate 1 MB for chunk files\nextern const int ALLOCATE_NBTFILE;\n\nextern const int kMaxChatMessageLength;\n\n#endif\n"
  },
  {
    "path": "src/constants_num.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _CONSTANTS_NUM_H\n#define _CONSTANTS_NUM_H\n#include <string>\n\n//\n// Mineserver constants\n//\n\n//Player digging status\nenum\n{\n  BLOCK_STATUS_STARTED_DIGGING,\n  BLOCK_STATUS_DIGGING,\n  //BLOCK_STATUS_STOPPED_DIGGING,\n  BLOCK_STATUS_BLOCK_BROKEN,\n  BLOCK_STATUS_DROP_ITEM_STACK,\n  BLOCK_STATUS_DROP_ITEM\n};\n\n// Chat colors\n#ifdef __cplusplus\n#define MC_COLOR_BLACK std::string(\"§0\")\n#define MC_COLOR_DARK_BLUE std::string(\"§1\")\n#define MC_COLOR_DARK_GREEN std::string(\"§2\")\n#define MC_COLOR_DARK_CYAN std::string(\"§3\")\n#define MC_COLOR_DARK_RED std::string(\"§4\")\n#define MC_COLOR_DARK_MAGENTA std::string(\"§5\")\n#define MC_COLOR_DARK_ORANGE std::string(\"§6\")\n#define MC_COLOR_GREY std::string(\"§7\")\n#define MC_COLOR_DARK_GREY std::string(\"§8\")\n#define MC_COLOR_BLUE std::string(\"§9\")\n#define MC_COLOR_GREEN std::string(\"§a\")\n#define MC_COLOR_CYAN std::string(\"§b\")\n#define MC_COLOR_RED std::string(\"§c\")\n#define MC_COLOR_MAGENTA std::string(\"§d\")\n#define MC_COLOR_YELLOW std::string(\"§e\")\n#define MC_COLOR_WHITE std::string(\"§f\")\n#else\n#define MC_COLOR_BLACK (\"§0\")\n#define MC_COLOR_DARK_BLUE (\"§1\")\n#define MC_COLOR_DARK_GREEN (\"§2\")\n#define MC_COLOR_DARK_CYAN (\"§3\")\n#define MC_COLOR_DARK_RED (\"§4\")\n#define MC_COLOR_DARK_MAGENTA (\"§5\")\n#define MC_COLOR_DARK_ORANGE (\"§6\")\n#define MC_COLOR_GREY (\"§7\")\n#define MC_COLOR_DARK_GREY (\"§8\")\n#define MC_COLOR_BLUE (\"§9\")\n#define MC_COLOR_GREEN (\"§a\")\n#define MC_COLOR_CYAN (\"§b\")\n#define MC_COLOR_RED (\"§c\")\n#define MC_COLOR_MAGENTA (\"§d\")\n#define MC_COLOR_YELLOW (\"§e\")\n#define MC_COLOR_WHITE (\"§f\")\n#endif\n\n// Direction\nenum Direction\n{\n  BLOCK_BOTTOM, BLOCK_NORTH, BLOCK_SOUTH, BLOCK_EAST, BLOCK_WEST, BLOCK_TOP\n};\n\n// Blocks\nenum Block\n{\n  BLOCK_AIR, BLOCK_STONE, BLOCK_GRASS, BLOCK_DIRT, BLOCK_COBBLESTONE, BLOCK_PLANK,\n  BLOCK_SAPLING, BLOCK_BEDROCK, BLOCK_WATER, BLOCK_STATIONARY_WATER, BLOCK_LAVA,\n  BLOCK_STATIONARY_LAVA, BLOCK_SAND, BLOCK_GRAVEL, BLOCK_GOLD_ORE, BLOCK_IRON_ORE,\n  BLOCK_COAL_ORE, BLOCK_LOG, BLOCK_LEAVES, BLOCK_SPONGE, BLOCK_GLASS, BLOCK_LAPIS_ORE,\n  BLOCK_LAPIS_BLOCK, BLOCK_DISPENSER, BLOCK_SANDSTONE, BLOCK_NOTE_BLOCK, BLOCK_BED,\n  BLOCK_YELLOW_FLOWER = 37, BLOCK_RED_ROSE, BLOCK_BROWN_MUSHROOM, BLOCK_RED_MUSHROOM,\n  BLOCK_GOLD_BLOCK, BLOCK_IRON_BLOCK, BLOCK_DOUBLE_STEP, BLOCK_STEP, BLOCK_BRICK,\n  BLOCK_TNT, BLOCK_BOOKSHELF, BLOCK_MOSSY_COBBLESTONE, BLOCK_OBSIDIAN, BLOCK_TORCH,\n  BLOCK_FIRE, BLOCK_MOB_SPAWNER, BLOCK_WOODEN_STAIRS, BLOCK_CHEST, BLOCK_REDSTONE_WIRE,\n  BLOCK_DIAMOND_ORE, BLOCK_DIAMOND_BLOCK, BLOCK_WORKBENCH, BLOCK_CROPS, BLOCK_SOIL,\n  BLOCK_FURNACE, BLOCK_BURNING_FURNACE, BLOCK_SIGN_POST, BLOCK_WOODEN_DOOR,\n  BLOCK_LADDER, BLOCK_MINECART_TRACKS, BLOCK_COBBLESTONE_STAIRS, BLOCK_WALL_SIGN,\n  BLOCK_LEVER, BLOCK_STONE_PRESSURE_PLATE, BLOCK_IRON_DOOR, BLOCK_WOODEN_PRESSURE_PLATE,\n  BLOCK_REDSTONE_ORE, BLOCK_GLOWING_REDSTONE_ORE, BLOCK_REDSTONE_TORCH_OFF,\n  BLOCK_REDSTONE_TORCH_ON, BLOCK_STONE_BUTTON, BLOCK_SNOW, BLOCK_ICE, BLOCK_SNOW_BLOCK,\n  BLOCK_CACTUS, BLOCK_CLAY, BLOCK_REED, BLOCK_JUKEBOX, BLOCK_FENCE_OAK, BLOCK_PUMPKIN,\n  BLOCK_NETHERSTONE, BLOCK_SLOW_SAND, BLOCK_GLOWSTONE, BLOCK_PORTAL, BLOCK_JACK_O_LANTERN,\n  BLOCK_CAKE, BLOCK_REDSTONE_REPEATER_OFF, BLOCK_REDSTONE_REPEATER_ON, BLOCK_LOCKED_CHEST,\n  BLOCK_WOOL = 35,\n  BLOCK_BREWING_STAND = 117,\n  BLOCK_LOG2 = 162,\n  BLOCK_FENCE_SPRUCE = 188, BLOCK_FENCE_BIRCH, BLOCK_FENCE_JUNGLE, BLOCK_FENCE_DARK_OAK,\n  BLOCK_FENCE_ACACIA\n};\n\n// Items\nenum\n{\n  ITEM_IRON_SPADE = 256, ITEM_IRON_PICKAXE, ITEM_IRON_AXE, ITEM_FLINT_AND_STEEL, ITEM_APPLE,\n  ITEM_BOW, ITEM_ARROW, ITEM_COAL, ITEM_DIAMOND, ITEM_IRON_INGOT, ITEM_GOLD_INGOT, ITEM_IRON_SWORD,\n  ITEM_WOODEN_SWORD, ITEM_WOODEN_SPADE, ITEM_WOODEN_PICKAXE, ITEM_WOODEN_AXE, ITEM_STONE_SWORD,\n  ITEM_STONE_SPADE, ITEM_STONE_PICKAXE, ITEM_STONE_AXE, ITEM_DIAMOND_SWORD,\n  ITEM_DIAMOND_SPADE, ITEM_DIAMOND_PICKAXE, ITEM_DIAMOND_AXE, ITEM_STICK, ITEM_BOWL,\n  ITEM_MUSHROOM_SOUP, ITEM_GOLD_SWORD, ITEM_GOLD_SPADE, ITEM_GOLD_PICKAXE, ITEM_GOLD_AXE,\n  ITEM_STRING, ITEM_FEATHER, ITEM_GUNPOWDER, ITEM_WOODEN_HOE, ITEM_STONE_HOE,\n  ITEM_IRON_HOE, ITEM_DIAMOND_HOE, ITEM_GOLD_HOE, ITEM_SEEDS, ITEM_WHEAT, ITEM_BREAD,\n  ITEM_LEATHER_HELMET, ITEM_LEATHER_CHESTPLATE, ITEM_LEATHER_LEGGINGS, ITEM_LEATHER_BOOTS,\n  ITEM_CHAINMAIL_HELMET, ITEM_CHAINMAIL_CHESTPLATE, ITEM_CHAINMAIL_LEGGINGS,\n  ITEM_CHAINMAIL_BOOTS, ITEM_IRON_HELMET, ITEM_IRON_CHESTPLATE, ITEM_IRON_LEGGINGS,\n  ITEM_IRON_BOOTS, ITEM_DIAMOND_HELMET, ITEM_DIAMOND_CHESTPLATE, ITEM_DIAMOND_LEGGINGS,\n  ITEM_DIAMOND_BOOTS, ITEM_GOLD_HELMET, ITEM_GOLD_CHESTPLATE, ITEM_GOLD_LEGGINGS,\n  ITEM_GOLD_BOOTS, ITEM_FLINT, ITEM_PORK, ITEM_GRILLED_PORK, ITEM_PAINTINGS,\n  ITEM_GOLDEN_APPLE, ITEM_SIGN, ITEM_WOODEN_DOOR, ITEM_BUCKET, ITEM_WATER_BUCKET,\n  ITEM_LAVA_BUCKET, ITEM_MINECART, ITEM_SADDLE, ITEM_IRON_DOOR, ITEM_REDSTONE,\n  ITEM_SNOWBALL, ITEM_BOAT, ITEM_LEATHER, ITEM_MILK_BUCKET, ITEM_CLAY_BRICK,\n  ITEM_CLAY_BALLS, ITEM_REED, ITEM_PAPER, ITEM_BOOK, ITEM_SLIME_BALL,\n  ITEM_STORAGE_MINECART, ITEM_POWERED_MINECART, ITEM_EGG, ITEM_COMPASS, ITEM_FISHING_ROD,\n  ITEM_WATCH, ITEM_GLOWSTONE_DUST, ITEM_RAW_FISH, ITEM_COOKED_FISH, ITEM_DYE,\n  ITEM_BONE, ITEM_SUGAR, ITEM_CAKE, ITEM_BED, ITEM_SHEARS = 359,\n  ITEM_BREWING_STAND = 379\n};\n\n// Records\nenum\n{\n  ITEM_GOLD_RECORD = 2256, ITEM_GREEN_RECORD\n};\n\n// Mobs\nenum\n{\n  MOB_CREEPER = 50, MOB_SKELETON, MOB_SPIDER, MOB_GIANT_ZOMBIE, MOB_ZOMBIE,\n  MOB_SLIME, MOB_GHAST, MOB_ZOMBIE_PIGMAN\n};\n\n// Animals\nenum\n{\n  MOB_PIG = 90, MOB_SHEEP, MOB_COW, MOB_CHICKEN, MOB_SQUID\n};\n\n//Instruments (based off http://www.minecraftwiki.net/wiki/Note_Block)\n\nenum\n{\n  INSTRUMENT_BASS = 1, INSTRUMENT_SNARE, INSTRUMENT_STICK, INSTRUMENT_BASSDRUM, INSTRUMENT_HARP\n};\n\nenum\n{\n  ENTITY_SAND = 21\n};\n\n// Animation\nenum\n{\n  ANIMATE_HURT = 2, ANIMATE_DEAD\n};\n\nenum\n{\n  ANIMATE_SWING = 1, ANIMATE_DAMAGE, ANIMATE_LEAVE_BED, ANIMATE_CROUCH = 104, ANIMATE_UNCROUCH\n};\n\nenum Dye\n{\n  DYE_INK_SAC, DYE_RED, DYE_CACTUS_GREEN, DYE_COCOA_BEANS, DYE_LAPIS_LAZULI, DYE_PURPLE, DYE_CYAN,\n  DYE_LIGHT_GRAY, DYE_GRAY, DYE_PINK, DYE_LIME, DYE_YELLOW, DYE_LIGHT_BLUE, DYE_MAGENTA, DYE_ORANGE,\n  DYE_BONE_MEAL\n};\n\nenum\n{\n  OBJECT_TYPE_ITEM_STACK = 2,\n  OBJECT_TYPE_MINECART = 10\n};\n\nenum\n{\n  USE_ENTITY_INTERACT=0,\n  USE_ENTITY_ATTACK,\n  USE_ENTITY_INTERACT_AT\n};\n\nenum\n{\n  ENTITY_STATUS_HURT=2,\n  ENTITY_STATUS_DEAD=3\n};\n\n// get block names.\n//extern std::string GetBlockName(Block);\n#endif\n"
  },
  {
    "path": "src/extern.h",
    "content": "/*\n  Copyright (c) 2011-2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n// NOTICE: These are for EXTERNAL GLOBAL VARIABLES ONLY!\n\n// NOTE: this is to be used with all classes that are considered \"API\" for plugins\n#ifndef EXTERN_H\n#define EXTERN_H\n\n#include \"SystemExceptions.h\"\n#ifndef _WIN32\n# define CoreExport\n#else\n# define CoreExport\n//__declspec(dllimport)\n#endif\n\n#ifndef MINESERVER_BUILD\n#define E extern CoreExport\n#else\n#define E extern\n#endif\n\nclass Mineserver;\nclass User;\nclass Map;\nclass Chat;\nclass Plugin;\nclass Screen;\nclass Config;\nclass FurnaceManager;\nclass PacketHandler;\nclass Physics;\nclass RedstoneSimulation;\nclass MapGen;\nclass Logger;\nclass Inventory;\nclass Mobs;\nclass Mob;\n\nE Mineserver *ServerInstance;\n\n#endif\n"
  },
  {
    "path": "src/fastset.h",
    "content": "#ifndef FASTSET_H\n#define FASTSET_H\n\n#include <memory>\n#include <vector>\n\n/// use for small 'set's with small T objects\ntemplate<class T, class Allocator = std::allocator<T> >\nclass fastset : public std::vector<T, Allocator>\n{\npublic:\n    typedef std::vector<T, Allocator> VectorT;\n     typename VectorT::iterator find(const T& t){\n        for(auto it = this->begin();it!=this->end();it++){\n            if(t == *it)\n                return it;\n        }\n        return this->end();\n    }\n    typename VectorT::const_iterator find(const T& t) const{\n        for(auto it = this->begin();it!=this->end();it++){\n            if(t == *it)\n                return it;\n        }\n        return this->end();\n    }\n    bool contains(const T& t) const{\n        return find(t) != this->end();\n    }\n};\n#endif // FASTSET_H\n"
  },
  {
    "path": "src/furnace.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <iostream>\n\n#include \"constants.h\"\n#include \"furnace.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"tools.h\"\n#include \"config.h\"\n#include \"protocol.h\"\n\nCreation createList[2258];\nbool configIsRead = false;\n\nCreation::Creation()\n{\n  output = -1;\n  meta = 0;\n  count = 0;\n}\n\nFurnace::Furnace(furnaceDataPtr data)\n  : m_data(data)\n{\n  uint8_t block;\n  uint8_t meta;\n\n  ServerInstance->map(m_data->map)->getBlock(m_data->x, m_data->y, m_data->z, &block, &meta);\n\n  if (!configIsRead)\n  {\n    readConfig();\n    configIsRead = true;\n  }\n\n  // Check if this is a burning block\n  if (block == BLOCK_BURNING_FURNACE)\n  {\n    m_burning = true;\n  }\n  else\n  {\n    m_burning = false;\n  }\n\n  // Make sure we're the right kind of block based on our current status\n  updateBlock();\n}\n\nvoid Furnace::updateItems()\n{\n  if (!hasValidIngredient())\n  {\n    m_data->cookTime = 0;\n  }\n  else\n  {\n\n  }\n}\n\nvoid Furnace::updateBlock()\n{\n  // Get a pointer to this furnace's current block\n  uint8_t block;\n  uint8_t meta;\n\n  // Now make sure that it's got the correct block type based on it's current status\n  if (isBurningFuel() && !m_burning)\n  {\n    ServerInstance->map(m_data->map)->getBlock(m_data->x, m_data->y, m_data->z, &block, &meta);\n    // Switch to burning furnace\n    ServerInstance->map(m_data->map)->setBlock(m_data->x, m_data->y, m_data->z, BLOCK_BURNING_FURNACE, meta);\n    ServerInstance->map(m_data->map)->sendBlockChange(m_data->x, m_data->y, m_data->z, BLOCK_BURNING_FURNACE, meta);\n    sendToAllUsers();\n    m_burning = true;\n  }\n  else if (!isBurningFuel() && m_burning)\n  {\n    ServerInstance->map(m_data->map)->getBlock(m_data->x, m_data->y, m_data->z, &block, &meta);\n    // Switch to regular furnace\n    ServerInstance->map(m_data->map)->setBlock(m_data->x, m_data->y, m_data->z, BLOCK_FURNACE, meta);\n    ServerInstance->map(m_data->map)->sendBlockChange(m_data->x, m_data->y, m_data->z, BLOCK_FURNACE, meta);\n    sendToAllUsers();\n    m_burning = false;\n  }\n}\n\nvoid Furnace::smelt()\n{\n  // Check if we're cooking\n  if (isCooking())\n  {\n    // Convert where applicable\n    Item* inputSlot  = &slots()[SLOT_INPUT];\n    Item* fuelSlot   = &slots()[SLOT_FUEL];\n    Item* outputSlot = &slots()[SLOT_OUTPUT];\n    int32_t creationID = createList[inputSlot->getType()].output;\n\n    // Update other params if we actually converted\n    if (creationID != -1 && outputSlot->getCount() != 64)\n    {\n      // Check if the outputSlot is empty\n      if (outputSlot->getType() == -1)\n      {\n        outputSlot->setType(creationID);\n        outputSlot->setCount(1);\n        outputSlot->setHealth(createList[inputSlot->getType()].meta);\n        inputSlot->setCount(inputSlot->getCount() - 1);\n        m_data->cookTime = 0;\n      }\n\n      // Ok - now check if the current output slot contains the same stuff\n      if (outputSlot->getType() == creationID && m_data->cookTime != 0)\n      {\n        // Increment output and decrememnt the input source\n        outputSlot->setCount(outputSlot->getCount() + createList[inputSlot->getType()].count);\n        inputSlot->setCount(inputSlot->getCount() - 1);\n        outputSlot->setHealth(createList[inputSlot->getType()].meta);\n        m_data->cookTime = 0;\n\n        if (inputSlot->getCount() == 0)\n        {\n          *inputSlot = Item();\n        }\n      }\n    }\n  }\n}\nbool Furnace::isBurningFuel()\n{\n  // Check if this furnace is currently burning\n  if (m_data->burnTime > 0)\n  {\n    return true;\n  }\n  else\n  {\n    return false;\n  }\n}\nbool Furnace::isCooking()\n{\n  // If we're burning fuel and have valid ingredients, we're cooking!\n  if (isBurningFuel() && hasValidIngredient())\n  {\n    return true;\n  }\n  else\n  {\n    return false;\n  }\n}\nbool Furnace::hasValidIngredient()\n{\n  // Check that we have a valid input type\n  Item* slot = &slots()[SLOT_INPUT];\n  if (slot->getType() < 0)\n  {\n    return false;\n  }\n  if (createList[slot->getType()].output != -1)\n  {\n    return true;\n  }\n  return false;\n}\nvoid Furnace::consumeFuel()\n{\n  // Check that we have fuel\n  if (slots()[SLOT_FUEL].getCount() == 0)\n  {\n    return;\n  }\n\n  // Increment the fuel burning time based on fuel type\n  // http://www.minecraftwiki.net/wiki/Furnace#Fuel_efficiency\n  Item* fuelSlot = &slots()[SLOT_FUEL];\n\n  uint16_t fuelTime = 0;\n  switch (fuelSlot->getType())\n  {\n  case ITEM_COAL:\n    fuelTime = 80;\n    break;\n  case BLOCK_PLANK:\n    fuelTime = 15;\n    break;\n  case ITEM_STICK:\n    fuelTime = 5;\n    break;\n  case BLOCK_LOG:\n    fuelTime = 15;\n    break;\n  case BLOCK_WORKBENCH:\n    fuelTime = 15;\n    break;\n  case BLOCK_CHEST:\n    fuelTime = 15;\n    break;\n  case BLOCK_BOOKSHELF:\n    fuelTime = 15;\n    break;\n  case BLOCK_JUKEBOX:\n    fuelTime = 15;\n    break;\n  case BLOCK_FENCE_OAK:\n  case BLOCK_FENCE_BIRCH:\n  case BLOCK_FENCE_JUNGLE:\n  case BLOCK_FENCE_DARK_OAK:\n  case BLOCK_FENCE_ACACIA:\n    fuelTime = 15;\n    break;\n  case BLOCK_WOODEN_STAIRS:\n    fuelTime = 15;\n    break;\n  case ITEM_LAVA_BUCKET:\n    fuelTime = 1000;\n    break;\n  default:\n    break;\n  }\n\n  if (fuelTime > 0)\n  {\n    m_data->burnTime += fuelTime;\n    // Now decrement the fuel & reset\n    fuelSlot->setCount(fuelSlot->getCount() - 1);\n    if (fuelSlot->getCount() == 0)\n    {\n      *fuelSlot = Item();\n    }\n  }\n\n  // Update our block type if need be\n  updateBlock();\n}\nint16_t Furnace::burnTime()\n{\n  return m_data->burnTime;\n}\nint16_t Furnace::cookTime()\n{\n  return 10;\n}\n\nvoid Furnace::sendToAllUsers()\n{\n\n\n  enum { PROGRESS_FIRE = 0, PROGRESS_ARROW = 2 };\n  //ToDo: send changes to all with this furnace opened\n\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory()->openFurnaces;\n\n  for (size_t openinv = 0; openinv < inv.size(); ++openinv)\n  {\n    if (inv[openinv]->x == m_data->x &&\n        inv[openinv]->y == m_data->y &&\n        inv[openinv]->z == m_data->z)\n    {\n      for (size_t user = 0; user < inv[openinv]->users.size(); ++user)\n      {\n        for (size_t j = 0; j < 3; ++j)\n        {\n          Item& item = m_data->items[j];\n          inv[openinv]->users[user]->writePacket(Protocol::setSlot(WINDOW_FURNACE, j, item));\n        }\n        inv[openinv]->users[user]->writePacket(Protocol::windowProperty(WINDOW_FURNACE, PROGRESS_FIRE,  m_data->burnTime>10?200: (m_data->burnTime * 20)));\n        inv[openinv]->users[user]->writePacket(Protocol::windowProperty(WINDOW_FURNACE, 3, 200));\n        inv[openinv]->users[user]->writePacket(Protocol::windowProperty(WINDOW_FURNACE, PROGRESS_ARROW, (m_data->cookTime * 20)));\n      }\n\n      break;\n    }\n  }\n\n}\n\nvoid readConfig()\n{\n  const std::string key = \"furnace.items\";\n  if (ServerInstance->config()->has(key) && ServerInstance->config()->type(key) == CONFIG_NODE_LIST)\n  {\n    std::list<std::string> tmp = ServerInstance->config()->mData(key)->keys();\n    for (std::list<std::string>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)\n    {\n      int input = ServerInstance->config()->iData(key + \".\" + *it + \".in\");\n      createList[input].output = ServerInstance->config()->iData(key + \".\" + *it + \".out\");\n      createList[input].meta = ServerInstance->config()->iData(key + \".\" + *it + \".meta\");\n      createList[input].count = ServerInstance->config()->iData(key + \".\" + *it + \".count\");\n    }\n  }\n}\n"
  },
  {
    "path": "src/furnace.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _FURNACE_H\n#define _FURNACE_H\n\n#include <cstdlib>\n#include <stdint.h>\n#include \"chunkmap.h\"\n\nclass User;\nclass NBT_Value;\n\nclass Creation\n{\npublic:\n  int output, meta, count;\n  Creation();\n};\n\nenum\n{\n  SLOT_INPUT,\n  SLOT_FUEL,\n  SLOT_OUTPUT\n};\n\nclass Furnace\n{\n\n\npublic:\n  Furnace(furnaceDataPtr data);\n\n  void sendToAllUsers();\n  void smelt();\n  bool isBurningFuel();\n  bool isCooking();\n  bool hasValidIngredient();\n  void consumeFuel();\n  void updateBlock();\n\n  /**\n   * Getter & setter methods\n   */\n\n  int16_t burnTime();\n  int16_t cookTime();\n  void updateItems();\n\n  inline int16_t fuelBurningTime() const\n  {\n    return m_data->burnTime;\n  }\n\n  inline int16_t setFuelBurningTime(int16_t burntime)\n  {\n    m_data->burnTime = burntime;\n    return m_data->burnTime;\n  }\n\n  inline int16_t cookingTime() const\n  {\n    return m_data->cookTime;\n  }\n  inline int16_t setCookingTime(int16_t cookTime)\n  {\n    m_data->cookTime = cookTime;\n    return m_data->cookTime;\n  }\n\n  inline int32_t x() const { return m_data->x; }\n  inline int32_t y() const { return m_data->y; }\n  inline int32_t z() const { return m_data->z; }\n\n  Item* slots()\n  {\n    return m_data->items;\n  };\n\nprivate:\n  furnaceDataPtr m_data;\n  bool m_burning;\n};\n\nvoid readConfig();\n\n#endif // _FURNACE.H\n"
  },
  {
    "path": "src/furnaceManager.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <iostream>\n#include <algorithm>\n\n#include \"furnaceManager.h\"\n#include \"furnace.h\"\n#include \"mineserver.h\"\n#include \"logger.h\"\n#include \"tools.h\"\n\nvoid FurnaceManager::update()\n{\n  // Loop thru all the furnaces\n  for (FurnaceContainer::iterator it = m_activeFurnaces.begin(); it != m_activeFurnaces.end(); )\n  {\n    // Get a pointer to this furnace\n    FurnacePtr currentFurnace = *it;\n\n    // If we're burning, decrememnt the fuel\n    if (currentFurnace->isBurningFuel())\n    {\n      currentFurnace->setFuelBurningTime(currentFurnace->fuelBurningTime() - 1);\n    }\n    // Now that we've decremented, if we're no longer burning fuel but still have stuff to cook, consume fuel\n    if (!currentFurnace->isBurningFuel() && currentFurnace->hasValidIngredient())\n    {\n      currentFurnace->consumeFuel();\n    }\n\n    // If we're cooking, increment the activity and check if we're ready to smelt the output\n    if (currentFurnace->isCooking())\n    {\n      currentFurnace->setCookingTime(currentFurnace->cookingTime() + 1);\n      if (currentFurnace->cookingTime() >= currentFurnace->cookTime())\n      {\n        // Finished cooking time, so create the output\n        currentFurnace->smelt();\n      }\n    }\n\n    // Update all clients\n    currentFurnace->sendToAllUsers();\n\n    // Update it's block style\n    currentFurnace->updateBlock();\n\n    // Remove this furnace from the list once it stops burning it's current fuel\n    if (!currentFurnace->isBurningFuel())\n    {\n      it = m_activeFurnaces.erase(it);\n    }\n    else\n    {\n      ++it;\n    }\n  }\n}\n\nvoid removeFurnace(furnaceDataPtr data)\n{\n  ServerInstance->furnaceManager()->removeFurnace(data);\n}\n\nstruct FurnaceDataFinder\n{\n  FurnaceDataFinder(furnaceDataPtr d) : data(d) { }\n  furnaceDataPtr data;\n  inline bool operator()(FurnacePtr f) { return (f->x() == data->x && f->y() == data->y && f->z() == data->z); }\n};\n\nvoid FurnaceManager::removeFurnace(furnaceDataPtr data)\n{\n  m_activeFurnaces.remove_if(FurnaceDataFinder(data));\n}\n\nvoid FurnaceManager::handleActivity(furnaceDataPtr data)\n{\n  FurnaceContainer::iterator it = std::find_if(m_activeFurnaces.begin(), m_activeFurnaces.end(), FurnaceDataFinder(data));\n  const bool found = !(it == m_activeFurnaces.end());\n  FurnacePtr furnace = found ? *it : FurnacePtr(new Furnace(data));\n\n  if (found) furnace->updateItems();\n\n  // Check if this furnace is active\n  if ((furnace->isBurningFuel() || furnace->slots()[SLOT_FUEL].getCount() > 0) &&  furnace->hasValidIngredient())\n  {\n    if (!found) m_activeFurnaces.push_front(furnace);\n  }\n  else\n  {\n    if (found)  m_activeFurnaces.erase(it);\n  }\n}\n\n\n"
  },
  {
    "path": "src/furnaceManager.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _FURNACE_MANAGER_H\n#define _FURNACE_MANAGER_H\n\n#include <stdint.h>\n#include <list>\n#include \"chunkmap.h\"\n\n\nclass Furnace;\nclass NBT_Value;\n\ntypedef std::shared_ptr<Furnace> FurnacePtr;\n\nclass FurnaceManager\n{\npublic:\n  void update();\n  void handleActivity(std::shared_ptr<furnaceData> data);\n  void removeFurnace(std::shared_ptr<furnaceData> data);\n\nprivate:\n  typedef std::list<FurnacePtr> FurnaceContainer;\n  FurnaceContainer m_activeFurnaces;\n};\n\nvoid removeFurnace(std::shared_ptr<furnaceData> data);\n\n\n#endif\n"
  },
  {
    "path": "src/inventory/inventoryBasic.cpp",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdint.h>\n#include <string>\n#include \"inventoryPlayer.h\"\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"protocol.h\"\n#include \"map.h\"\n\n\nbool InventoryBasic::handleDrag(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n  Inventory* inventory = ServerInstance->inventory();\n  //Start of stop drag\n  if (slot == -999)\n  {\n    if(user->inventoryHolding.getType() != -1)\n    {\n      //click-and-drag (begin)\n      if(button == INVENTORY_BUTTON_START_DRAG_RIGHT || button == INVENTORY_BUTTON_LEFT)\n      {\n        user->openInv.slotActions.clear();\n        user->openInv.recordAction = true;\n        return true;\n      }\n      //click-and-drag (end)\n      else if(button == INVENTORY_BUTTON_END_DRAG_LEFT || button == INVENTORY_BUTTON_END_DRAG_RIGHT)\n      {\n        user->openInv.recordAction = false;\n\n        //Spread the stack nice and evenly\n        if(!user->openInv.slotActions.size() || user->openInv.slotActions.size() > (uint32_t)user->inventoryHolding.getCount())\n        {\n          //FAILURE (should not happen)\n          return true;\n        }\n\n        // Handle spreading the stack, leftover stays in the Holding\n        \n        // Store original for a while\n        Item tempHolding = user->inventoryHolding;\n        \n        Item oneStack(user->inventoryHolding.getType(), user->inventoryHolding.getCount(),user->inventoryHolding.getHealth());\n\n        // With left click put the same amount of items in a slot\n        if (button == INVENTORY_BUTTON_END_DRAG_LEFT)\n        {\n          int16_t count = (user->inventoryHolding.getCount()/user->openInv.slotActions.size());\n          oneStack.setCount(count);\n          tempHolding.setCount(user->inventoryHolding.getCount() - count*user->openInv.slotActions.size());\n        }\n        else // Right click\n        {\n          oneStack.setCount(1);\n          tempHolding.setCount(user->inventoryHolding.getCount() - user->openInv.slotActions.size());\n        }\n\n        // Set \"oneStack\" to each of the slots\n        for(uint32_t i = 0; i < user->openInv.slotActions.size(); i++)\n        {\n          user->inventoryHolding = oneStack;\n          onwindowClick(user, windowID, user->openInv.slotActions[i], INVENTORY_BUTTON_LEFT, 0, -1, 0, 0, INVENTORY_MODE_NORMAL);\n        }\n        // Restore holding\n        user->inventoryHolding = tempHolding;\n        inventory->setSlot(user, WINDOW_CURSOR, 0, &user->inventoryHolding);\n      }\n    }\n    return true;\n  }\n  //on click-and-drag mode, recording the slots used\n  else if(user->openInv.recordAction)\n  {\n    if(mode == INVENTORY_BUTTON_ADD_SLOTS_RIGHT || mode == INVENTORY_BUTTON_ADD_SLOTS_LEFT)\n    {\n      user->openInv.slotActions.push_back(slot);\n    }\n    else\n    {\n      user->openInv.recordAction = false;\n    }\n    return true;\n  }\n\n  return true;\n}\n\n\nbool InventoryBasic::handleNumber(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n  Inventory* inventory = ServerInstance->inventory();\n\n  // Only when not holding anything\n  if(user->inventoryHolding.getType() == -1)\n  {\n    // Offset for \"toolbar\" items depending on the opened inventory\n    int inventory_offset;\n    switch (windowID) {\n      case WINDOW_PLAYER:\n        inventory_offset = 36;\n      break;\n      case WINDOW_CRAFTING_TABLE:\n        inventory_offset = 37;\n      break;\n      case WINDOW_CHEST:\n        inventory_offset = 27;\n      break;\n      case WINDOW_LARGE_CHEST:\n        inventory_offset = 54;\n      break;\n      case WINDOW_FURNACE:\n        inventory_offset = 30;\n      break;\n      case WINDOW_BREWING_STAND:\n        inventory_offset = 30;\n      break;\n      default:\n      return false;\n        \n    }\n    // Pick up from toolbar\n    onwindowClick(user, windowID, inventory_offset+button, INVENTORY_BUTTON_LEFT, 0, -1, 0, 0, INVENTORY_MODE_NORMAL);\n    // Swap with slot\n    onwindowClick(user, windowID, slot, INVENTORY_BUTTON_LEFT, 0, -1, 0, 0, INVENTORY_MODE_NORMAL);    \n    // Insert back to toolbar if holding something\n    if(user->inventoryHolding.getType() != -1)\n    {\n      onwindowClick(user, windowID, inventory_offset+button, INVENTORY_BUTTON_LEFT, 0, -1, 0, 0, INVENTORY_MODE_NORMAL);\n    }\n  }\n\n  return true;\n}"
  },
  {
    "path": "src/inventory/inventoryBrewingstand.cpp",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdint.h>\n#include <string>\n#include \"inventoryBrewingstand.h\"\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"protocol.h\"\n#include \"map.h\"\n\nbool InventoryBrewingstand::onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, \n                                          int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n\n  // Safeguard against overflow\n  if (slot > MAX_SLOT_BREWING_STAND) return false;\n  if (slot != -999 && slot < 0) return false;\n\n  return true;\n}\n\nbool InventoryBrewingstand::onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{  \n  // ToDo: openBrewingstands\n  /*\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory.openFurnaces;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      inv[i]->users.push_back(user);\n      user->isOpenInv = true;\n      user->openInv = *inv[i];\n      break;\n    }\n  }\n\n  if (!user->isOpenInv)\n  {\n    //If the inventory not yet opened, create it\n    OpenInvPtr newInv(new OpenInventory());\n    newInv->type = type;\n    newInv->x    = x;\n    newInv->y    = y;\n    newInv->z    = z;\n    user->openInv = *newInv;\n\n    newInv->users.push_back(user);\n\n    inv.push_back(newInv);\n    user->isOpenInv = true;\n  }\n  */\n\n  user->writePacket(Protocol::openWindow(WINDOW_BREWING_STAND,INVENTORYTYPE_BREWING_STAND,\"{\\\"text\\\": \\\"\"+json_esc(\"Brewing Stand\")+\"\\\"}\", 4));\n\n\n  return true;\n}\n\nbool InventoryBrewingstand::onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  //ToDo: openBrewingStands\n  /*\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory.openFurnaces;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      for (size_t j = 0; j < inv[i]->users.size(); ++j)\n      {\n        if (inv[i]->users[j] == user)\n        {\n          // We should make users into a container that supports fast erase.\n          inv[i]->users.erase(inv[i]->users.begin() + j);\n\n          user->isOpenInv = false;\n          return true;\n        }\n      }\n      break;\n    }\n  }\n  */\n  user->isOpenInv = false;\n  return true;\n}"
  },
  {
    "path": "src/inventory/inventoryBrewingstand.h",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include <stdint.h>\n#include <string>\n#include \"inventorybasic.h\"\n#include \"constants_num.h\"\n#include \"inventory.h\"\n\nclass User;\n\n/**\n * InventoryBrewingstand handles all the brewing stands\n */\nclass InventoryBrewingstand :  public InventoryBasic\n{\npublic:\n  bool affected(int window_id) const { return window_id == WINDOW_BREWING_STAND; };\n  bool onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode = 0);\n  bool onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n  bool onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n};\n"
  },
  {
    "path": "src/inventory/inventoryChest.cpp",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdint.h>\n#include <string>\n#include \"inventoryChest.h\"\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"protocol.h\"\n#include \"chunkmap.h\"\n#include \"map.h\"\n\nbool InventoryChest::onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber,\n                                  int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n\n  if (windowID == WINDOW_LARGE_CHEST && slot > MAX_SLOT_LARGE_CHEST) return false;\n  else if (windowID == WINDOW_CHEST && slot > MAX_SLOT_CHEST) return false;\n  if (slot != -999 && slot < 0) return false;\n\n  Inventory* inventory = ServerInstance->inventory();\n  //Ack\n  if(actionNumber)\n  {\n    // ToDo: actually check the action before ack\n    user->writePacket(Protocol::confirmTransaction(windowID, actionNumber, 1));\n  }\n\n  // Handle drag mode in a base class helper function\n  if (mode == INVENTORY_MODE_DRAG)\n  {\n    return this->handleDrag(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n  else if (mode == INVENTORY_MODE_NUMBER)\n  {\n    return this->handleNumber(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n\n  user->openInv.recordAction = false;\n\n  //Click outside the window\n  if (slot == -999)\n  {\n    //Dropping outside of the window\n    if(button == 0 && mode == 0 && user->inventoryHolding.getType() != -1)\n    {\n      ServerInstance->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,\n          user->inventoryHolding.getType(), user->inventoryHolding.getCount(),\n          user->inventoryHolding.getHealth(), user);\n      user->inventoryHolding.setType(-1);\n      return true;\n    }\n    return true;\n  }\n  //on click-and-drag mode, recording the slots used\n  else if(user->openInv.recordAction)\n  {\n    if(mode == 5)\n    {\n      user->openInv.slotActions.push_back(slot);\n    }\n    else\n    {\n      user->openInv.recordAction = false;\n    }\n    return true;\n  }\n\n  if (!user->isOpenInv && windowID != 0)\n  {\n    return false;\n  }\n\n  sChunk* chunk = NULL;\n  chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(user->openInv.x), blockToChunk(user->openInv.z));\n\n  if (chunk == NULL)\n  {\n    return false;\n  }\n\n  chunk->changed = true;\n\n  chestDataPtr _thischest;\n  for(size_t i = 0; i < chunk->chests.size(); i++)\n  {\n    if((chunk->chests[i]->x() == user->openInv.x)\n      && (chunk->chests[i]->y() == user->openInv.y)\n      && (chunk->chests[i]->z() == user->openInv.z))\n    {\n      _thischest = chunk->chests[i];\n      break;\n    }\n  }\n\n  std::vector<User*>* otherUsers = NULL;\n  std::vector<User*>* otherUsersCon = NULL;\n\n  std::vector<OpenInvPtr>& inv = inventory->openChests;\n\n  for (size_t i = 0; i < inv.size(); i++)\n  {\n    if (inv[i]->x == user->openInv.x &&\n        inv[i]->y == user->openInv.y &&\n        inv[i]->z == user->openInv.z)\n    {\n      otherUsers = &inv[i]->users;\n      break;\n    }\n  }\n  // Users in connected chest\n  if (_thischest->large())\n  {\n    for (size_t i = 0; i < inv.size(); i++)\n    {\n      if (inv[i]->x == _thischest->getConnectedLoc().x() &&\n          inv[i]->y == _thischest->getConnectedLoc().y() &&\n          inv[i]->z == _thischest->getConnectedLoc().z())\n      {\n        otherUsersCon = &inv[i]->users;\n        break;\n      }\n    }\n  }\n\n  if (otherUsers == NULL)\n  {\n    return false;\n  }\n\n  Item* slotItem = NULL;\n\n  switch (windowID)\n  {\n  case WINDOW_CHEST:\n    if (slot > 26)\n    {\n      slotItem = &user->inv[slot - 18];\n    }\n    else\n    {\n      for (uint32_t i = 0; i < chunk->chests.size(); i ++)\n      {\n        if (chunk->chests[i]->x() == user->openInv.x &&\n            chunk->chests[i]->y() == user->openInv.y &&\n            chunk->chests[i]->z() == user->openInv.z)\n        {\n          slotItem = (*chunk->chests[i]->items())[slot].get();\n          break;\n        }\n      }\n      // Chest data has to exist at this point\n      if (slotItem == NULL)\n      {\n        return false;\n      }\n    }\n    break;\n  case WINDOW_LARGE_CHEST:\n    if (slot > 53)\n    {\n      slotItem = &user->inv[slot - 45];\n    }\n    else\n    {\n      // Search for this chest\n      for (chestDataPtr chest : chunk->chests)\n      {\n        if(chest->x() == user->openInv.x &&\n           chest->y() == user->openInv.y &&\n           chest->z() == user->openInv.z)\n        {\n          // Chests are separate entities and connected with \"top\" bit telling which is the top part of inventory\n\n          // Bottom part\n          if (slot > 26) {\n            slotItem = chest->getTop()?(*chest->getConnectedData()->items())[slot-27].get() : (*chest->items())[slot-27].get() ;\n          } else { // Top part\n            slotItem = chest->getTop()?(*chest->items())[slot].get() : (*chest->getConnectedData()->items())[slot].get();\n          }\n          break;\n        }\n      }\n\n      // Chest data has to exist at this point\n      if (slotItem == NULL)\n      {\n        return false;\n      }\n\n    }\n    break;\n  }\n  \n  //Empty slot and holding something\n  if ((slotItem->getType() == -1 || (slotItem->getType() == user->inventoryHolding.getType() && slotItem->getHealth() == user->inventoryHolding.getHealth() && slotItem->getCount() < 64)) && user->inventoryHolding.getType() != -1)\n  {\n    //ToDo: Make sure we have room for the items!\n\n    //Make sure not putting anything to the crafting space\n    if ((windowID != WINDOW_CRAFTING_TABLE && windowID != WINDOW_PLAYER) || slot != 0)\n    {\n      int16_t addCount = (64 - slotItem->getCount() >= user->inventoryHolding.getCount()) ? user->inventoryHolding.getCount() : 64 - slotItem->getCount();\n\n      slotItem->decCount(0 - ((button) ? 1 : addCount));\n      slotItem->setHealth(user->inventoryHolding.getHealth());\n      slotItem->setType(user->inventoryHolding.getType());\n\n      user->inventoryHolding.decCount((button) ? 1 : addCount);\n    }\n  }\n  //We are not holding anything, get the item we clicked\n  else if (user->inventoryHolding.getType() == -1)\n  {\n    //Shift+click -> items to player inv\n    //ToDo: from player inventory to chest\n    if(!button && mode && inventory->isSpace(user, slotItem->getType(), slotItem->getCount()))\n    {\n      inventory->addItems(user, slotItem->getType(), slotItem->getCount(), slotItem->getHealth());\n      slotItem->setCount(0);\n    }\n    else\n    {\n      user->inventoryHolding.setType(slotItem->getType());\n      user->inventoryHolding.setHealth(slotItem->getHealth());\n      user->inventoryHolding.setCount(slotItem->getCount());\n      if (button == 1)\n      {\n        user->inventoryHolding.decCount(slotItem->getCount() >> 1);\n      }\n      slotItem->decCount(user->inventoryHolding.getCount());\n    }\n      \n    if (slotItem->getCount() == 0)\n    {\n      slotItem->setHealth(0);\n      slotItem->setType(-1);\n    }\n  }\n  else\n  {\n    //Swap items if holding something and clicking another, not with craft slot\n    int16_t type = slotItem->getType();\n    int8_t count = slotItem->getCount();\n    int16_t health = slotItem->getHealth();\n    slotItem->setType(user->inventoryHolding.getType());\n    slotItem->setCount(user->inventoryHolding.getCount());\n    slotItem->setHealth(user->inventoryHolding.getHealth());\n    user->inventoryHolding.setType(type);\n    user->inventoryHolding.setCount(count);\n    user->inventoryHolding.setHealth(health);\n  }\n\n  //Update slot\n  inventory->setSlot(user, windowID, slot, slotItem);\n\n  //Update item on the cursor\n  inventory->setSlot(user, WINDOW_CURSOR, 0, &user->inventoryHolding);\n  \n  //Signal others using the same space\n  switch(windowID)\n  {\n    case WINDOW_CHEST:\n      if(slot > 26)\n      {\n        return true;\n      }\n      break;\n    case WINDOW_LARGE_CHEST:\n      if(slot > 53)\n      {\n        return true;\n      }\n  }\n\n  for(uint32_t i = 0; i < otherUsers->size(); i++)\n  {\n    if((*otherUsers)[i] != user)\n    {\n      inventory->setSlot((*otherUsers)[i], windowID, slot, slotItem);\n    }\n  }\n\n  // If connected chest inventory was found, loop that too\n  if (otherUsersCon != NULL)\n  {\n    for(uint32_t i = 0; i < otherUsersCon->size(); i++)\n    {\n      if((*otherUsersCon)[i] != user)\n      {\n        inventory->setSlot((*otherUsersCon)[i], windowID, slot, slotItem);\n      }\n    } \n  }\n  return true;\n}\n\nbool InventoryChest::onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(x), blockToChunk(z));\n  if (chunk == NULL)\n  {\n    return false;\n  }\n\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory()->openChests;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      inv[i]->users.push_back(user);\n      user->isOpenInv = true;\n      user->openInv = *inv[i];\n      break;\n    }\n  }\n\n  if (!user->isOpenInv)\n  {\n    //If the inventory not yet opened, create it\n    OpenInvPtr newInv(new OpenInventory());\n    newInv->type = type;\n    newInv->x    = x;\n    newInv->y    = y;\n    newInv->z    = z;\n    user->openInv = *newInv;\n\n    newInv->users.push_back(user);\n\n    inv.push_back(newInv);\n    user->isOpenInv = true;\n\n    //Chest opening animation and sound\n    user->sendAll(Protocol::blockAction(x,y,z,1,1,BLOCK_CHEST));\n    user->sendAll(Protocol::namedSoundEffect(\"random.chestopen\", x<<3, y<<3, z<<3, 1.0, 63));\n  }\n\n  // Get the actual data in the chest and dump it to the player\n  chestDataPtr _chestData;\n  for (uint32_t i = 0; i < chunk->chests.size(); i++)\n  {\n    if ((chunk->chests[i]->x() == x)\n      && (chunk->chests[i]->y() == y)\n      && (chunk->chests[i]->z() == z) )\n    {\n      _chestData = chunk->chests[i];\n      break;\n    }\n  }\n  if(_chestData != NULL)\n  {\n    std::string windowName = _chestData->large() ? \"Large chest\" : \"Chest\";\n\n    user->writePacket(Protocol::openWindow(type,INVENTORYTYPE_CHEST,\"{\\\"text\\\": \\\"\"+json_esc(windowName)+\"\\\"}\", _chestData->large()?54:27));\n\n    uint32_t chestSlots = _chestData->size() * (_chestData->large() ? 2: 1);\n\n    for (size_t j = 0; j < chestSlots; j++)\n    {\n      ItemPtr tmpItem;\n      if (_chestData->large()) {\n        if (j < 27) {\n          tmpItem = _chestData->getTop() ? (*_chestData->items())[j] : (*_chestData->getConnectedData()->items())[j];\n        } else {\n          tmpItem = _chestData->getTop() ? (*_chestData->getConnectedData()->items())[j-27] : (*_chestData->items())[j-27];\n        }\n      }\n      else\n      {\n        tmpItem = (*_chestData->items())[j];\n      }\n\n      // Send all non-empty slots\n      if (tmpItem->getType() != -1)\n      {\n        user->writePacket(Protocol::setSlot(type, j, *tmpItem));\n      }\n    }\n  }\n\n  return true;\n}\n\nbool InventoryChest::onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory()->openChests;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    // Find this chest\n    if (inv[i]->x == user->openInv.x &&\n        inv[i]->y == user->openInv.y &&\n        inv[i]->z == user->openInv.z)\n    {\n      // Find this user\n      for (size_t j = 0; j < inv[i]->users.size(); ++j)\n      {\n        if (inv[i]->users[j] == user)\n        {\n          // We should make users into a container that supports fast erase.\n          inv[i]->users.erase(inv[i]->users.begin() + j);\n\n          if (inv[i]->users.empty())\n          {\n            user->sendAll(Protocol::blockAction(x,y,z,1,0,BLOCK_CHEST));\n            user->sendAll(Protocol::namedSoundEffect(\"random.chestclosed\", x<<3, y<<3, z<<3, 1.0, 63));\n            inv.erase(inv.begin() + i);\n          }\n\n          user->isOpenInv = false;\n          return true;\n        }\n      }\n      break;\n    }\n  }\n\n  user->isOpenInv = false;\n  return true;\n}"
  },
  {
    "path": "src/inventory/inventoryChest.h",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include <stdint.h>\n#include <string>\n#include \"inventorybasic.h\"\n#include \"constants_num.h\"\n#include \"inventory.h\"\n\nclass User;\n\n/**\n * InventoryChest handles normal and large chests \n */\nclass InventoryChest :  public InventoryBasic\n{\npublic:\n  bool affected(int window_id) const { return window_id == WINDOW_CHEST || window_id == WINDOW_LARGE_CHEST; };\n  bool onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode = 0);\n  bool onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n  bool onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n};\n"
  },
  {
    "path": "src/inventory/inventoryFurnace.cpp",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdint.h>\n#include <string>\n#include \"inventoryFurnace.h\"\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"protocol.h\"\n#include \"map.h\"\n#include \"furnaceManager.h\"\n\nbool InventoryFurnace::onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber,\n                                     int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n  // Safeguard against overflow\n  if (slot > MAX_SLOT_FURNACE) return false;\n  if (slot != -999 && slot < 0) return false;\n\n  Inventory* inventory = ServerInstance->inventory();\n  //Ack\n  if(actionNumber)\n  {\n    // ToDo: actually check the action before ack\n    user->writePacket(Protocol::confirmTransaction(windowID, actionNumber, 1));\n  }\n\n  // Handle drag mode in a base class helper function\n  if (mode == INVENTORY_MODE_DRAG)\n  {\n    return this->handleDrag(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n  else if (mode == INVENTORY_MODE_NUMBER)\n  {\n    return this->handleNumber(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n  user->openInv.recordAction = false;\n\n  //Click outside the window\n  if (slot == -999)\n  {\n    //Dropping outside of the window\n    if(button == 0 && mode == 0 && user->inventoryHolding.getType() != -1)\n    {\n      ServerInstance->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,\n          user->inventoryHolding.getType(), user->inventoryHolding.getCount(),\n          user->inventoryHolding.getHealth(), user);\n      user->inventoryHolding.setType(-1);\n      return true;\n    }\n    return true;\n  }\n  //on click-and-drag mode, recording the slots used\n  else if(user->openInv.recordAction)\n  {\n    if(mode == 5)\n    {\n      user->openInv.slotActions.push_back(slot);\n    }\n    else\n    {\n      user->openInv.recordAction = false;\n    }\n    return true;\n  }\n\n  if (!user->isOpenInv && windowID != 0)\n  {\n    return false;\n  }\n\n  sChunk* chunk = NULL;\n  chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(user->openInv.x), blockToChunk(user->openInv.z));\n\n  if (chunk == NULL)\n  {\n    return false;\n  }\n  chunk->changed = true;\n\n  std::vector<User*>* otherUsers = NULL;\n  OpenInvPtr currentInventory;\n  std::vector<OpenInvPtr>& inv = inventory->openFurnaces;\n\n  for (size_t i = 0; i < inv.size(); i++)\n  {\n    if (inv[i]->x == user->openInv.x &&\n        inv[i]->y == user->openInv.y &&\n        inv[i]->z == user->openInv.z)\n    {\n      otherUsers = &inv[i]->users;\n      currentInventory = inv[i];\n      break;\n    }\n  }\n\n  if (otherUsers == NULL || currentInventory == NULL)\n  {\n    return false;\n  }\n\n\n  Item* slotItem = NULL;\n  furnaceDataPtr tempFurnace;\n\n  if (slot >= 3)\n  {\n    slotItem = &user->inv[slot + 6];\n  }\n  else\n  {\n    for (uint32_t i = 0; i < chunk->furnaces.size(); i ++)\n    {\n      if (chunk->furnaces[i]->x == user->openInv.x &&\n          chunk->furnaces[i]->y == user->openInv.y &&\n          chunk->furnaces[i]->z == user->openInv.z)\n      {\n        slotItem = &chunk->furnaces[i]->items[slot];\n        tempFurnace = chunk->furnaces[i];\n      }\n    }\n    //Create furnace data if it doesn't exist\n    if (slotItem == NULL)\n    {\n      furnaceDataPtr newFurnace(new furnaceData);\n      newFurnace->x = user->openInv.x;\n      newFurnace->y = user->openInv.y;\n      newFurnace->z = user->openInv.z;\n      newFurnace->burnTime = 0;\n      newFurnace->cookTime = 0;\n      chunk->furnaces.push_back(newFurnace);\n      slotItem = &newFurnace->items[slot];\n      tempFurnace = newFurnace;\n    }\n  }\n\n\n  //Empty slot and holding something\n  if ((slotItem->getType() == -1 || (slotItem->getType() == user->inventoryHolding.getType() && slotItem->getHealth() == user->inventoryHolding.getHealth() && slotItem->getCount() < 64)) && user->inventoryHolding.getType() != -1)\n  {\n    //ToDo: Make sure we have room for the items!\n    int16_t addCount = (64 - slotItem->getCount() >= user->inventoryHolding.getCount()) ? user->inventoryHolding.getCount() : 64 - slotItem->getCount();\n\n    slotItem->decCount(0 - ((button) ? 1 : addCount));\n    slotItem->setHealth(user->inventoryHolding.getHealth());\n    slotItem->setType(user->inventoryHolding.getType());\n\n    user->inventoryHolding.decCount((button) ? 1 : addCount);\n\n  }\n  //We are not holding anything, get the item we clicked\n  else if (user->inventoryHolding.getType() == -1)\n  {\n    //Shift+click -> items to player inv\n    //ToDo: from player inventory to chest\n    if(!button && mode && inventory->isSpace(user, slotItem->getType(), slotItem->getCount()))\n    {\n      inventory->addItems(user, slotItem->getType(), slotItem->getCount(), slotItem->getHealth());\n      slotItem->setCount(0);\n    }\n    else\n    {\n      user->inventoryHolding.setType(slotItem->getType());\n      user->inventoryHolding.setHealth(slotItem->getHealth());\n      user->inventoryHolding.setCount(slotItem->getCount());\n      if (button == 1)\n      {\n        user->inventoryHolding.decCount(slotItem->getCount() >> 1);\n      }\n      slotItem->decCount(user->inventoryHolding.getCount());\n    }\n      \n    if (slotItem->getCount() == 0)\n    {\n      slotItem->setHealth(0);\n      slotItem->setType(-1);\n    }\n  }\n  else\n  {\n    //Swap items if holding something and clicking another, not with craft slot\n    int16_t type = slotItem->getType();\n    int8_t count = slotItem->getCount();\n    int16_t health = slotItem->getHealth();\n    slotItem->setType(user->inventoryHolding.getType());\n    slotItem->setCount(user->inventoryHolding.getCount());\n    slotItem->setHealth(user->inventoryHolding.getHealth());\n    user->inventoryHolding.setType(type);\n    user->inventoryHolding.setCount(count);\n    user->inventoryHolding.setHealth(health);\n  }\n\n  //Update slot\n  inventory->setSlot(user, windowID, slot, slotItem);\n\n  //Update item on the cursor\n  inventory->setSlot(user, WINDOW_CURSOR, 0, &user->inventoryHolding);\n\n  //If handling the \"fuel\" slot\n  if ((slot == 1 || slot == 0))\n  {\n    tempFurnace->map = user->pos.map;\n    ServerInstance->furnaceManager()->handleActivity(tempFurnace);\n  }\n  \n  // If touching the furnace slots, update to everyone that has the furnace inventory open\n  if(slot < 3)\n  {\n    for(uint32_t i = 0; i < otherUsers->size(); i++)\n    {\n      if((*otherUsers)[i] != user)\n      {\n        inventory->setSlot((*otherUsers)[i], windowID, slot, slotItem);\n      }\n    }\n  }\n\n  return true;\n}\n\nbool InventoryFurnace::onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{  \n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory()->openFurnaces;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      inv[i]->users.push_back(user);\n      user->isOpenInv = true;\n      user->openInv = *inv[i];\n      break;\n    }\n  }\n\n  if (!user->isOpenInv)\n  {\n    //If the inventory not yet opened, create it\n    OpenInvPtr newInv(new OpenInventory());\n    newInv->type = type;\n    newInv->x    = x;\n    newInv->y    = y;\n    newInv->z    = z;\n    user->openInv = *newInv;\n\n    newInv->users.push_back(user);\n\n    inv.push_back(newInv);\n    user->isOpenInv = true;\n  }\n\n  user->writePacket(Protocol::openWindow(WINDOW_FURNACE,INVENTORYTYPE_FURNACE,\"{\\\"text\\\": \\\"\"+json_esc(\"Furnace\")+\"\\\"}\", 3));\n\n  sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(x), blockToChunk(z));\n\n  for (uint32_t i = 0; i < chunk->furnaces.size(); i++)\n  {\n    if (chunk->furnaces[i]->x == x && chunk->furnaces[i]->y == y && chunk->furnaces[i]->z == z)\n    {\n      std::vector<Item> slots;\n      for (int j = 0; j < 3; j++)\n      {        \n        slots.push_back(chunk->furnaces[i]->items[j]);\n      }\n      user->writePacket(Protocol::windowItems(WINDOW_FURNACE, slots));\n\n      user->writePacket(Protocol::windowProperty(WINDOW_FURNACE, 0,  chunk->furnaces[i]->burnTime>10?200: (chunk->furnaces[i]->burnTime * 20)));\n      user->writePacket(Protocol::windowProperty(WINDOW_FURNACE, 3, 200));\n      user->writePacket(Protocol::windowProperty(WINDOW_FURNACE, 2, (chunk->furnaces[i]->cookTime * 20)));\n      break;\n    }\n  }\n\n  return true;\n}\n\nbool InventoryFurnace::onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory()->openFurnaces;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      for (size_t j = 0; j < inv[i]->users.size(); ++j)\n      {\n        if (inv[i]->users[j] == user)\n        {\n          // We should make users into a container that supports fast erase.\n          inv[i]->users.erase(inv[i]->users.begin() + j);\n          break;\n        }\n      }\n      if (inv[i]->users.empty())\n      {\n        inv.erase(inv.begin()+i);\n      }\n      break;\n    }\n  }\n\n  user->isOpenInv = false;\n  return true;\n}"
  },
  {
    "path": "src/inventory/inventoryFurnace.h",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include <stdint.h>\n#include <string>\n#include \"inventorybasic.h\"\n#include \"constants_num.h\"\n#include \"inventory.h\"\n\nclass User;\n\n/**\n * InventoryFurnce handles all the furnaces\n */\nclass InventoryFurnace :  public InventoryBasic\n{\npublic:\n  bool affected(int window_id) const { return window_id == WINDOW_FURNACE; };\n  bool onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode = 0);\n  bool onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n  bool onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n};\n"
  },
  {
    "path": "src/inventory/inventoryPlayer.cpp",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdint.h>\n#include <string>\n#include \"inventoryPlayer.h\"\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"protocol.h\"\n#include \"map.h\"\n\n\nbool InventoryPlayer::onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button,int16_t actionNumber,\n                                   int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n  Inventory* inventory = ServerInstance->inventory();\n\n  // Safeguard against overflow\n  if (slot > MAX_SLOT_PLAYER) return false;\n  if (slot != -999 && slot < 0) return false;\n\n  //Ack\n  if(actionNumber)\n  {\n    // ToDo: actually check the action before ack\n    user->writePacket(Protocol::confirmTransaction(windowID, actionNumber, 1));\n  }\n\n  // Handle drag mode in a base class helper function\n  if (mode == INVENTORY_MODE_DRAG)\n  {\n    return this->handleDrag(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n  else if (mode == INVENTORY_MODE_NUMBER)\n  {\n    return this->handleNumber(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n  user->openInv.recordAction = false;\n\n  //Click outside the window\n  if (slot == -999)\n  {\n    //Dropping outside of the window\n    if(button == 0 && mode == 0 && user->inventoryHolding.getType() != -1)\n    {\n      ServerInstance->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,\n          user->inventoryHolding.getType(), user->inventoryHolding.getCount(),\n          user->inventoryHolding.getHealth(), user);\n      user->inventoryHolding.setType(-1);\n      return true;\n    }\n    return true;\n  }\n\n  if (!user->isOpenInv && windowID != 0)\n  {\n    return false;\n  }\n\n  Item* slotItem = &user->inv[slot];\n\n\n  bool workbenchCrafting = false;\n  bool playerCrafting    = false;\n\n  if (slot >= 5 && slot <= 8)\n  {\n    // Armour slots are a strange case. Only a quantity of one should be allowed, so this must be checked for.\n    if (slotItem->getType() == -1 && user->inventoryHolding.getType() > 0)\n    {\n      if (inventory->canBeArmour(slot, user->inventoryHolding.getType()))\n      {\n        slotItem->setType(user->inventoryHolding.getType());\n        slotItem->setHealth(user->inventoryHolding.getHealth());\n        slotItem->setCount(1);\n        user->inventoryHolding.decCount();\n      }\n      else\n      {\n        slotItem->decCount(0);\n        user->inventoryHolding.decCount(0); // Refresh both\n      }\n    }\n    else if (slotItem->getType() > 0 && user->inventoryHolding.getType() == -1)\n    {\n      user->inventoryHolding.setType(slotItem->getType());\n      user->inventoryHolding.setCount(slotItem->getCount());\n      user->inventoryHolding.setHealth(slotItem->getHealth());\n      slotItem->setType(-1);\n\n    }\n    else if (slotItem->getType() > 0 && user->inventoryHolding.getType() > 0 && user->inventoryHolding.getCount() == 1)\n    {\n      if (inventory->canBeArmour(slot, user->inventoryHolding.getType()))\n      {\n        uint16_t t_type = slotItem->getType();\n        uint8_t t_count = slotItem->getCount();\n        uint16_t t_health = slotItem->getHealth();\n        slotItem->setCount(1);\n        slotItem->setHealth(user->inventoryHolding.getHealth());\n        slotItem->setType(user->inventoryHolding.getType());\n        user->inventoryHolding.setCount(t_count);\n        user->inventoryHolding.setHealth(t_health);\n        user->inventoryHolding.setType(t_type);\n      }\n      else\n      {\n        slotItem->decCount(0);\n        user->inventoryHolding.decCount(0); // Refresh both\n      }\n    }\n    inventory->setSlot(user, WINDOW_CURSOR, 0, &user->inventoryHolding);\n    return false;\n  }\n\n\n  //Empty slot and holding something\n  if ((slotItem->getType() == -1 || (slotItem->getType() == user->inventoryHolding.getType() && slotItem->getHealth() == user->inventoryHolding.getHealth() && slotItem->getCount() < 64)) && user->inventoryHolding.getType() != -1)\n  {\n    //If accessing crafting output slot\n    if (slotItem->getType() != -1 && slot == 0)\n    {\n      if (user->inventoryHolding.getType() == slotItem->getType() && 64 - user->inventoryHolding.getCount() >= slotItem->getCount())\n      {\n        user->inventoryHolding.decCount(-slotItem->getCount());\n\n        for (uint8_t playerSlot = 1; playerSlot < 5; playerSlot++)\n        {\n          if (user->inv[playerSlot].getType() != -1)\n          {\n            user->inv[playerSlot].decCount();\n            inventory->setSlot(user, windowID, playerSlot, &user->inv[playerSlot]);\n          }\n        }\n        playerCrafting = true;\n\n      }\n    }\n    else\n    {\n      //ToDo: Make sure we have room for the items!\n\n      //Make sure not putting anything to the crafting space\n      if (slot != 0)\n      {\n        int16_t addCount = (64 - slotItem->getCount() >= user->inventoryHolding.getCount()) ? user->inventoryHolding.getCount() : 64 - slotItem->getCount();\n\n        slotItem->decCount(0 - ((button) ? 1 : addCount));\n        slotItem->setHealth(user->inventoryHolding.getHealth());\n        slotItem->setType(user->inventoryHolding.getType());\n\n        user->inventoryHolding.decCount((button) ? 1 : addCount);\n      }\n    }\n\n  }\n  //We are not holding anything, get the item we clicked\n  else if (user->inventoryHolding.getType() == -1)\n  {\n    //If accessing crafting output slot, remove from input!\n    if (slotItem->getType() != -1 && slot == 0)\n    {\n      user->inventoryHolding.setType(slotItem->getType());\n      user->inventoryHolding.setCount(slotItem->getCount());\n      user->inventoryHolding.setHealth(slotItem->getHealth());\n\n      for (uint8_t playerSlot = 1; playerSlot < 5; playerSlot++)\n      {\n        if (user->inv[playerSlot].getType() != -1)\n        {\n          user->inv[playerSlot].decCount();\n        }\n      }\n      playerCrafting = true;\n\n    }\n    else\n    {\n      //Shift+click -> items to player inv\n      //ToDo: from player inventory to chest\n      if(!button && mode && inventory->isSpace(user, slotItem->getType(), slotItem->getCount()))\n      {\n        inventory->addItems(user, slotItem->getType(), slotItem->getCount(), slotItem->getHealth());\n        slotItem->setCount(0);\n      }\n      else\n      {\n        user->inventoryHolding.setType(slotItem->getType());\n        user->inventoryHolding.setHealth(slotItem->getHealth());\n        user->inventoryHolding.setCount(slotItem->getCount());\n        if (button == 1)\n        {\n          user->inventoryHolding.decCount(slotItem->getCount() >> 1);\n        }\n        slotItem->decCount(user->inventoryHolding.getCount());\n      }\n      \n      if (slotItem->getCount() == 0)\n      {\n        slotItem->setHealth(0);\n        slotItem->setType(-1);\n      }\n    }\n  }\n  else\n  {\n    //Swap items if holding something and clicking another, not with craft slot\n    if (slot != 0)\n    {\n      int16_t type = slotItem->getType();\n      int8_t count = slotItem->getCount();\n      int16_t health = slotItem->getHealth();\n      slotItem->setType(user->inventoryHolding.getType());\n      slotItem->setCount(user->inventoryHolding.getCount());\n      slotItem->setHealth(user->inventoryHolding.getHealth());\n      user->inventoryHolding.setType(type);\n      user->inventoryHolding.setCount(count);\n      user->inventoryHolding.setHealth(health);\n    }\n  }\n\n  //Update slot\n  inventory->setSlot(user, windowID, slot, slotItem);\n\n  //Update item on the cursor\n  inventory->setSlot(user, WINDOW_CURSOR, 0, &user->inventoryHolding);\n\n\n  //Check if crafting\n  if ((slot < 5 && slot > 0) || playerCrafting)\n  {\n    if (inventory->doCraft(user->inv, 2, 2))\n    {\n      inventory->setSlot(user, windowID, 0, &user->inv[0]);\n    }\n    else\n    {\n      Item temp(0, -1);\n      user->inv[0].setType(-1);\n      inventory->setSlot(user, windowID, 0, &temp);\n    }\n  }\n\n  return true;\n}\n\nbool InventoryPlayer::onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  // We don't get info of player opening own inventory\n\n  return true;\n}\n\nbool InventoryPlayer::onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  // We don't get info of player closing own inventory\n\n   return true;\n}"
  },
  {
    "path": "src/inventory/inventoryPlayer.h",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include <stdint.h>\n#include <string>\n#include \"inventorybasic.h\"\n#include \"constants_num.h\"\n#include \"inventory.h\"\n\nclass User;\n\n\n/**\n * InventoryPlayer handles player inventory actions\n */\nclass InventoryPlayer :  public InventoryBasic\n{\npublic:\n  bool affected(int window_id) const { return window_id == WINDOW_PLAYER; };\n  bool onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode = 0);\n  bool onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n  bool onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n};\n"
  },
  {
    "path": "src/inventory/inventoryWorkbench.cpp",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <stdint.h>\n#include <string>\n#include \"inventoryWorkbench.h\"\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"protocol.h\"\n#include \"map.h\"\n\nbool InventoryWorkbench::onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, \n                                      int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n\n  // Safeguard against overflow\n  if (slot > MAX_SLOT_CRAFTING_TABLE) return false;\n  if (slot != -999 && slot < 0) return false;\n\n  Inventory* inventory = ServerInstance->inventory();\n  //Ack\n  if(actionNumber)\n  {\n    // ToDo: actually check the action before ack\n    user->writePacket(Protocol::confirmTransaction(windowID, actionNumber, 1));\n  }\n\n  // Handle drag mode in a base class helper function\n  if (mode == INVENTORY_MODE_DRAG)\n  {\n    return this->handleDrag(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n  else if (mode == INVENTORY_MODE_NUMBER)\n  {\n    return this->handleNumber(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode);\n  }\n  user->openInv.recordAction = false;\n\n  //Click outside the window\n  if (slot == -999)\n  {\n    //Dropping outside of the window\n    if(button == 0 && mode == 0 && user->inventoryHolding.getType() != -1)\n    {\n      ServerInstance->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,\n          user->inventoryHolding.getType(), user->inventoryHolding.getCount(),\n          user->inventoryHolding.getHealth(), user);\n      user->inventoryHolding.setType(-1);\n      return true;\n    }\n    return true;\n  }\n  //on click-and-drag mode, recording the slots used\n  else if(user->openInv.recordAction)\n  {\n    if(mode == 5)\n    {\n      user->openInv.slotActions.push_back(slot);\n    }\n    else\n    {\n      user->openInv.recordAction = false;\n    }\n    return true;\n  }\n\n  if (!user->isOpenInv && windowID != 0)\n  {\n    return false;\n  }\n\n  sChunk* chunk = NULL;\n  chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(user->openInv.x), blockToChunk(user->openInv.z));\n\n  if (chunk == NULL)\n  {\n    return false;\n  }\n\n  chunk->changed = true;\n\n\n  std::vector<User*>* otherUsers = NULL;\n  OpenInvPtr currentInventory;\n  std::vector<OpenInvPtr>& inv = inventory->openWorkbenches;\n\n  for (size_t i = 0; i < inv.size(); i++)\n  {\n    if (inv[i]->x == user->openInv.x &&\n        inv[i]->y == user->openInv.y &&\n        inv[i]->z == user->openInv.z)\n    {\n      otherUsers = &inv[i]->users;\n      currentInventory = inv[i];\n      break;\n    }\n  }\n\n  if (otherUsers == NULL || currentInventory == NULL)\n  {\n    return false;\n  }\n\n\n  Item* slotItem = NULL;\n\n  if (slot > 9)\n  {\n    slotItem = &user->inv[slot - 1];\n  }\n  else\n  {\n    slotItem = &currentInventory->workbench[slot];\n  }\n\n\n  bool workbenchCrafting = false;\n  \n  //Empty slot and holding something\n  if ((slotItem->getType() == -1 || (slotItem->getType() == user->inventoryHolding.getType() && slotItem->getHealth() == user->inventoryHolding.getHealth() && slotItem->getCount() < 64)) && user->inventoryHolding.getType() != -1)\n  {\n    //If accessing crafting output slot\n    if (slotItem->getType() != -1 && slot == 0)\n    {\n      if (user->inventoryHolding.getType() == slotItem->getType() && 64 - user->inventoryHolding.getCount() >= slotItem->getCount())\n      {\n        user->inventoryHolding.decCount(-slotItem->getCount());\n\n        for (uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)\n        {\n          if (currentInventory->workbench[workbenchSlot].getType() != -1)\n          {\n            currentInventory->workbench[workbenchSlot].decCount();\n            inventory->setSlot(user, windowID, workbenchSlot, &currentInventory->workbench[workbenchSlot]);\n          }\n        }\n        workbenchCrafting = true;\n\n      }\n    }\n    else\n    {\n      //ToDo: Make sure we have room for the items!\n\n      //Make sure not putting anything to the crafting space\n      if (slot != 0)\n      {\n        int16_t addCount = (64 - slotItem->getCount() >= user->inventoryHolding.getCount()) ? user->inventoryHolding.getCount() : 64 - slotItem->getCount();\n\n        slotItem->decCount(0 - ((button) ? 1 : addCount));\n        slotItem->setHealth(user->inventoryHolding.getHealth());\n        slotItem->setType(user->inventoryHolding.getType());\n\n        user->inventoryHolding.decCount((button) ? 1 : addCount);\n      }\n    }\n\n  }\n  //We are not holding anything, get the item we clicked\n  else if (user->inventoryHolding.getType() == -1)\n  {\n    //If accessing crafting output slot, remove from input!\n    if (slotItem->getType() != -1 && slot == 0)\n    {\n      user->inventoryHolding.setType(slotItem->getType());\n      user->inventoryHolding.setCount(slotItem->getCount());\n      user->inventoryHolding.setHealth(slotItem->getHealth());\n\n      for (uint8_t workbenchSlot = 1; workbenchSlot < 10; workbenchSlot++)\n      {\n        if (currentInventory->workbench[workbenchSlot].getType() != -1)\n        {\n          currentInventory->workbench[workbenchSlot].decCount();\n\n          inventory->setSlot(user, windowID, workbenchSlot, &currentInventory->workbench[workbenchSlot]);\n        }\n      }\n      workbenchCrafting = true;\n\n      \n    }\n    else\n    {\n\n      //Shift+click -> items to player inv\n      //ToDo: from player inventory to chest\n      if(!button && mode &&inventory-> isSpace(user, slotItem->getType(), slotItem->getCount()))\n      {\n        inventory->addItems(user, slotItem->getType(), slotItem->getCount(), slotItem->getHealth());\n        slotItem->setCount(0);\n      }\n      else\n      {\n        user->inventoryHolding.setType(slotItem->getType());\n        user->inventoryHolding.setHealth(slotItem->getHealth());\n        user->inventoryHolding.setCount(slotItem->getCount());\n        if (button == 1)\n        {\n          user->inventoryHolding.decCount(slotItem->getCount() >> 1);\n        }\n        slotItem->decCount(user->inventoryHolding.getCount());\n      }\n      \n      if (slotItem->getCount() == 0)\n      {\n        slotItem->setHealth(0);\n        slotItem->setType(-1);\n      }\n    }\n  }\n  else\n  {\n    //Swap items if holding something and clicking another, not with craft slot\n    if (slot != 0)\n    {\n      int16_t type = slotItem->getType();\n      int8_t count = slotItem->getCount();\n      int16_t health = slotItem->getHealth();\n      slotItem->setType(user->inventoryHolding.getType());\n      slotItem->setCount(user->inventoryHolding.getCount());\n      slotItem->setHealth(user->inventoryHolding.getHealth());\n      user->inventoryHolding.setType(type);\n      user->inventoryHolding.setCount(count);\n      user->inventoryHolding.setHealth(health);\n    }\n  }\n\n  //Update slot\n  inventory->setSlot(user, windowID, slot, slotItem);\n\n  //Update item on the cursor\n  inventory->setSlot(user, WINDOW_CURSOR, 0, &user->inventoryHolding);\n\n\n  //Check if crafting\n  if (inventory->doCraft(currentInventory->workbench, 3, 3))\n  {\n    inventory->setSlot(user, windowID, 0, &currentInventory->workbench[0]);\n  }\n  else\n  {\n    Item temp(0, -1);\n    currentInventory->workbench[0].setType(-1);\n    inventory->setSlot(user, windowID, 0, &temp);\n  }\n\n  \n  //Signal others using the same space\n  if(slot < 10)\n  {\n    for(uint32_t i = 0; i < otherUsers->size(); i++)\n    {\n      if((*otherUsers)[i] != user)\n      {\n        inventory->setSlot((*otherUsers)[i], windowID, slot, slotItem);\n      }\n    }\n  }\n\n  return true;\n}\n\n\nbool InventoryWorkbench::onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory()->openWorkbenches;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      inv[i]->users.push_back(user);\n      user->isOpenInv = true;\n      user->openInv = *inv[i];\n      break;\n    }\n  }\n\n  if (!user->isOpenInv)\n  {\n    //If the inventory not yet opened, create it\n    OpenInvPtr newInv(new OpenInventory());\n    newInv->type = type;\n    newInv->x    = x;\n    newInv->y    = y;\n    newInv->z    = z;\n    user->openInv = *newInv;\n\n    newInv->users.push_back(user);\n\n    inv.push_back(newInv);\n    user->isOpenInv = true;\n  }\n\n  user->writePacket(Protocol::openWindow(WINDOW_CRAFTING_TABLE,INVENTORYTYPE_CRAFTING_TABLE,\"{\\\"text\\\": \\\"\"+json_esc(\"Workbench\")+\"\\\"}\", 0));\n\n  // ToDo: option for shared workbenches\n  for (uint32_t i = 0; i < inv.size(); i++)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      for (int j = 0; j < 10; j++)\n      {\n        if (inv[i]->workbench[j].getType() != -1)\n        {\n          user->writePacket(Protocol::setSlot(WINDOW_CRAFTING_TABLE, j, inv[i]->workbench[j]));\n        }\n      }\n      break;\n    }\n  }\n\n  return true;\n}\n\nbool InventoryWorkbench::onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const\n{\n  std::vector<OpenInvPtr>& inv = ServerInstance->inventory()->openWorkbenches;\n\n  for (size_t i = 0; i < inv.size(); ++i)\n  {\n    if (inv[i]->x == x &&\n        inv[i]->y == y &&\n        inv[i]->z == z)\n    {\n      for (size_t j = 0; j < inv[i]->users.size(); ++j)\n      {\n        if (inv[i]->users[j] == user)\n        {\n          // We should make users into a container that supports fast erase.\n          inv[i]->users.erase(inv[i]->users.begin() + j);\n\n          if (inv[i]->users.empty())\n          {\n            //Dump stuff to ground if no other users\n\n            for (uint32_t slotNumber = 1; slotNumber < 10; ++slotNumber)\n            {\n              if (inv[i]->workbench[slotNumber].getType() != -1)\n              {\n                ServerInstance->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,\n                    inv[i]->workbench[slotNumber].getType(), inv[i]->workbench[slotNumber].getCount(),\n                    inv[i]->workbench[slotNumber].getHealth(), user);\n              }\n            }\n\n            inv.erase(inv.begin() + i);\n          }\n\n          user->isOpenInv = false;\n          return true;\n        }\n      }\n      break;\n    }\n  }\n\n  user->isOpenInv = false;\n  return true;\n}"
  },
  {
    "path": "src/inventory/inventoryWorkbench.h",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include <stdint.h>\n#include <string>\n#include \"inventorybasic.h\"\n#include \"constants_num.h\"\n#include \"inventory.h\"\n\nclass User;\n\n/**\n * InventoryChest handles normal and large chests \n */\nclass InventoryWorkbench :  public InventoryBasic\n{\npublic:\n  bool affected(int window_id) const { return window_id == WINDOW_CRAFTING_TABLE; };\n  bool onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode = 0);\n  bool onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n  bool onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const;\n};\n"
  },
  {
    "path": "src/inventory/inventorybasic.h",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include <stdint.h>\n#include <string>\n\nclass User;\n\n\n/**\n * InventoryBasic is used as a base class for inventory actions for player, chest etc\n * methods are pure virtual\n */\nclass InventoryBasic\n{\npublic:\n  virtual ~InventoryBasic() { }\n  virtual bool affected(int window_id) const = 0;\n  virtual bool onwindowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode = 0) = 0;\n  virtual bool onwindowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const = 0;\n  virtual bool onwindowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z) const = 0;\n\n  virtual bool handleDrag(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode);\n  virtual bool handleNumber(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode);\n};\n"
  },
  {
    "path": "src/inventory.cpp",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n\n#include <fstream>\n#include <stdio.h>\n#include <stdlib.h>\n\n#include \"inventory.h\"\n#include \"protocol.h\"\n#include \"constants.h\"\n#include \"map.h\"\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"furnaceManager.h\"\n#include \"logger.h\"\n#include \"plugin.h\"\n#include <sstream>\n\n\nvoid Item::sendUpdate()\n{\n  if (player != NULL && ready)\n  {\n    if (slot == player->curItem + 36)\n    {\n      Packet pkt = Protocol::entityEquipment(player->UID, 0, *this);\n      player->sendOthers(pkt);\n    }\n    if (slot >= 5 && slot <= 8)\n    {\n      Packet pkt = Protocol::entityEquipment(player->UID,(5 - (slot - 4)), *this);\n      player->sendOthers(pkt);\n    }\n    \n    int window = 0;\n    int t_slot = slot;\n    if (slot == -1)\n    {\n      window = -1;\n      t_slot = 0;\n    }\n    player->writePacket(Protocol::setSlot(window, t_slot, *this));\n  }\n  // Cases where we're changing items in chests, furnaces etc?\n}\n\nvoid Item::setType(int16_t type)\n{\n  this->type = type;\n  if (type == -1)\n  {\n    count = 0;\n    health = 0;\n  }\n\n  sendUpdate();\n}\n\nvoid Item::setCount(int8_t count)\n{\n  this->count = count;\n  if (count < 1)\n  {\n    setType(-1);\n    return;\n  }\n  sendUpdate();\n}\n\nvoid Item::setData(NBT_Value* _data)\n{\n  if (data) delete data;\n  data = _data;\n}\n\nvoid Item::setHealth(int16_t health)\n{\n  //bool rightUse;\n  if (health <= 0)\n  {\n    this->health = health;\n    return;\n  }\n  int healthMax = itemHealth(type);\n  if (health > healthMax && healthMax > 0)\n  {\n    type = -1;\n    count = 0;\n    this->health = 0;\n    sendUpdate();\n  }\n  else\n  {\n    this->health = health;\n    sendUpdate();\n  }\n}\n\nvoid Item::decCount(int c)\n{\n  count -= c;\n  if (count < 1)\n  {\n    setType(-1);\n    return;\n  }\n  sendUpdate();\n}\n\nvoid Item::incHealth(int c)\n{\n  int healthMax = itemHealth(type);\n  health += c;\n  if (health > healthMax && healthMax > 0)\n  {\n    setType(-1);\n  }\n  sendUpdate();\n}\n\nint16_t Item::itemHealth(int item)\n{\n  int16_t health = 0;\n  switch (type)\n  {\n  case ITEM_GOLD_AXE:\n  case ITEM_GOLD_PICKAXE:\n  case ITEM_GOLD_HOE:\n  case ITEM_GOLD_SPADE:\n  case ITEM_GOLD_SWORD:\n    health = 33;\n    break;\n  case ITEM_WOODEN_AXE:\n  case ITEM_WOODEN_PICKAXE:\n  case ITEM_WOODEN_HOE:\n  case ITEM_WOODEN_SPADE:\n  case ITEM_WOODEN_SWORD:\n    health = 60;\n    break;\n  case ITEM_STONE_AXE:\n  case ITEM_STONE_PICKAXE:\n  case ITEM_STONE_HOE:\n  case ITEM_STONE_SPADE:\n  case ITEM_STONE_SWORD:\n  case ITEM_BOW:\n    health = 132;\n    break;\n  case ITEM_IRON_AXE:\n  case ITEM_IRON_PICKAXE:\n  case ITEM_IRON_HOE:\n  case ITEM_IRON_SPADE:\n  case ITEM_IRON_SWORD:\n    health = 251;\n    break;\n  case ITEM_DIAMOND_AXE:\n  case ITEM_DIAMOND_PICKAXE:\n  case ITEM_DIAMOND_HOE:\n  case ITEM_DIAMOND_SPADE:\n  case ITEM_DIAMOND_SWORD:\n    health = 1562;\n    break;\n\n  default:\n    health = 0;\n  }\n  return health;\n}\n\n\nvoid Inventory::getEnabledRecipes(std::vector<std::string>& receiptFiles, const std::string& cfg)\n{\n  std::ifstream ifs(cfg.c_str());\n\n  if (ifs.fail())\n  {\n    ifs.close();\n    return;\n  }\n\n  std::string suffix = \".recipe\";\n  std::string temp;\n  std::string text;\n  while (getline(ifs, temp))\n  {\n    //If empty line\n    if (temp.size() == 0)\n    {\n      continue;\n    }\n\n    // If commentline -> skip to next\n    if (temp[0] == COMMENTPREFIX)\n    {\n      continue;\n    }\n\n    receiptFiles.push_back(temp + suffix);\n  }\n  ifs.close();\n}\n\nInventory::Inventory(const std::string& path, const std::string& suffix, const std::string& cfg)\n{\n  std::vector<std::string> receiptFiles;\n  getEnabledRecipes( receiptFiles, cfg);\n\n  for (unsigned int i = 0; i < receiptFiles.size(); i++)\n  {\n    readRecipe(path + '/' + receiptFiles[i]);\n  }\n}\n\nbool Inventory::addRecipe(int width, int height, std::vector<ItemPtr> inputrecipe, int outputCount, int16_t outputType, int16_t outputHealth)\n{\n  RecipePtr recipe(new Recipe);\n\n  recipe->width  = width;\n  recipe->height = height;\n  recipe->output.setCount(outputCount);\n  recipe->output.setType(outputType);\n  recipe->output.setHealth(outputHealth);\n  recipe->slots = inputrecipe;\n\n  recipes.push_back(recipe);\n\n  return true;\n}\n\nbool Inventory::readRecipe(const std::string& recipeFile)\n{\n  std::ifstream ifs(recipeFile.c_str());\n\n  if (ifs.fail())\n  {\n    LOG2(ERROR, \"Could not find: \" + recipeFile);\n    ifs.close();\n    return false;\n  }\n\n  //LOG(INFO, \"Inventory\", \"Reading: \" + recipeFile);\n\n  std::string temp;\n\n  int height = 0, width = 0, outCount = 0;\n  int16_t outType = 0, outHealth = 0;\n\n  // Reading row at a time\n  int del;\n  bool readingRecipe = false;\n  std::vector<std::string> line;\n  std::vector<ItemPtr> recipetable;\n  std::string text;\n  while (getline(ifs, temp))\n  {\n    //If empty line\n    if (temp.empty())\n    {\n      continue;\n    }\n\n    // If commentline -> skip to next\n    if (temp[0] == COMMENTPREFIX)\n    {\n      continue;\n    }\n\n    // Init vars\n    del = 0;\n    line.clear();\n\n    // Process line\n    while (!temp.empty())\n    {\n      // Remove white spaces\n      while (temp[0] == ' ')\n      {\n        temp = temp.substr(1);\n      }\n\n      // Split words\n      del = temp.find(' ');\n      if (del > -1)\n      {\n        line.push_back(temp.substr(0, del));\n        temp = temp.substr(del + 1);\n      }\n      else\n      {\n        line.push_back(temp);\n        break;\n      }\n    }\n\n    // Begin recipe\n    if (line.size() == 1 && line[0] == \"<-\")\n    {\n      readingRecipe = true;\n      continue;\n    }\n    // Begin recipe\n    if (line.size() == 1 && line[0] == \"->\")\n    {\n      readingRecipe = false;\n      continue;\n    }\n\n    if (readingRecipe)\n    {\n      for (unsigned int i = 0; i < line.size(); i++)\n      {\n        std::string data(line[i]);\n        ItemPtr item(new Item);\n        item->setCount(1);\n        item->setHealth(-1);\n        int location = data.find(\"x\");\n        if (location > -1)\n        {\n          // Quantity before ID\n          item->setCount(atoi(data.substr(0, location).c_str()));\n          data = data.substr(location + 1, std::string::npos);\n        }\n        location = data.find(\":\");\n        if (location > -1)\n        {\n          // Meta after ID\n          item->setHealth(atoi(data.substr(location + 1, std::string::npos).c_str()));\n          data = data.substr(0, location);\n        }\n        item->setType(atoi(data.c_str()));\n        recipetable.push_back(item);\n      }\n      continue;\n    }\n    else\n    {\n      // Keywords\n      if (line[0] == \"width\")\n      {\n        width = atoi(line[1].c_str());\n      }\n      if (line[0] == \"height\")\n      {\n        height = atoi(line[1].c_str());\n      }\n      if (line[0] == \"outputcount\")\n      {\n        outCount = atoi(line[1].c_str());\n      }\n      if (line[0] == \"outputtype\")\n      {\n        outType = atoi(line[1].c_str());\n      }\n      if (line[0] == \"outputhealth\")\n      {\n        outHealth = atoi(line[1].c_str());\n      }\n    }\n  }\n  ifs.close();\n\n  addRecipe(width, height, recipetable, outCount, outType, outHealth);\n\n  return true;\n}\n\nbool Inventory::canBeArmour(int slot, int type)\n{\n  if (slot == 5)\n  {\n    // Helmet slot. Lots of fun here\n    if (ServerInstance->m_only_helmets)\n    {\n      switch (type)\n      {\n      case ITEM_LEATHER_HELMET:\n      case ITEM_CHAINMAIL_HELMET:\n      case ITEM_IRON_HELMET:\n      case ITEM_DIAMOND_HELMET:\n      case ITEM_GOLD_HELMET:\n        return true;\n        break;\n      }\n      return false;\n    }\n    else\n    {\n      return true;\n    }\n  }\n  else if (slot == 6)\n  {\n    switch (type)\n    {\n    case ITEM_LEATHER_CHESTPLATE:\n    case ITEM_CHAINMAIL_CHESTPLATE:\n    case ITEM_IRON_CHESTPLATE:\n    case ITEM_DIAMOND_CHESTPLATE:\n    case ITEM_GOLD_CHESTPLATE:\n      return true;\n      break;\n    }\n    return false;\n  }\n  else if (slot == 7)\n  {\n    switch (type)\n    {\n    case ITEM_LEATHER_LEGGINGS:\n    case ITEM_CHAINMAIL_LEGGINGS:\n    case ITEM_IRON_LEGGINGS:\n    case ITEM_DIAMOND_LEGGINGS:\n    case ITEM_GOLD_LEGGINGS:\n      return true;\n      break;\n    }\n    return false;\n  }\n  else if (slot == 8)\n  {\n    switch (type)\n    {\n    case ITEM_LEATHER_BOOTS:\n    case ITEM_CHAINMAIL_BOOTS:\n    case ITEM_IRON_BOOTS:\n    case ITEM_DIAMOND_BOOTS:\n    case ITEM_GOLD_BOOTS:\n      return true;\n      break;\n    }\n    return false;\n  }\n  LOG2(WARNING, \"Unknown armour slot.\");\n  return false;\n}\n\n\nbool Inventory::windowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode)\n{\n  for (auto invCb : ServerInstance->plugin()->getInventoryCB())\n  {    \n    if (invCb != NULL && invCb->affected(windowID))\n    {\n      if (invCb->onwindowClick(user, windowID, slot, button, actionNumber, itemID, itemCount, itemUses, mode))\n      {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nbool Inventory::windowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z)\n{\n  for (auto invCb : ServerInstance->plugin()->getInventoryCB())\n  {    \n    if (invCb != NULL && invCb->affected(type))\n    {\n      if (invCb->onwindowClose(user, type, x, y, z))\n      {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nbool Inventory::windowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z)\n{\n  // Close inventory if one already open\n  if (user->isOpenInv)\n  {\n    windowClose(user, user->openInv.type, user->openInv.x, user->openInv.y, user->openInv.z);\n  }\n\n  for (auto invCb : ServerInstance->plugin()->getInventoryCB())\n  {    \n    if (invCb != NULL && invCb->affected(type))\n    {\n      if (invCb->onwindowOpen(user, type, x, y, z))\n      {\n        return true;\n      }\n    }\n  }\n\n  return false;\n}\n\nbool Inventory::isSpace(User* user, int16_t itemID, char count)\n{\n  int leftToFit = count;\n  for (uint8_t i = 0; i < 36; i++)\n  {\n    Item* slot = &user->inv[i + 9];\n    if (slot->getType() == -1)\n    {\n      return true;\n    }\n\n    if (slot->getType() == itemID)\n    {\n      if (64 - slot->getCount() >= leftToFit)\n      {\n        return true;\n      }\n      else if (64 - slot->getCount() > 0)\n      {\n        leftToFit -= 64 - slot->getCount();\n      }\n    }\n  }\n  return false;\n}\n\n\nbool Inventory::addItems(User* user, int16_t itemID, int16_t count, int16_t health)\n{\n  bool checkingTaskbar = true;\n  int checkdir=1;\n\n  //First loop and check if we can pile this up with existing blocks\n  for (uint8_t i = 36 - 9; i >= 9 || checkingTaskbar; i+=checkdir)\n  {\n    //First, the \"task bar\"\n    if (i == 36)\n    {\n      checkingTaskbar = false;\n      i = 35-9;\n      checkdir=-1;\n    }\n\n    //The main slots are in range 9-44\n    Item* slot = &user->inv[i + 9];\n\n    //If same item type\n    if (slot->getType() == itemID)\n    {\n      if (slot->getHealth() == health)\n      {\n        //Put to the stack\n        if (64 - slot->getCount() >= count)\n        {\n          slot->setType(itemID);\n          slot->decCount(-count);\n          count--;\n          break;\n        }\n        //Put some of the items to this stack and continue searching for space\n        else if (64 - slot->getCount() > 0)\n        {\n          slot->setType(itemID);\n          count -= 64 - slot->getCount();\n          slot->setCount(64);\n        }\n      }\n    }\n  }\n\n  checkdir=1;\n\n  //If more items\n  if(count)\n  {\n    //Check for empty slots\n    for (uint8_t i = 36 - 9; i >= 9 || checkingTaskbar; i+=checkdir)\n    {\n      //First, the \"task bar\"\n      if (i == 36)\n      {\n        checkingTaskbar = false;\n        i = 35-9;\n        checkdir=-1;\n      }\n\n      //The main slots are in range 9-44\n      Item* slot = &user->inv[i + 9];\n\n      //If slot empty, put item there\n      if (slot->getType() == -1)\n      {\n        slot->setType(itemID);\n        slot->setCount(int8_t(count));\n        slot->setHealth(health);\n        break;\n      }\n    }\n  }\n\n  return true;\n}\n\nbool Inventory::windowClose(User* user, int8_t windowID)\n{\n  //If still holding something, dump the items to ground\n  if (user->inventoryHolding.getType() != -1)\n  {\n    ServerInstance->map(user->pos.map)->createPickupSpawn((int)user->pos.x, (int)user->pos.y, (int)user->pos.z,\n        user->inventoryHolding.getType(), user->inventoryHolding.getCount(),\n        user->inventoryHolding.getHealth(), user);\n    user->inventoryHolding.setType(-1);\n  }\n\n  if (user->isOpenInv)\n  {\n    windowClose(user, user->openInv.type, user->openInv.x, user->openInv.y, user->openInv.z);\n  }\n\n  return true;\n}\n\nbool Inventory::doCraft(Item* slots, int8_t width, int8_t height)\n{\n  for (uint32_t i = 0; i < recipes.size(); i++)\n  {\n    //Skip if recipe doesn't fit\n    if (width < recipes[i]->width || height < recipes[i]->height)\n    {\n      continue;\n    }\n\n    int8_t offsetX = 0, offsetY = 0;\n\n    //Check for any possible position the recipe would fit\n    do\n    {\n      offsetX = 0;\n      do\n      {\n        bool mismatch = false;\n        //Check for the recipe match on this position\n        for (int32_t recipePosX = 0; recipePosX < recipes[i]->width; recipePosX++)\n        {\n          for (int32_t recipePosY = 0; recipePosY < recipes[i]->height; recipePosY++)\n          {\n            if (slots[(recipePosY + offsetY)*width + recipePosX + 1 + offsetX].getType() != recipes[i]->slots[recipePosY * recipes[i]->width + recipePosX]->getType())\n            {\n              mismatch = true;\n              break;\n            }\n            if (recipes[i]->slots[recipePosY * recipes[i]->width + recipePosX]->getHealth() != -1)\n            {\n              if (slots[(recipePosY + offsetY)*width + recipePosX + 1 + offsetX].getHealth() != recipes[i]->slots[recipePosY * recipes[i]->width + recipePosX]->getHealth())\n              {\n                mismatch = true;\n                break;\n              }\n            }\n            if (slots[(recipePosY + offsetY)*width + recipePosX + 1 + offsetX].getCount() < recipes[i]->slots[recipePosY * recipes[i]->width + recipePosX]->getCount())\n            {\n              mismatch = true;\n              break;\n            }\n          }\n        }\n\n        //Found match!\n        if (!mismatch)\n        {\n          //Check that other areas are empty!\n          bool foundItem = false;\n          for (int32_t craftingPosX = 0; craftingPosX < width; craftingPosX++)\n          {\n            for (int32_t craftingPosY = 0; craftingPosY < height; craftingPosY++)\n            {\n              //If not inside the recipe boundaries\n              if (craftingPosX < offsetX || craftingPosX >= offsetX + recipes[i]->width ||\n                  craftingPosY < offsetY || craftingPosY >= offsetY + recipes[i]->height)\n              {\n                if (slots[(craftingPosY)*width + craftingPosX + 1].getType() != -1)\n                {\n                  foundItem = true;\n                  break;\n                }\n              }\n            }\n          }\n          if (!foundItem)\n          {\n            slots[0] = recipes[i]->output;\n            return true;\n          }\n        }\n\n        offsetX++;\n      }\n      while (offsetX <= width - recipes[i]->width);\n\n      offsetY++;\n    }\n    while (offsetY <= height - recipes[i]->height);\n  }\n\n  return false;\n}\n\nbool Inventory::setSlot(User* user, int8_t windowID, int16_t slot, Item* item)\n{\n  user->writePacket(Protocol::setSlot(windowID, slot, *item));\n  return true;\n}\n\nbool Inventory::updateInventory(User* user, int8_t windowID)\n{\n   if(!this->onupdateinventory(user, windowID))\n      return false;\n   for(int i = 0; i < 44; i++)\n      user->inv[i].sendUpdate();\n   return true;\n}\n\nbool Inventory::onupdateinventory(User* user, int8_t windowID)\n{\n   return true;\n}\n\nint16_t Inventory::itemHealth(int16_t itemID, int8_t block, bool& rightUse)\n{\n  int16_t health = 0;\n  rightUse = false;\n  switch (itemID)\n  {\n  case ITEM_GOLD_AXE:\n  case ITEM_GOLD_PICKAXE:\n  case ITEM_GOLD_HOE:\n  case ITEM_GOLD_SPADE:\n    health = 33;\n    break;\n  case ITEM_WOODEN_AXE:\n  case ITEM_WOODEN_PICKAXE:\n  case ITEM_WOODEN_HOE:\n  case ITEM_WOODEN_SPADE:\n    health = 60;\n    break;\n  case ITEM_STONE_AXE:\n  case ITEM_STONE_PICKAXE:\n  case ITEM_STONE_HOE:\n  case ITEM_STONE_SPADE:\n  case ITEM_BOW:\n    health = 132;\n    break;\n  case ITEM_IRON_AXE:\n  case ITEM_IRON_PICKAXE:\n  case ITEM_IRON_HOE:\n  case ITEM_IRON_SPADE:\n    health = 251;\n    break;\n  case ITEM_DIAMOND_AXE:\n  case ITEM_DIAMOND_PICKAXE:\n  case ITEM_DIAMOND_HOE:\n  case ITEM_DIAMOND_SPADE:\n    health = 1562;\n    break;\n\n  default:\n    health = 0;\n  }\n\n\n  switch (itemID)\n  {\n  case ITEM_WOODEN_AXE:\n  case ITEM_GOLD_AXE:\n  case ITEM_STONE_AXE:\n  case ITEM_IRON_AXE:\n  case ITEM_DIAMOND_AXE:\n    if (block == BLOCK_LOG || block == BLOCK_PLANK)\n    {\n      rightUse = true;\n    }\n    break;\n\n  case ITEM_WOODEN_PICKAXE:\n  case ITEM_STONE_PICKAXE:\n  case ITEM_GOLD_PICKAXE:\n  case ITEM_IRON_PICKAXE:\n  case ITEM_DIAMOND_PICKAXE:\n    switch (block)\n    {\n    case BLOCK_STONE:\n    case BLOCK_COBBLESTONE:\n    case BLOCK_MOSSY_COBBLESTONE:\n    case BLOCK_COAL_ORE:\n    case BLOCK_IRON_ORE:\n    case BLOCK_GOLD_ORE:\n    case BLOCK_DIAMOND_ORE:\n    case BLOCK_OBSIDIAN:\n    case BLOCK_GLOWSTONE:\n    case BLOCK_NETHERSTONE:\n    case BLOCK_WOODEN_STAIRS:\n    case BLOCK_COBBLESTONE_STAIRS:\n    case BLOCK_IRON_DOOR:\n    case BLOCK_ICE:\n      rightUse = true;\n      break;\n    default:\n      rightUse = false;\n    }\n    break;\n\n  case ITEM_WOODEN_HOE:\n  case ITEM_GOLD_HOE:\n  case ITEM_STONE_HOE:\n  case ITEM_IRON_HOE:\n  case ITEM_DIAMOND_HOE:\n    //ToDo: add this\n    rightUse = false;\n    break;\n\n  case ITEM_WOODEN_SPADE:\n  case ITEM_GOLD_SPADE:\n  case ITEM_STONE_SPADE:\n  case ITEM_IRON_SPADE:\n  case ITEM_DIAMOND_SPADE:\n    switch (block)\n    {\n    case BLOCK_DIRT:\n    case BLOCK_GRASS:\n    case BLOCK_SAND:\n    case BLOCK_GRAVEL:\n    case BLOCK_CLAY:\n    case BLOCK_SNOW:\n      rightUse = true;\n      break;\n    default:\n      rightUse = false;\n    }\n    break;\n\n  default:\n    health = 0;\n  }\n  return health;\n}\n"
  },
  {
    "path": "src/inventory.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _INVENTORY_H_\n#define _INVENTORY_H_\n\n#include <stdint.h>\n#include <vector>\n#include <memory>\n#include \"nbt.h\"\n\nclass User;\n\nclass Item\n{\npublic:\n  void setType(int16_t type);\n  void setCount(int8_t count);\n  void setHealth(int16_t healt);\n  void setData(NBT_Value* _data);\n\n  static bool isEnchantable(int16_t type)\n  {\n    return (256 <= type && type <= 259) ||\n           (267 <= type && type <= 279) ||\n           (283 <= type && type <= 286) ||\n           (290 <= type && type <= 294) ||\n           (298 <= type && type <= 317) ||\n            type == 261 || type == 359 ||\n            type == 346;\n  }\n\n  inline int16_t getType()   const { return type;   }\n  inline int8_t  getCount()  const { return count;  }\n  inline int16_t getHealth() const { return health; }\n  inline NBT_Value* getData() const { return data; }\n\n  int16_t itemHealth(int type);\n  void decCount(int c = 1);\n  void incHealth(int c = 1);\n  void sendUpdate();\n  bool ready;\n\nprivate:\n  User* player;\n  int slot;\n  int16_t type;\n  int8_t count;\n  int16_t health;\n  NBT_Value *data;\n\npublic:\n\n  ~Item()\n  {\n    if (data) delete data;\n  }\n\n  Item(User* player = NULL, int slot = -1)\n    :\n    ready(false),\n    player(player),\n    slot(slot),\n    type(-1),\n    count(0),\n    health(0),\n    data(nullptr)\n  {\n  }\n\n  Item(int16_t _type, int8_t _count, int16_t _health, User* player = NULL)\n    :\n    ready(false),\n    player(player),\n    slot(-1),\n    type(_type),\n    count(_count),\n    health(_health),\n    data(nullptr)\n  {\n  }\n};\n\ntypedef std::shared_ptr<Item> ItemPtr;\n\nstruct OpenInventory\n{\n  OpenInventory(): recordAction(false){};\n  int8_t type;\n  int32_t x;\n  int32_t y;\n  int32_t z;\n  Item workbench[10];\n  std::vector<User*> users;\n  std::vector<int16_t> slotActions;\n  bool recordAction;\n};\n\ntypedef std::shared_ptr<OpenInventory> OpenInvPtr;\n\nenum { WINDOW_CURSOR = -1, WINDOW_PLAYER = 0, WINDOW_CRAFTING_TABLE, WINDOW_CHEST, WINDOW_LARGE_CHEST, WINDOW_FURNACE, WINDOW_BREWING_STAND };\n\nenum { MAX_SLOT_PLAYER = 44, MAX_SLOT_CHEST = 62, MAX_SLOT_LARGE_CHEST = 89,\n       MAX_SLOT_CRAFTING_TABLE = 45, MAX_SLOT_FURNACE=38, MAX_SLOT_BREWING_STAND = 39};\n\n// clickWindow special slot values\nenum { SLOT_SPECIAL };\n\n// clickWindow button values\nenum { INVENTORY_BUTTON_LEFT = 0, INVENTORY_BUTTON_RIGHT,\n       INVENTORY_BUTTON_ADD_SLOTS_LEFT = 1,\n       INVENTORY_BUTTON_END_DRAG_LEFT,\n       INVENTORY_BUTTON_START_DRAG_RIGHT = 4, INVENTORY_BUTTON_ADD_SLOTS_RIGHT = 5,\n       INVENTORY_BUTTON_END_DRAG_RIGHT };\n\n// clickWindow mode values\nenum { INVENTORY_MODE_NORMAL, INVENTORY_MODE_SHIFT, INVENTORY_MODE_NUMBER, INVENTORY_MODE_MIDDLECLICK,\n       INVENTORY_MODE_DROP_ITEM, INVENTORY_MODE_DRAG, INVENTORY_MODE_DOUBLECLICK };\n\n#define INVENTORYTYPE_CHEST \"minecraft:chest\"\n#define INVENTORYTYPE_CRAFTING_TABLE \"minecraft:crafting_table\"\n#define INVENTORYTYPE_FURNACE \"minecraft:furnace\"\n#define INVENTORYTYPE_BREWING_STAND \"minecraft:brewing_stand\"\n#define INVENTORYTYPE_HORSE \"EntityHorse\"\n\nclass User;\n\nclass Inventory\n{\npublic:\n\n  struct Recipe\n  {\n    Recipe() : width(0), height(0), slots() {}\n\n    int8_t width;\n    int8_t height;\n    std::vector<ItemPtr> slots;\n    Item output;\n  };\n\n  typedef std::shared_ptr<Recipe> RecipePtr;\n\n  bool addRecipe(int width, int height, std::vector<ItemPtr> inputrecipe,\n                 int outputCount, int16_t outputType, int16_t outputHealth);\n  bool readRecipe(const std::string& recipeFile);\n\n  Inventory(const std::string& path, const std::string& suffix, const std::string& cfg);\n\n  // Recipes\n  std::vector<RecipePtr> recipes;\n\n  // Open chest/workbench/furnace inventories\n  std::vector<OpenInvPtr> openWorkbenches;\n  std::vector<OpenInvPtr> openChests;\n  std::vector<OpenInvPtr> openFurnaces;\n\n  bool canBeArmour(int slot, int type);\n  bool onupdateinventory(User* user, int8_t windowID);\n\n\n  bool windowOpen(User* user, int8_t type, int32_t x, int32_t y, int32_t z);\n  bool windowClose(User* user, int8_t type, int32_t x, int32_t y, int32_t z);\n\n  bool windowClick(User* user, int8_t windowID, int16_t slot, int8_t button, int16_t actionNumber, int16_t itemID, int8_t itemCount, int16_t itemUses, int8_t mode = 0);\n\n  bool windowClose(User* user, int8_t windowID);\n\n  //Check inventory for space\n  bool isSpace(User* user, int16_t itemID, char count);\n\n  //Add items to inventory (pickups)\n  bool addItems(User* user, int16_t itemID, int16_t count, int16_t health);\n\n  bool updateInventory(User* user, int8_t windowID);\n  bool doCraft(Item* slots, int8_t width, int8_t height);\n\n  bool setSlot(User* user, int8_t windowID, int16_t slot, Item* item);\n\n  int16_t itemHealth(int16_t itemID, int8_t block, bool& rightUse);\n\n  void getEnabledRecipes(std::vector<std::string>& receiptFiles, const std::string& cfg);\n\n};\n\n#endif\n"
  },
  {
    "path": "src/items/food.cpp",
    "content": "#include \"food.h\"\n#include \"packets.h\"\n#include \"protocol.h\"\n#include \"map.h\"\n#include \"metadata.h\"\n\nbool ItemFood::affectedItem(int item) const\n{\n  switch (item)\n  {\n  case ITEM_GOLDEN_APPLE:\n  case ITEM_MUSHROOM_SOUP:\n  case ITEM_PORK:\n  case ITEM_GRILLED_PORK:\n  case ITEM_BREAD:\n  case ITEM_COOKED_FISH:\n  case ITEM_RAW_FISH:\n  case ITEM_APPLE:\n    return true;\n  }\n  return false;\n}\n\nvoid ItemFood::onRightClick(User* user, Item* item)\n{\n  int healammount = 0;\n  switch (item->getType())\n  {\n  case ITEM_GOLDEN_APPLE:\n    healammount = 20;\n    break;\n  case ITEM_MUSHROOM_SOUP:\n    healammount = 10;\n    break;\n  case ITEM_GRILLED_PORK:\n    healammount = 8;\n    break;\n  case ITEM_PORK:\n    healammount = 3;\n    break;\n  case ITEM_BREAD:\n    healammount = 5;\n    break;\n  case ITEM_COOKED_FISH:\n    healammount = 5;\n    break;\n  case ITEM_RAW_FISH:\n    healammount = 2;\n    break;\n  case ITEM_APPLE:\n    healammount = 4;\n    break;\n  }\n\n  int newhealth = user->health + healammount;\n  if (newhealth > 20)\n  {\n    newhealth = 20;\n  }\n\n  user->sethealth(newhealth);\n   \n  //Accept eating\n  user->buffer << Protocol::entityStatus(user->UID, 9);\n\n  //Eating animation\n  MetaData meta;\n  MetaDataElemByte *element = new MetaDataElemByte(0,0x10);\n  meta.set(element);\n  Packet pkt = Protocol::animation(user->UID,5);\n  //pkt << Protocol::entityMetadata(user->UID, meta);\n  //ToDo: add timer stop animation\n  \n  sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk((int32_t)user->pos.x), blockToChunk((int32_t)user->pos.z));\n  if (chunk != NULL)\n  {\n    chunk->sendPacket(pkt);\n  }\n\n  if(item->getCount() > 1)\n  {\n    item->setCount(item->getCount()-1);\n  }\n  else\n  {\n    item->setType(-1);\n    item->setCount(0);\n  }\n}\n\n"
  },
  {
    "path": "src/items/food.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _ITEMS_FOOD_H\n#define _ITEMS_FOOD_H\n\n#include <stdint.h>\n#include <string>\n\n#include \"constants.h\"\n#include \"inventory.h\"\n#include \"itembasic.h\"\n\nclass ItemFood: public ItemBasic\n{\npublic:\n  bool affectedItem(int item) const;\n  void onRightClick(User* user, Item* item);\n};\n\n#endif\n"
  },
  {
    "path": "src/items/itembasic.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cmath>\n#include <cstdlib>\n\n#include \"mineserver.h\"\n#include \"plugin.h\"\n#include \"inventory.h\"\n\n#include \"itembasic.h\"\n\nvoid ItemBasic::onRightClick(User* user, Item* item)\n{\n\n}\n\n\n"
  },
  {
    "path": "src/items/itembasic.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _ITEMS_BASIC_H\n#define _ITEMS_BASIC_H\n\n#include <stdint.h>\n#include <string>\n\n#include \"constants.h\"\n#include \"inventory.h\"\n#include \"user.h\"\n\n\n/**\n * BlockBasic can be used to extend your own block classes. It contains useful\n * methods for reuse in your own block extensions.\n */\nclass ItemBasic\n{\npublic:\n  virtual ~ItemBasic() { }\n  virtual bool affectedItem(int item) const = 0;\n  virtual void timer200() { }\n  virtual void onRightClick(User* user, Item* item);\n};\n\n#endif\n"
  },
  {
    "path": "src/items/projectile.cpp",
    "content": "#include \"projectile.h\"\n#include \"packets.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include <cmath>\n\n\nuint32_t generateEID();\n\nbool ItemProjectile::affectedItem(int item) const\n{\n  switch (item)\n  {\n  case ITEM_SNOWBALL:\n  case ITEM_EGG:\n  case ITEM_BOW:\n    return true;\n  }\n  return false;\n}\n\nvoid ItemProjectile::onRightClick(User* user, Item* item)\n{\n  int8_t projID = 0;\n  switch (item->getType())\n  {\n  case ITEM_SNOWBALL:\n    projID = 61;\n    break;\n  case ITEM_EGG:\n    projID = 62;\n    break;\n  case ITEM_BOW:\n    projID = 60;\n    break;\n  }\n\n  if(projID != 0)\n  {\n    if(projID == 60) // Bow and Arrow\n    {\n      bool foundArrow = false;\n      // Hotbar\n      for( int i = 36; i < 45; i++ )\n      {\n        if( user->inv[i].getType() == ITEM_ARROW )\n        {\n          foundArrow = true;\n          user->inv[i].decCount();\n          i = 45;\n        }\n      }\n      //Inventory\n      if(foundArrow == false)\n      {\n        for(int i = 9; i < 36; i++)\n        {\n          if( user->inv[i].getType() == ITEM_ARROW )\n          {\n            foundArrow = true;\n            user->inv[i].decCount();\n            i = 36;\n          }\n        }\n      }\n      if(!foundArrow)\n        return;\n      ServerInstance->map(user->pos.map)->sendProjectileSpawn(user, projID);\n    }\n    else\n    {\n      item->decCount();\n      ServerInstance->map(user->pos.map)->sendProjectileSpawn(user, projID);\n    }\n  }\n}\n"
  },
  {
    "path": "src/items/projectile.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _ITEMS_PROJECTILE_H\n#define _ITEMS_PROJECTILE_H\n\n#include <stdint.h>\n#include <string>\n\n#include \"constants.h\"\n#include \"inventory.h\"\n#include \"itembasic.h\"\n\nclass ItemProjectile: public ItemBasic\n{\npublic:\n  bool affectedItem(int item) const;\n  void onRightClick(User* user, Item* item);\n};\n\n#endif\n"
  },
  {
    "path": "src/json.cpp",
    "content": "/*\n  Copyright (c) 2016, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <iostream>\n#include <fstream>\n#include <cstring>\n#include <cstdlib>\n#include <sstream>\n\n#include \"mineserver.h\"\n#include \"json.h\"\n#include \"tools.h\"\n\nstd::string JSON_Val::readString(uint8_t* buf, int32_t& len) {\n  bool done = false;\n  bool escapeChar = false;\n  int32_t readBytes = 0;\n  std::string str;\n\n  while (!done) {\n    char byte = buf[0];    \n    buf++;\n    readBytes++;\n    switch (byte) {\n      case  '\\\\':\n        escapeChar = true;\n      break;\n      case '\\\"':\n        if (!escapeChar) {\n          done = true;\n        } else {\n          str += byte;\n        }\n      break;\n      default:\n        str+=byte;\n      break;\n    }\n    if (!len) done = true;\n  }\n  len -= readBytes;\n  return str;\n}\n\nvoid JSON_Val::dump(std::string &str) {\n  switch (m_type) {\n    case JSON_COMPOUND:\n      str += \"{\\n\";\n      {\n        bool first = true;\n        for (auto val : *m_value.compoundVal) {          \n          if (!first) {\n            str += \",\\n\";\n          }\n          first = false;\n          if (val.second->getType() == JSON_COMPOUND) if (val.first != \"\") str += \"\\\"\" + val.first + \"\\\": \";\n          val.second->dump(str);\n        }\n      }\n      str += \"\\n}\\n\";\n    break;\n    case JSON_LIST:\n      if (m_name != \"\") {\n        str += \"\\\"\" + m_name + \"\\\": \";\n      }\n      str += \"[\\n\";\n      {\n        bool first = true;\n        for (JSON_Val *val : *m_value.listVal) {\n          if (!first) {\n            str += \",\\n\";\n          }\n          first = false;\n          val->dump(str);\n        }\n      }\n      str += \"\\n]\\n\";\n    break;\n    case JSON_INT:\n      if (m_name != \"\") {\n        str += \"\\\"\" + m_name + \"\\\": \";\n      }\n      str += dtos(m_value.intVal);\n    break;\n    case JSON_FLOAT:\n      if (m_name != \"\") {\n        str += \"\\\"\" + m_name + \"\\\": \";\n      }\n      str += dtos(m_value.floatVal);\n    break;\n    case JSON_STRING:\n      if (m_name != \"\") {\n        str += \"\\\"\" + m_name + \"\\\": \";\n      }\n      str += \"\\\"\" + *m_value.stringVal + \"\\\"\";\n    break;\n    case JSON_BOOL:\n      if (m_name != \"\") {\n        str += \"\\\"\" + m_name + \"\\\": \";\n      }\n      str += m_value.boolVal ? \"true\": \"false\";\n    break;\n  }\n}\n\nJSON_Val::JSON_Val(uint8_t* buf, int32_t& len, JSON_type type) : m_type(type)\n{\n  bool readingString = false;\n  bool readingArray = false;\n  bool done = false;\n  bool escapeChar = false;\n  bool nameRead = false;\n\n  std::string temp;\n  int32_t readBytes = 0;\n  int32_t len_temp;\n\n  switch (m_type) {\n    case JSON_COMPOUND:\n      m_value.compoundVal = new std::map<std::string, JSON_Val*>();\n      while (!done) {\n        char byte = buf[0];    \n        buf++;\n        readBytes++;\n\n        switch (byte) {\n          case '\\\"':\n            if (!nameRead) {\n              len_temp = len-readBytes;\n              temp = readString(buf, len_temp);              \n              buf += len-readBytes - len_temp;\n              readBytes += len-readBytes - len_temp;\n            } else {\n              len_temp = len-readBytes;\n              std::string value = readString(buf, len_temp);\n              (*m_value.compoundVal)[temp] = new JSON_Val(temp, value);\n              buf += len-readBytes - len_temp;\n              readBytes += len-readBytes - len_temp;\n              nameRead = false;\n            }\n          break;\n          case ':':\n            nameRead = true;\n          break;\n          case '[':\n            if (nameRead) {\n              len_temp = len-readBytes;\n              (*m_value.compoundVal)[temp] = new JSON_Val(buf, len_temp, JSON_LIST);\n              (*m_value.compoundVal)[temp]->setName(temp);\n              buf += len-readBytes - len_temp;\n              readBytes += len-readBytes - len_temp;\n              nameRead = false;\n            }\n          break;\n          case '}':\n           done = true;\n          break;\n          case '{':\n            if (nameRead) {\n              len_temp = len-readBytes;\n              (*m_value.compoundVal)[temp] = new JSON_Val(buf, len_temp, JSON_COMPOUND);\n              buf += len-readBytes - len_temp;\n              readBytes += len-readBytes - len_temp;\n              nameRead = false;\n            }\n          break;\n          case ',':\n            // next value\n          break;\n          default:\n            if (!len) done = true;\n            else {\n              if (nameRead && ((byte >= '0' && byte <= '9') || byte == '-')) {\n                std::string val;\n                bool floatingpoint = false;\n                while ((byte >= '0' && byte <= '9') || byte == '.' || byte == 'e') {\n                  if (byte == '.') floatingpoint = true;\n                  val += byte;\n                  byte = buf[0];\n                  buf++;\n                  readBytes++;\n                }\n                if (!floatingpoint) {\n                  (*m_value.compoundVal)[temp] = new JSON_Val(temp, atoi(val.c_str()));\n                } else {\n                  double d;\n                  std::istringstream floatVal(val);                  \n                  floatVal >> d;\n                  (*m_value.compoundVal)[temp] = new JSON_Val(temp, d);\n                }\n                buf--;\n                readBytes--;\n                nameRead = false;\n              } else if (nameRead && strncmp((char*)(buf-1), \"true\", 4) == 0) {\n                buf+=3;\n                readBytes += 3;\n                (*m_value.compoundVal)[temp] = new JSON_Val(temp, true);\n                nameRead = false;\n              }\n              else if (nameRead && strncmp((char*)(buf-1), \"false\", 5) == 0) {\n                buf+=4;\n                readBytes += 4;\n                (*m_value.compoundVal)[temp] = new JSON_Val(temp, false);\n                nameRead = false;\n              }\n            }\n        }\n      }\n    break;\n    case JSON_LIST:\n      m_value.listVal = new std::vector<JSON_Val*>();\n      while (!done) {\n        char byte = buf[0];    \n        buf++;\n        readBytes++;\n\n        switch (byte) {\n          case '\\\"':\n            len_temp = len-readBytes;\n            temp = readString(buf, len_temp);\n            m_value.listVal->push_back(new JSON_Val(\"\", temp));\n            buf += len-readBytes - len_temp;\n            readBytes += len-readBytes - len_temp;\n          break;\n          case '[':\n            len_temp = len-readBytes;\n            m_value.listVal->push_back(new JSON_Val(buf, len_temp, JSON_LIST));\n            buf += len-readBytes - len_temp;\n            readBytes += len-readBytes - len_temp;\n          break;\n          case ']':\n            done = true;\n          break;\n          case '{':\n            len_temp = len-readBytes;\n            m_value.listVal->push_back(new JSON_Val(buf, len_temp, JSON_COMPOUND));\n            buf += len-readBytes - len_temp;\n            readBytes += len-readBytes - len_temp;\n          break;\n      \n        }\n      }\n    break;\n  }\n  len -= readBytes;\n}\n"
  },
  {
    "path": "src/json.h",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#pragma once\n\n#include <map>\n#include <string>\n#include <vector>\n\n#include <stdint.h>\n\n\nclass JSON_Val\n{\npublic:\n  enum JSON_type\n  {\n    JSON_COMPOUND,\n    JSON_LIST,\n    JSON_INT,\n    JSON_STRING,\n    JSON_BOOL,\n    JSON_FLOAT\n  };\n\n  JSON_Val(uint8_t* buf, int32_t& len, JSON_type type = JSON_COMPOUND);\n\n  std::string readString(uint8_t* buf, int32_t& len);\n\n  JSON_Val(const std::string& name, const std::string& val) {\n    m_type = JSON_STRING;\n    m_name = name;\n    m_value.stringVal = new std::string(val);\n  }\n\n  JSON_Val(const std::string& name, int32_t val) {\n    m_type = JSON_INT;\n    m_name = name;\n    m_value.intVal = val;\n  }\n\n  JSON_Val(const std::string& name, double val) {\n    m_type = JSON_FLOAT;\n    m_name = name;\n    m_value.floatVal = val;\n  }\n\n  JSON_Val(const std::string& name, bool val) {\n    m_type = JSON_BOOL;\n    m_name = name;\n    m_value.boolVal = val;\n  }\n\n  ~JSON_Val() {\n    switch (m_type) {\n      case JSON_COMPOUND:\n        for (auto val : *m_value.compoundVal)\n          delete val.second;\n        delete m_value.compoundVal;\n      break;\n      case JSON_LIST:\n        for (JSON_Val *val : *m_value.listVal)\n          delete val;\n        delete m_value.listVal;\n      break;\n      case JSON_STRING:\n        delete m_value.stringVal;\n      break;\n    }\n  }\n  \n  JSON_Val* operator[](const std::string& index) {\n      if (m_type != JSON_COMPOUND) {\n        return nullptr;\n      }\n\n      if (!m_value.compoundVal->count(index)) {\n        return nullptr;\n      }\n      return (*m_value.compoundVal)[index];\n  }\n\n  void Insert(const std::string& str, JSON_Val* val) {\n    if (m_type != JSON_COMPOUND) {\n      return;\n    }\n\n    if (m_value.compoundVal == 0) {\n      m_value.compoundVal = new std::map<std::string, JSON_Val*>();\n    }\n\n    if ((*m_value.compoundVal)[str] != 0) {\n      delete(*m_value.compoundVal)[str];\n    }\n    (*m_value.compoundVal)[str] = val;\n  }\n\n  JSON_Val& operator =(int32_t val) {\n    m_type = JSON_INT;\n    m_value.intVal = val;\n    return *this;\n  }\n\n  JSON_Val& operator =(const std::string& val) {\n    m_type = JSON_INT;\n    if (m_value.stringVal != nullptr) delete m_value.stringVal;\n    m_value.stringVal = new std::string(val);\n    return *this;\n  }\n\n  std::string* getString() {\n    return m_value.stringVal;\n  }\n\n  JSON_type getType() {\n    return m_type;\n  }\n\n  std::vector<JSON_Val*>* getList() {\n    if (m_type != JSON_LIST) {\n        return nullptr;\n      }\n    if (m_value.listVal == nullptr) {\n      m_value.listVal = new std::vector<JSON_Val*>();\n    }\n    return m_value.listVal;\n  }\n\n  void dump(std::string &str);\n\n  void setName(std::string str) {\n    m_name = str;\n  }\n\nprivate:\n  JSON_type m_type;\n  std::string m_name;\n  union\n  {\n    bool boolVal;\n    int32_t intVal;\n    double floatVal;\n    std::string* stringVal;\n    std::vector<JSON_Val*>* listVal;\n    std::map<std::string, JSON_Val*>* compoundVal;\n  } m_value;\n};\n"
  },
  {
    "path": "src/lighting.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n * Neither the name of the The Mineserver Project nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"lighting.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"nbt.h\"\n\nLighting* Lighting::mLight;\n\n\nbool Lighting::generateLight(int x, int z, sChunk* chunk)\n{\n\n  uint8_t* blocks     = chunk->blocks;\n  uint8_t* skylight   = chunk->skylight;\n  uint8_t* blocklight = chunk->blocklight;\n  int32_t* heightmap  = chunk->heightmap;\n\n  uint64_t* blocks64 = (uint64_t*)blocks;\n  uint32_t* skylight32 = (uint32_t*)skylight;\n  uint8_t meta, block, blockl, skyl;\n\n  std::queue<lightInfo> lightQueue;\n\n  int highest_y = 0;\n\n  // Clear lightmaps\n  memset(skylight, 0, 16 * 16 * 128 / 2);\n  memset(blocklight, 0, 16 * 16 * 128 / 2);\n\n  int light = 0;\n\n  // Sky light optimized search\n  for (int block_x = 0; block_x < 16; block_x++)\n  {\n    for (int block_z = 0; block_z < 16; block_z++)\n    {\n      int blockx_blockz = ((block_z << 7) + (block_x << 11)) >> 3;\n      int absolute_x    = (x << 4) + block_x;\n      int absolute_z    = (z << 4) + block_z;\n\n      for (int block_y = (127 / 8) - 1; block_y >= 0; block_y--)\n      {\n        int index      = block_y + blockx_blockz;\n        uint64_t block64 = blocks64[index];\n\n        // if one of these 8 blocks is\n        if (block64 != 0)\n        {\n          //Iterate which of the 8 is the first non-air\n          for (int i = 7; i >= 0; i--)\n          {\n            //Set light value if air\n            setLight(absolute_x, (block_y << 3) + i, absolute_z, 15, 0, 1, chunk);\n            light = 15;\n            int block = blocks[(index << 3) + i];\n            if (block != BLOCK_AIR)\n            {\n              //lightQueue.push(lightInfo(absolute_x,(block_y<<3)+i+1,absolute_z,15));\n              heightmap[block_z + (block_x << 4)] = (block_y << 3) + i;\n              for (int block_yy = (block_y << 3) + i; block_yy >= 0; block_yy --)\n              {\n                setLight(absolute_x, block_yy, absolute_z, light, 0, 1, chunk);\n                block = blocks[(blockx_blockz << 3) + block_yy];\n                light -= stopLight[block];\n\n                if (light < 1)\n                {\n                  break;\n                }\n\n                lightQueue.push(lightInfo(absolute_x, block_yy, absolute_z, light));\n              }\n              break;\n            }\n          }\n\n          if (heightmap[block_z + (block_x << 4)] > highest_y)\n          {\n            highest_y = heightmap[block_z + (block_x << 4)];\n          }\n          break;\n        }\n        //These 8 blocks are full lit\n        skylight32[index] = 0xffffffff;\n      }\n    }\n  }\n\n  for (int block_x = 0; block_x < 16; block_x++)\n  {\n    for (int block_z = 0; block_z < 16; block_z++)\n    {\n      int absolute_x = (x << 4) + block_x;\n      int absolute_z = (z << 4) + block_z;\n\n      //ToDo: heigth according to neighboring blocks\n      //int height = highest_y;\n      //if(block_x == 0 || block_x == 15 || block_z == 0 || block_z == 15)\n      //{\n      //}\n      if (heightmap[block_z + (block_x << 4)] < highest_y)\n      {\n        for (int i = heightmap[block_z + (block_x << 4)] + 1; i <= highest_y; i++)\n        {\n          lightQueue.push(lightInfo(absolute_x, i, absolute_z, 15));\n        }\n      }\n    }\n  }\n\n\n\n\n  spreadLight(&lightQueue, chunk);\n\n\n  //Get light from border chunks\n  for (int block_x = 0; block_x < 16; block_x += 15)\n  {\n    for (int block_z = 0; block_z < 16; block_z += 15)\n    {\n      int absolute_x = (x << 4) + block_x;\n      int absolute_z = (z << 4) + block_z;\n\n      int xdir = absolute_x;\n      int zdir = absolute_z;\n      int skipdir = -1;\n\n      //Which border?\n      if (block_z == 0)\n      {\n        zdir--;\n        skipdir = 5;\n      }\n      else if (block_z == 15)\n      {\n        zdir++;\n        skipdir = 4;\n      }\n      else if (block_x == 0)\n      {\n        xdir--;\n        skipdir = 3;\n      }\n      else if (block_x == 15)\n      {\n        xdir++;\n        skipdir = 2;\n      }\n      //ToDo: Corner case\n\n      for (int block_y = heightmap[block_z + (block_x << 4)]; block_y >= 0; block_y--)\n      {\n        if (ServerInstance->map(0)->getBlock(xdir, block_y, zdir, &block, &meta, false))\n        {\n          uint8_t curblocklight, curskylight;\n          if (getLight(xdir, block_y, zdir, &skyl, &blockl, chunk)                            &&\n              getLight(absolute_x, block_y, absolute_z, &curskylight, &curblocklight, chunk))\n          {\n            if (skyl - stopLight[block] - 1 > curskylight)\n            {\n              uint8_t curblock, curmeta;\n              if (ServerInstance->map(0)->getBlock(absolute_x, block_y, absolute_z, &curblock, &curmeta, false) &&\n                  skyl - stopLight[block] - stopLight[curblock] > 1)\n              {\n                lightQueue.push(lightInfo(absolute_x, block_y, absolute_z, skyl - stopLight[block] - stopLight[curblock] - 1, skipdir));\n              }\n              setLight(absolute_x, block_y, absolute_z, skyl - stopLight[block] - 1, 0, 1, chunk);\n            }\n            if (blockl - stopLight[block] - 1 > curblocklight)\n            {\n              //ToDo: get blocklight from this chunk\n            }\n          }\n        }\n      }\n    }\n  }\n\n  spreadLight(&lightQueue, chunk);\n\n\n\n  return true;\n}\n\nbool Lighting::spreadLight(std::queue<lightInfo> *lightQueue, sChunk* chunk)\n{\n  uint8_t meta, block, blockl, skyl;\n  //Next up, skylight spreading\n  while (!lightQueue->empty())\n  {\n    lightInfo info = lightQueue->front();\n    lightQueue->pop();\n\n    for (int direction = 0; direction < 6; direction++)\n    {\n      int xdir = info.x;\n      int ydir = info.y;\n      int zdir = info.z;\n      int skipdir = -1;\n\n      //If we came from this direction, skip\n      if (direction == info.skipdir)\n      {\n        continue;\n      }\n\n      switch (direction)\n      {\n      case 0:\n        ydir--;\n        skipdir = 1;\n        break;\n      case 1:\n        ydir++;\n        skipdir = 0;\n        break;\n      case 2:\n        xdir--;\n        skipdir = 3;\n        break;\n      case 3:\n        xdir++;\n        skipdir = 2;\n        break;\n      case 4:\n        zdir--;\n        skipdir = 5;\n        break;\n      case 5:\n        zdir++;\n        skipdir = 4;\n        break;\n      }\n      //Going too high\n      if (ydir == 128)\n      {\n        continue;\n      }\n\n      int light = info.light - 1;\n\n      //Stop of this block light value already higher\n      if (getLight(xdir, ydir, zdir, &skyl, &blockl, chunk) && skyl < light)\n      {\n        //If still light left, generate for this block also!\n        if (light > 1)\n        {\n          if (ServerInstance->map(0)->getBlock(xdir, ydir, zdir, &block, &meta, false) && light - stopLight[block] > 1)\n          {\n            lightQueue->push(lightInfo(xdir, ydir, zdir, light - stopLight[block], skipdir));\n          }\n        }\n        setLight(xdir, ydir, zdir, light, 0, 1, chunk);\n      }\n    }\n  }\n  return true;\n}\n\n// Light get/set\nbool Lighting::getLight(int x, int y, int z, uint8_t* skylight, uint8_t* blocklight, sChunk* chunk)\n{\n  return ServerInstance->map(0)->getLight(x, y, z, skylight, blocklight, chunk);\n}\n\nbool Lighting::setLight(int x, int y, int z, int skylight, int blocklight, int setLight, sChunk* chunk)\n{\n  return ServerInstance->map(0)->setLight(x, y, z, skylight, blocklight, setLight, chunk);\n}\n"
  },
  {
    "path": "src/lighting.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n   Redistribution and use in source and binary forms, with or without\n   modification, are permitted provided that the following conditions are met:\n * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n * Neither the name of the The Mineserver Project nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\n   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _LIGHTING_H_\n#define _LIGHTING_H_\n\n#include <queue>\n#include \"constants.h\"\n#include \"chunkmap.h\"\n\n\nstruct lightInfo\n{\n  lightInfo() { };\n  lightInfo(int _x, int _y, int _z, int _light)\n  {\n    x = _x;\n    y = _y;\n    z = _z;\n    light = _light;\n    skipdir = -1;\n  }\n  lightInfo(int _x, int _y, int _z, int _light, int _skipdir)\n  {\n    x = _x;\n    y = _y;\n    z = _z;\n    light = _light;\n    skipdir = _skipdir;\n  }\n  int x;\n  int y;\n  int z;\n  int light;\n  int skipdir;\n};\n\nclass Lighting\n{\nprivate:\n\n  Lighting()\n  {\n    for (int i = 0; i < 256; i++)\n    {\n      emitLight[i] = 0;\n    }\n    emitLight[0x0A] = 15; // Lava\n    emitLight[0x0B] = 15; // Stationary Lava\n    emitLight[0x27] = 1;  // Brown mushroom\n    emitLight[0x32] = 14; // Torch\n    emitLight[0x33] = 15; // Fire\n    emitLight[0x3E] = 14; // Lit furnace\n    emitLight[0x4A] = 9;  // Redstone ore (Glowing)\n    emitLight[0x4C] = 7;  // Redstone Torch (On)\n    emitLight[0x59] = 15; // Lightstone\n    emitLight[0x5A] = 11; // Portal\n    emitLight[0x5B] = 15; // Jack-O-Lantern\n\n    for (int i = 0; i < 256; i++)\n    {\n      stopLight[i] = 16;\n    }\n    stopLight[0x00] = 0; // Empty\n    stopLight[0x06] = 0; // Sapling\n    stopLight[0x08] = 3; // Water\n    stopLight[0x09] = 3; // Stationary water\n    stopLight[0x12] = 3; // Leaves\n    stopLight[0x14] = 0; // Glass\n    stopLight[0x25] = 0; // Yellow flower\n    stopLight[0x26] = 0; // Red rose\n    stopLight[0x27] = 0; // Brown mushroom\n    stopLight[0x28] = 0; // Red mushroom\n    stopLight[0x32] = 0; // Torch\n    stopLight[0x33] = 0; // Fire\n    stopLight[0x34] = 0; // Mob spawner\n    stopLight[0x35] = 0; // Wooden stairs\n    stopLight[0x37] = 0; // Redstone wire\n    stopLight[0x40] = 0; // Wooden door\n    stopLight[0x41] = 0; // Ladder\n    stopLight[0x42] = 0; // Minecart track\n    stopLight[0x43] = 0; // Cobblestone stairs\n    stopLight[0x47] = 0; // Iron door\n    stopLight[0x4b] = 0; // Redstone Torch (Off)\n    stopLight[0x4C] = 0; // Redstone Torch (On)\n    stopLight[0x4e] = 0; // Snow\n    stopLight[0x4f] = 3; // Ice\n    stopLight[0x53] = 0; // Reed (Sugar Cane)\n    stopLight[0x55] = 0; // Fence\n    stopLight[0x5A] = 0; // Portal\n    stopLight[0x5B] = 0; // Jack-O-Lantern\n    stopLight[BLOCK_SIGN_POST] = 0; // Sign post\n    stopLight[BLOCK_WALL_SIGN] = 0; // Wall sign\n    mLight = NULL;\n  }\n\n  ~Lighting()\n  {\n\n  }\n\n  static Lighting* mLight;\n\npublic:\n\n\n  // How blocks affect light\n  int stopLight[256];\n\n  // Blocks that emit light\n  int emitLight[256];\n\n  // Generate light maps for chunk\n  bool generateLight(int x, int z, sChunk* chunk);\n\n\n  // Light get/set\n  bool getLight(int x, int y, int z, uint8_t* blocklight, uint8_t* skylight, sChunk* chunk);\n  bool setLight(int x, int y, int z, int blocklight, int skylight, int setLight, sChunk* chunk);\n\n  bool spreadLight(std::queue<lightInfo> *lightQueue, sChunk* chunk);\n\n  static Lighting* get()\n  {\n    if (!mLight)\n    {\n      mLight = new Lighting();\n    }\n    return mLight;\n  }\n};\n\n\n#endif\n"
  },
  {
    "path": "src/logger.cpp",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n//\n// Mineserver logger.cpp\n//\n\n#include <sstream>\n#include <stdio.h>\n\n#include \"mineserver.h\"\n#include \"plugin.h\"\n\n#include \"logger.h\"\n\nvoid Logger::log(const std::string& msg, const std::string& file, int line)\n{\n  std::ostringstream str;\n  size_t pos;\n\n  pos = file.rfind(PATH_SEPARATOR);\n  if (pos != std::string::npos)\n  {\n    str << file.substr(pos + 1, file.length());\n  }\n  str << \":\";\n  str << (int)line;\n\n  log(LogType::LOG_INFO, str.str(), msg);\n}\n\nvoid Logger::log(LogType::LogType type, const std::string& source, const std::string& message)\n{\n  if (!ServerInstance->plugin()->hasHook(\"LogPost\"))\n  {\n    std::clog.tie(&std::cout);\n    if (type < LogType::LOG_WARNING)\n    {\n      std::clog.tie(&std::cerr);\n    }\n\n    std::clog << source << \": \" << message << std::endl;\n    return;\n  }\n\n  runAllCallback(\"LogPost\",(int)type, source.c_str(), message.c_str());\n}\n\nvoid Logger::log(LogType::LogType type, const std::string& source, const char* message, ...)\n{\n  // Message formatting\n  char buffer[4096];\n  va_list args;\n  va_start(args, message);\n  vsnprintf(buffer, sizeof(buffer), message, args);\n  va_end(args);\n\n  // Call back to our own logging function because i am too lazy to make it here\n  this->log(type, source, std::string(buffer));\n}\n"
  },
  {
    "path": "src/logger.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _LOGGER_H\n#define _LOGGER_H\n\n//\n// Mineserver logger.h\n//\n#include <string>\n\n#include \"logtype.h\"\n#include \"tools.h\"\n\n#define LOGLF(msg) ServerInstance->logger()->log(msg, std::string(__FILE__), __LINE__)\n\n#define LOG(type, source, msg) ServerInstance->logger()->log(LogType::LOG_##type, source, msg)\n\n\n// TODO: winex: log(type, file, line, msg) might be better than this\n#define LOG_FILENAME std::string(__FILE__).substr(std::string(__FILE__).rfind(PATH_SEPARATOR) + 1)\n#ifdef DEBUG\n#define LOG_FORMAT   LOG_FILENAME + \":\" + dtos(__LINE__) + \"::\" + std::string(__FUNCTION__) + \"()\"\n#else\n#define LOG_FORMAT   LOG_FILENAME + \"::\" + std::string(__FUNCTION__) + \"()\"\n#endif\n\n#define LOG2(type, msg) ServerInstance->logger()->log(LogType::LOG_##type, LOG_FORMAT, msg)\n\n\nclass Logger\n{\npublic:\n  void log(const std::string& message, const std::string& file, int line);\n  void log(LogType::LogType type, const std::string& source, const std::string& message);\n  void log(LogType::LogType type, const std::string& source, const char* message, ...);\n\n};\n\n#endif\n"
  },
  {
    "path": "src/logtype.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _LOG_TYPE_H\n#define _LOG_TYPE_H\n\n/**\n * An enumeration of types of log messages..\n *\n * Inspired by syslog.\n */\n#ifndef MINESERVER_C_API\nnamespace LogType\n{\n#endif\nenum LogType\n{\n  LOG_EMERG,    /** system is unusable */\n  LOG_ALERT,    /** action must be taken immediately*/\n  LOG_CRITICAL, /** critical conditions */\n  LOG_ERROR,    /** error conditions */\n  LOG_WARNING,  /** warning conditions */\n  LOG_NOTICE,   /** normal, but significant, condition */\n  LOG_INFO,     /** informational message */\n  LOG_DEBUG,    /** debug-level message */\n\n  // keep last and don't use for logging :P\n  LOG_COUNT\n};\n#ifndef MINESERVER_C_API\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/map.cpp",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n\n#include <sstream>\n#include <sys/stat.h>\n\n#include \"map.h\"\n#include \"logger.h\"\n#include \"worldgen/mapgen.h\"\n#include \"config.h\"\n#include \"permissions.h\"\n#include \"mineserver.h\"\n#include \"tree.h\"\n#include \"furnaceManager.h\"\n#include \"mcregion.h\"\n#include \"protocol.h\"\n#include \"physics.h\"\n\n// Copy Construtor\nMap::Map(const Map& oldmap)\n  :\n  chunks(oldmap.chunks),\n  mapLastused(oldmap.mapLastused),\n  mapChanged(oldmap.mapChanged),\n  mapLightRegen(oldmap.mapLightRegen),\n  items(oldmap.items),\n  mapTime(oldmap.mapTime),\n  mapSeed(oldmap.mapSeed),\n  physics(oldmap.physics)\n{\n}\n\nMap::Map()\n  :\n  chunks(441) // buckets!\n{\n  std::fill(emitLight, emitLight + 256, 0);\n\n  emitLight[0x0A] = 15; // Lava\n  emitLight[0x0B] = 15; // Stationary Lava\n  emitLight[0x27] = 1;  // Brown mushroom\n  emitLight[0x32] = 14; // Torch\n  emitLight[0x33] = 15; // Fire\n  emitLight[0x3E] = 14; // Lit furnace\n  emitLight[0x4A] = 9;  // Redstone ore (Glowing)\n  emitLight[0x4C] = 7;  // Redstone Torch (On)\n  emitLight[0x59] = 15; // Lightstone\n  emitLight[0x5A] = 11; // Portal\n  emitLight[0x5B] = 15; // Jack-O-Lantern\n\n  std::fill(stopLight, stopLight + 256, 16);\n\n  stopLight[0x00] = 0; // Empty\n  stopLight[0x06] = 0; // Sapling\n  stopLight[0x08] = 2; // Water\n  stopLight[0x09] = 2; // Stationary water\n  stopLight[0x12] = 2; // Leaves\n  stopLight[0x14] = 0; // Glass\n  stopLight[0x25] = 0; // Yellow flower\n  stopLight[0x26] = 0; // Red rose\n  stopLight[0x27] = 0; // Brown mushroom\n  stopLight[0x28] = 0; // Red mushroom\n  stopLight[0x32] = 0; // Torch\n  stopLight[0x33] = 0; // Fire\n  stopLight[0x34] = 0; // Mob spawner\n  stopLight[0x35] = 0; // Wooden stairs\n  stopLight[0x37] = 0; // Redstone wire\n  stopLight[0x40] = 0; // Wooden door\n  stopLight[0x41] = 0; // Ladder\n  stopLight[0x42] = 0; // Minecart track\n  stopLight[0x43] = 0; // Cobblestone stairs\n  stopLight[0x47] = 0; // Iron door\n  stopLight[0x4b] = 0; // Redstone Torch (Off)\n  stopLight[0x4C] = 0; // Redstone Torch (On)\n  stopLight[0x4e] = 0; // Snow\n  stopLight[0x4f] = 2; // Ice\n  stopLight[0x55] = 0; // Fence\n  stopLight[0x5A] = 0; // Portal\n  stopLight[0x5B] = 0; // Jack-O-Lantern\n  stopLight[BLOCK_SIGN_POST] = 0; // Sign post\n  stopLight[BLOCK_WALL_SIGN] = 0; // Wall sign\n\n  physics = 0;\n}\n\nMap::~Map()\n{\n\n  // louisdx: This destructor is doing WAY too much. All this should be in a separate function.\n  // A destructor must never throw, and this destructor does tons of non-exception-safe stuff.\n\n  for (ChunkMap::const_iterator it = chunks.begin(); it != chunks.end(); )\n  {\n    releaseMap((it++)->first);\n  }\n\n  // Free item memory\n  for (std::map<uint32_t, spawnedItem*>::const_iterator it = items.begin(); it != items.end(); ++it)\n  {\n    delete it->second;\n  }\n\n  items.clear();\n  std::string infile = mapDirectory + \"/level.dat\";\n\n  NBT_Value* root = NBT_Value::LoadFromFile(infile);\n  if (root != NULL)\n  {\n    NBT_Value& data = *((*root)[\"Data\"]);\n\n    //Get time from the map\n    data.Insert(\"Time\", new NBT_Value(mapTime));\n\n    NBT_Value* trees = ((*root)[\"Trees\"]);\n\n    if (trees)\n    {\n      std::vector<NBT_Value*>* tree_vec = trees->GetList();\n\n      tree_vec->clear();\n\n      for (std::list<sTree>::iterator iter = saplings.begin(); iter != saplings.end(); ++iter)\n      {\n        //(*trees)[i] = (*iter)\n        NBT_Value* tree = new NBT_Value(NBT_Value::TAG_COMPOUND);\n        tree->Insert(\"X\", new NBT_Value((int32_t)(*iter).x));\n        tree->Insert(\"Y\", new NBT_Value((int32_t)(*iter).y));\n        tree->Insert(\"Z\", new NBT_Value((int32_t)(*iter).z));\n        tree->Insert(\"plantedTime\", new NBT_Value((int32_t)(*iter).plantedTime));\n        tree->Insert(\"plantedBy\", new NBT_Value((int32_t)(*iter).plantedBy));\n        tree_vec->push_back(tree);\n      }\n    }\n\n    root->SaveToFile(infile);\n\n    delete root;\n  }\n}\n\nvoid Map::addSapling(User* user, int x, int y, int z)\n{\n  LOG(INFO, \"Map\", \"Place sapling \" + dtos(x) + \" \" + dtos(y) + \" \" + dtos(z));\n\n  saplings.push_back(sTree(x, y, z, mapTime, user->UID));\n}\n\nvoid Map::checkGenTrees()\n{\n  std::list<sTree>::iterator iter = saplings.begin();\n\n  static uint8_t light;\n  static uint8_t skylight;\n\n  static uint8_t blocktype;\n  static uint8_t meta;\n\n  while (iter != saplings.end())\n  {\n    getLight(iter->x, iter->y + 1, iter->z, &light, &skylight);\n    if (light > 9 || skylight > 3)\n    {\n      //Check above blocks\n      uint8_t i = 1;\n      for (i = 1; i < MAX_TRUNK; i++)\n      {\n        if (!getBlock(iter->x, iter->y + i, iter->z, &blocktype, &meta) || blocktype != BLOCK_AIR)\n        {\n          break;\n        }\n      }\n      if (i >= MIN_TREE_SPACE)\n      {\n        //If there is enough space\n        if (rand() % 50 == 0)\n        {\n          LOG(INFO, \"Map\", \"Grow tree!\");\n\n          Tree tree((*iter).x, (*iter).y, (*iter).z, 0);\n          saplings.erase(iter++);  // alternatively, i = items.erase(i);\n        }\n      }\n      else\n      {\n        ++iter;\n      }\n    }\n    else\n    {\n      ++iter;\n    }\n  }\n}\n\nvoid Map::init(int number)\n{\n  m_number = number;\n  const char* key = \"map.storage.nbt.directories\"; // Prefix for worlds config\n  std::list<std::string> tmp = ServerInstance->config()->mData(key)->keys();\n\n  if (number < int(tmp.size()))\n  {\n    std::list<std::string>::const_iterator it = tmp.begin();\n    std::advance(it, number);\n    mapDirectory = *it;\n  }\n\n  LOG2(INFO, \"Using world: \" + mapDirectory);\n\n  if (mapDirectory == \"Not found!\")\n  {\n    LOG2(WARNING, \"mapdir not defined\");\n    exit(EXIT_FAILURE);\n  }\n\n  std::string infile = mapDirectory + \"/level.dat\";\n\n  struct stat stFileInfo;\n  if (stat(mapDirectory.c_str(), &stFileInfo) != 0)\n  {\n    LOG(WARNING, \"Map\", \"Warning: Map directory not found, creating it now.\");\n\n    if (!makeDirectory(mapDirectory))\n    {\n      LOG(EMERG, \"Map\", \"Error: Could not create map directory.\");\n\n      exit(EXIT_FAILURE);\n    }\n  }\n\n  if (stat((infile).c_str(), &stFileInfo) != 0)\n  {\n    LOG(WARNING, \"Map\", \"Warning: level.dat not found, creating it now.\");\n\n    NBT_Value level(NBT_Value::TAG_COMPOUND);\n    level.Insert(\"Data\", new NBT_Value(NBT_Value::TAG_COMPOUND));\n    level[\"Data\"]->Insert(\"Time\", new NBT_Value((int64_t)0));\n    level[\"Data\"]->Insert(\"SpawnX\", new NBT_Value((int32_t)0));\n    level[\"Data\"]->Insert(\"SpawnY\", new NBT_Value((int32_t)120));\n    level[\"Data\"]->Insert(\"SpawnZ\", new NBT_Value((int32_t)0));\n    level[\"Data\"]->Insert(\"RandomSeed\", new NBT_Value((int64_t)(rand() * 65535)));\n    level[\"Data\"]->Insert(\"version\", new NBT_Value((int32_t)19133));\n    level[\"Data\"]->Insert(\"LevelName\", new NBT_Value(std::string(\"Mineserver world\")));\n\n    level.Insert(\"Trees\", new NBT_Value(NBT_Value::TAG_LIST));\n\n    level.SaveToFile(infile);\n\n    if (stat(infile.c_str(), &stFileInfo) != 0)\n    {\n      LOG(EMERG, \"Map\", \"Error: Could not create level.dat\");\n      exit(EXIT_FAILURE);\n    }\n  }\n\n  NBT_Value* root = NBT_Value::LoadFromFile(infile);\n  NBT_Value& data = *((*root)[\"Data\"]);\n\n  spawnPos.x() = (int32_t) * data[\"SpawnX\"];\n  spawnPos.y() = (int32_t) * data[\"SpawnY\"];\n  spawnPos.z() = (int32_t) * data[\"SpawnZ\"];\n\n  //Get time from the map\n  mapTime      = (int64_t) * data[\"Time\"];\n  mapSeed      = (int64_t) * data[\"RandomSeed\"];\n\n\n  //Check for McRegion format!\n  int32_t version = (int32_t) * data[\"version\"];\n\n  //Not in Anvil format?\n  if (version != 19133)\n  {\n    LOG(EMERG, \"Map\", \"Error: map not in Anvil format, shutting down!\");\n    \n    /*\n    //Do the actual conversion\n    convertMap(mapDirectory);\n\n    //Add version info to tell we are using McRegion format and levelname\n    (*root)[\"Data\"]->Insert(\"version\", new NBT_Value((int32_t)19133));\n    (*root)[\"Data\"]->Insert(\"LevelName\", new NBT_Value(std::string(\"Mineserver world\")));\n\n    //Save level.dat back with the new info\n    root->SaveToFile(infile);\n    */\n    exit(EXIT_FAILURE);\n  }\n\n  /////////////\n  // Basic tree handling\n\n  // Get list of saplings from map:\n  NBT_Value* trees = ((*root)[\"Trees\"]);\n\n  if (!trees || trees->GetListType() != NBT_Value::TAG_COMPOUND)\n  {\n    LOG(INFO, \"Map\", \"No Trees in level.dat, creating..\");\n    root->Insert(\"Trees\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n    trees = ((*root)[\"Trees\"]);\n    root->SaveToFile(infile);\n  }\n\n  std::vector<NBT_Value*>* tree_list = trees->GetList();\n\n  for (std::vector<NBT_Value*>::iterator iter = (*tree_list).begin(); iter != (*tree_list).end(); ++iter)\n  {\n    NBT_Value& tree = *(*iter);\n    int32_t x = (int32_t) * tree[\"X\"];\n    int32_t y = (int32_t) * tree[\"Y\"];\n    int32_t z = (int32_t) * tree[\"Z\"];\n    int32_t plantedTime = (int32_t) * tree[\"plantedTime\"];\n    int32_t plantedBy = (int32_t) * tree[\"plantedBy\"];\n    saplings.push_back(sTree(x, y, z, plantedTime, plantedBy));\n    LOG(INFO, \"Map\", \"sapling: \" + dtos(x) + \" \" + dtos(y) + \" \" + dtos(z));\n  }\n\n  /////////////////\n\n  // Init mapgenerator\n  Mineserver* _ServerInstance = ServerInstance;\n  _ServerInstance->mapGen(m_number)->re_init((int32_t)mapSeed);\n\n  delete root;\n}\n\nsChunk* Map::getMapData(int x, int z,  bool generate)\n{\n  const ChunkMap::const_iterator it = chunks.find(Coords(x, z));\n\n  if (it != chunks.end()) return it->second;\n\n  return generate == false ? NULL : loadMap(x, z, true);\n}\n\nbool Map::saveWholeMap()\n{\n  for (ChunkMap::const_iterator it = chunks.begin(); it != chunks.end(); ++it)\n  {\n    saveMap(it->first);\n  }\n\n  /////////////////////\n  // Save map details\n\n  std::string infile = mapDirectory + \"/level.dat\";\n\n  NBT_Value* root = NBT_Value::LoadFromFile(infile);\n  if (root != NULL)\n  {\n    NBT_Value& data = *((*root)[\"Data\"]);\n\n    //Get time from the map\n    *data[\"Time\"] = mapTime;\n    *data[\"SpawnX\"] = spawnPos.x();\n    *data[\"SpawnY\"] = spawnPos.y();\n    *data[\"SpawnZ\"] = spawnPos.z();\n\n    NBT_Value* trees = ((*root)[\"Trees\"]);\n\n    if (trees)\n    {\n      std::vector<NBT_Value*>* tree_vec = trees->GetList();\n\n      tree_vec->clear();\n\n      for (std::list<sTree>::iterator iter = saplings.begin(); iter != saplings.end(); ++iter)\n      {\n        //(*trees)[i] = (*iter)\n        NBT_Value* tree = new NBT_Value(NBT_Value::TAG_COMPOUND);\n        tree->Insert(\"X\", new NBT_Value((int32_t)(*iter).x));\n        tree->Insert(\"Y\", new NBT_Value((int32_t)(*iter).y));\n        tree->Insert(\"Z\", new NBT_Value((int32_t)(*iter).z));\n        tree->Insert(\"plantedTime\", new NBT_Value((int32_t)(*iter).plantedTime));\n        tree->Insert(\"plantedBy\", new NBT_Value((int32_t)(*iter).plantedBy));\n        tree_vec->push_back(tree);\n      }\n    }\n    root->SaveToFile(infile);\n\n    delete root;\n  }\n\n  return true;\n}\n\n//#define PRINT_LIGHTGEN_TIME\n\nbool Map::generateLight(int x, int z, sChunk* chunk)\n{\n  if (chunk == NULL)\n  {\n    const ChunkMap::const_iterator it = chunks.find(Coords(x, z));\n\n    if (it == chunks.end())\n    {\n      LOGLF(\"Loading chunk failed (generateLight)\");\n      return false;\n    }\n    else\n    {\n      chunk = it->second;\n    }\n  }\n\n#ifdef PRINT_LIGHTGEN_TIME\n#ifdef WIN32\n  DWORD t_begin, t_end;\n  t_begin = timeGetTime();\n#else\n  clock_t t_begin, t_end;\n  t_begin = clock();\n#endif\n#endif\n\n  uint8_t* blocks     = chunk->blocks;\n  uint8_t* skylight   = chunk->skylight;\n  uint8_t* blocklight = chunk->blocklight;\n  int32_t* heightmap  = chunk->heightmap;\n\n  int highest_y = 0;\n\n  // Clear lightmaps\n  memset(skylight, 0, 16 * 16 * 256 / 2);\n  memset(blocklight, 0, 16 * 16 * 256 / 2);\n\n  //Get neighboring chunks\n  sChunk* chunk_left   = getMapData(x-1, z, false);\n  sChunk* chunk_right  = getMapData(x+1, z, false);\n  sChunk* chunk_top    = getMapData(x, z+1, false);\n  sChunk* chunk_bottom = getMapData(x, z-1, false);\n\n  // Sky light\n  int light = 0;\n  bool foundheight = false;\n  for (int block_x = 0; block_x < 16; block_x++)\n  {\n    for (int block_z = 0; block_z < 16; block_z++)\n    {\n      light = 15;\n      foundheight = false;\n      uint32_t blockx_blockz = block_x + (block_z << 4);\n\n      for (int block_y = 255; block_y >= 0; block_y--)\n      {\n        int index      = blockx_blockz + (block_y << 8);\n        int absolute_x = x * 16 + block_x;\n        int absolute_z = z * 16 + block_z;\n        uint8_t block    = blocks[index];\n\n        //Grab light from the neighbouring chunks if it's brighter there..\n        if(block_x == 0 && chunk_left != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x-1, block_y, absolute_z, &temp_skylight, &temp_blocklight, chunk_left);          \n          if(temp_skylight-1 > light) light = temp_skylight-1;\n        }\n        else if(block_x == 15 && chunk_right != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x+1, block_y, absolute_z, &temp_skylight, &temp_blocklight, chunk_right);\n          if(temp_skylight-1 > light) light = temp_skylight-1;\n        }\n\n        if(block_z == 0 && chunk_bottom != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x, block_y, absolute_z-1, &temp_skylight, &temp_blocklight, chunk_bottom);\n          if(temp_skylight-1 > light) light = temp_skylight-1;\n        }\n        else if(block_z == 15 && chunk_top != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x, block_y, absolute_z+1, &temp_skylight, &temp_blocklight, chunk_top);\n          if(temp_skylight-1 > light) light = temp_skylight-1;\n        }\n\n        light -= stopLight[block];\n        if (light < 0)\n        {\n          light = 0;\n        }\n\n        // Calculate heightmap while looping this\n        if ((block != BLOCK_AIR) && (foundheight == false))\n        {\n          heightmap[block_z + (block_x << 4)] = ((block_y == 255) ? block_y : block_y + 1);\n          foundheight = true;\n        }\n\n        if (light < 1)\n        {\n          if (block_y > highest_y)\n          {\n            highest_y = block_y;\n          }\n\n          break;\n        }\n\n        setLight(absolute_x, block_y, absolute_z, light, 0, 1, chunk);\n      }\n    }\n  }\n\n  // Block light\n  for (int block_y = highest_y; block_y >= 0; block_y--)\n  {\n    for (int block_z = 0; block_z < 16; block_z++)\n    {      \n      uint32_t blocky_blockz = (block_z << 4) + (block_y << 8);\n\n      for (int block_x = 0; block_x < 16; block_x++)\n      {\n        int index      = block_y + blocky_blockz;\n        int absolute_x = x * 16 + block_x;\n        int absolute_z = z * 16 + block_z;\n        uint8_t block    = blocks[index];\n        int8_t light = 0;\n\n        if(block_x == 0 && chunk_left != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x-1, block_y, absolute_z, &temp_skylight, &temp_blocklight, chunk_left);          \n          light = temp_blocklight-1;\n        }\n        else if(block_x == 15 && chunk_right != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x+1, block_y, absolute_z, &temp_skylight, &temp_blocklight, chunk_right);\n          light = temp_blocklight-1;\n        }\n\n        if(block_z == 0 && chunk_bottom != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x, block_y, absolute_z-1, &temp_skylight, &temp_blocklight, chunk_bottom);\n          light = temp_blocklight-1;\n        }\n        else if(block_z == 15 && chunk_top != NULL)\n        {\n          uint8_t temp_blocklight, temp_skylight;\n          getLight(absolute_x, block_y, absolute_z+1, &temp_skylight, &temp_blocklight, chunk_top);\n          light = temp_blocklight-1;\n        }\n        light -= stopLight[block];\n        if (light < 0)\n        {\n          light = 0;\n        }\n\n        // If light emitting block\n        if (emitLight[block] > 0 || light > 0)\n        {\n          if(emitLight[block] > light) light = emitLight[block];\n          setLight(absolute_x, block_y, absolute_z, 0, light, 2, chunk);\n        }\n      }\n    }\n  }\n\n  // Spread light\n  for (int block_x = 0; block_x < 16; block_x++)\n  {\n    for (int block_z = 0; block_z < 16; block_z++)\n    {\n      for (int block_y = heightmap[block_z + (block_x << 4)]; block_y >= 0; block_y--)\n      {\n        int absolute_x = x * 16 + block_x;\n        int absolute_z = z * 16 + block_z;\n        uint8_t skylight_s, blocklight_s;\n\n        getLight(absolute_x, block_y, absolute_z, &skylight_s, &blocklight_s, chunk);\n\n        if (skylight_s)\n        {\n          spreadLight(absolute_x, block_y, absolute_z, skylight_s, 0);\n        }\n\n        if (blocklight_s)\n        {\n          spreadLight(absolute_x, block_y, absolute_z, blocklight_s, 1);\n        }\n      }\n    }\n  }\n#ifdef PRINT_LIGHTGEN_TIME\n#ifdef WIN32\n  t_end = timeGetTime();\n  ServerInstance->logger()->log(\"Lightgen: \" + dtos(t_end - t_begin) + \"ms\");\n#else\n  t_end = clock();\n  ServerInstance->logger()->log(\"Lightgen: \" + dtos((t_end - t_begin) / (CLOCKS_PER_SEC / 1000))) + \"ms\");\n#endif\n#endif\n\n\n  return true;\n}\n\nvoid Map::spreadLight(int x, int y, int z, int light_value, uint8_t type /* 0: sky, 1: block */)\n{\n  if ((y < 0) || (y > 255))\n  {\n    //LOGLF(\"Invalid y value (spreadLight)\");\n    // For sky style maps or maps with holes, this spams.\n    return;\n  }\n\n  // If no light, stop!\n  if (light_value < 1)\n  {\n    return;\n  }\n\n  for (int direction = 0; direction < 6; direction++)\n  {\n    // Going too high\n    if ((y == 255) && (direction == 2))\n    {\n      //Skip this direction\n      direction++;\n    }\n    // going negative\n    if ((y == 0) && (direction == 3))\n    {\n      //Skip this direction\n      direction++;\n    }\n\n    int x_toset = x;\n    int y_toset = y;\n    int z_toset = z;\n\n    switch (direction)\n    {\n    case 0:\n      x_toset++;\n      break;\n    case 1:\n      x_toset--;\n      break;\n    case 2:\n      y_toset++;\n      break;\n    case 3:\n      y_toset--;\n      break;\n    case 4:\n      z_toset++;\n      break;\n    case 5:\n      z_toset--;\n      break;\n    }\n\n    sChunk * chunk = getMapData(blockToChunk(x_toset), blockToChunk(z_toset), false);\n\n    if (chunk != NULL)\n    {\n      uint8_t block, meta, skylightCurrent, blocklightCurrent;\n\n      getBlock(x_toset, y_toset, z_toset, &block, &meta, false, chunk);\n\n      getLight(x_toset, y_toset, z_toset, &skylightCurrent, &blocklightCurrent, chunk);\n\n      const int lightNew = std::max(0, light_value - int(stopLight[block]) - 1);\n\n      if (lightNew > (type == 0 ? skylightCurrent : blocklightCurrent))\n      {\n        if      (type == 0) setLight(x_toset, y_toset, z_toset, lightNew, 0, 1, chunk);\n        else if (type == 1) setLight(x_toset, y_toset, z_toset, 0, lightNew, 2, chunk);\n        spreadLight(x_toset, y_toset, z_toset, lightNew, type);\n      }\n    }\n    else\n    {\n      //LOGLF(\"Loading chunk failed (spreadLight)\");\n      return;\n    }\n  }\n}\n\nbool Map::getBlock(int x, int y, int z, uint8_t* type, uint8_t* meta, bool generate)\n{\n  if ((y < 0) || (y > 255))\n  {\n    std::ostringstream str;\n    str << \"Invalid y value (\" << x << \", \" << y << \", \" << z << \")\";\n    LOG2(DEBUG, str.str());\n    return false;\n  }\n\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  sChunk* chunk = getMapData(chunk_x, chunk_z, generate);\n\n  if (!chunk)\n  {\n    if (generate)\n    {\n      LOGLF(\"Loading chunk failed (getBlock)\");\n    }\n\n    return false;\n  }\n\n  return getBlock(x, y, z, type, meta, generate, chunk);\n}\n\nbool Map::getBlock(int x, int y, int z, uint8_t* type, uint8_t* meta, bool generate, sChunk* chunk)\n{\n  int chunk_block_x  = blockToChunkBlock(x);\n  int chunk_block_z  = blockToChunkBlock(z);\n\n  uint8_t* blocks      = chunk->blocks;\n  uint8_t* metapointer = chunk->data;\n  int index            = chunk_block_x + (chunk_block_z << 4) + (y << 8);\n  *type                = blocks[index];\n  uint8_t metadata     = metapointer[(index) >> 1];\n\n  if (x & 1)\n  {\n    metadata  &= 0xf0;\n    metadata >>= 4;\n  }\n  else\n  {\n    metadata &= 0x0f;\n  }\n\n  *meta              = metadata;\n  chunk->lastused    = (int)time(0);\n\n  return true;\n}\n\nbool Map::getLight(int x, int y, int z, uint8_t* skylight, uint8_t* blocklight)\n{\n  if ((y < 0) || (y > 255))\n  {\n    LOGLF(\"Invalid y value (getLight)\");\n    return false;\n  }\n\n  // Map chunk pos from block pos\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  sChunk* chunk = getMapData(chunk_x, chunk_z, false);\n\n  if (!chunk)\n  {\n    LOGLF(\"Loading chunk failed (getLight)\");\n    return false;\n  }\n\n  return getLight(x, y, z, skylight, blocklight, chunk);\n}\n\nbool Map::getLight(int x, int y, int z, uint8_t* skylight, uint8_t* blocklight, sChunk* chunk)\n{\n  // Which block inside the chunk\n  int chunk_block_x = blockToChunkBlock(x);\n  int chunk_block_z = blockToChunkBlock(z);\n\n  uint8_t* blocklightPtr = chunk->blocklight;\n  uint8_t* skylightPtr   = chunk->skylight;\n  int index            = chunk_block_x + (chunk_block_z << 4) + (y << 8);\n  *blocklight = blocklightPtr[(index) >> 1];\n  *skylight   = skylightPtr[(index) >> 1];\n\n  if (x % 2)\n  {\n    *blocklight  &= 0xf0;\n    *blocklight >>= 4;\n\n    *skylight    &= 0xf0;\n    *skylight   >>= 4;\n  }\n  else\n  {\n    *blocklight &= 0x0f;\n    *skylight   &= 0x0f;\n  }\n\n  return true;\n}\n\nbool Map::setLight(int x, int y, int z, int skylight, int blocklight, int type)\n{\n\n  if ((y < 0) || (y > 255))\n  {\n    LOGLF(\"Invalid y value (setLight)\");\n    return false;\n  }\n\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  sChunk* chunk = getMapData(chunk_x, chunk_z, false);\n\n  if (!chunk)\n  {\n    LOGLF(\"Loading chunk failed (setLight)\");\n    return false;\n  }\n\n  return setLight(x, y, z, skylight, blocklight, type, chunk);\n}\n\nbool Map::setLight(int x, int y, int z, int skylight, int blocklight, int type, sChunk* chunk)\n{\n  //Make sure we are inside boundaries\n  if ((y < 0) || (y > 255))\n  {\n    LOGLF(\"Invalid y value (setLight 2)\");\n    return false;\n  }\n  int chunk_block_x        = blockToChunkBlock(x);\n  int chunk_block_z        = blockToChunkBlock(z);\n\n  uint8_t* blocklightPtr     = chunk->blocklight;\n  uint8_t* skylightPtr       = chunk->skylight;\n  int index                = chunk_block_x + (chunk_block_z << 4) + (y << 8);\n  char skylight_local      = skylightPtr[index >> 1];\n  char blocklight_local    = blocklightPtr[index >> 1];\n\n  if (x & 1)\n  {\n    if (type & 0x5) // 1 or 4\n    {\n      skylight_local &= 0x0f;\n      skylight_local |= skylight << 4;\n    }\n\n    if (type & 0x6) // 2 or 4\n    {\n      blocklight_local &= 0x0f;\n      blocklight_local |= blocklight << 4;\n    }\n  }\n  else\n  {\n    if (type & 0x5) // 1 or 4\n    {\n      skylight_local &= 0xf0;\n      skylight_local |= skylight;\n    }\n\n    if (type & 0x6) // 2 or 4\n    {\n      blocklight_local &= 0xf0;\n      blocklight_local |= blocklight;\n    }\n  }\n\n  if (type & 0x5) // 1 or 4\n  {\n    skylightPtr[index >> 1] = skylight_local;\n  }\n\n  if (type & 0x6) // 2 or 4\n  {\n    blocklightPtr[index >> 1] = blocklight_local;\n  }\n\n  return true;\n}\n\nbool Map::setBlock(int x, int y, int z, char type, char meta)\n{\n  if ((y < 0) || (y > 255))\n  {\n    LOGLF(\"Invalid y value (setBlock)\");\n    return false;\n  }\n\n  // Map chunk pos from block pos\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  sChunk* chunk = getMapData(chunk_x, chunk_z, true);\n\n  if (!chunk)\n  {\n    LOGLF(\"Loading chunk failed (setBlock)\");\n    return false;\n  }\n\n  // Which block inside the chunk\n  int chunk_block_x  = blockToChunkBlock(x);\n  int chunk_block_z  = blockToChunkBlock(z);\n\n  uint8_t* blocks      = chunk->blocks;\n  uint8_t* metapointer = chunk->data;\n  int index          = chunk_block_x + (chunk_block_z << 4) + (y << 8);\n  blocks[index] = type;\n  char metadata      = metapointer[index >> 1];\n\n  if (chunk_block_x & 1)\n  {\n    metadata &= 0x0f;\n    metadata |= meta << 4;\n  }\n  else\n  {\n    metadata &= 0xf0;\n    metadata |= meta;\n  }\n  metapointer[index >> 1] = metadata;\n\n  chunk->changed       = true;\n  chunk->lightRegen    = true;\n  chunk->lastused      = (int)time(NULL);\n\n  if (type == BLOCK_AIR)\n  {\n    uint8_t temp_type = 0, temp_meta = 0;\n    int16_t temp_y = y;\n    while (getBlock(x, temp_y, z, &temp_type, &temp_meta, false) && (temp_type == BLOCK_AIR))\n    {\n      temp_y--;\n    }\n    // We've actually moved down past the last air block to the one beneath, so we need to go back up one\n    temp_y++;\n\n    std::map<uint32_t, spawnedItem*>::const_iterator it_a = items.begin(), it_b = items.end();\n    for (; it_a != it_b; ++it_a)\n    {\n      if ((floor(static_cast<double>(it_a->second->pos.x()) / 32) == x) && (floor(static_cast<double>(it_a->second->pos.y()) / 32) == y + 1) && (floor(static_cast<double>(it_a->second->pos.z()) / 32) == z))\n      {\n        it_a->second->pos.y() = temp_y * 32;\n      }\n    }\n  }\n\n  return true;\n}\n\nbool Map::sendBlockChange(int x, int y, int z, int16_t type, char meta)\n{\n  const ChunkMap::const_iterator it = chunks.find(Coords(blockToChunk(x), blockToChunk(z)));\n\n  if (it == chunks.end())\n  {\n    return false;\n  }\n\n  it->second->sendPacket(Protocol::blockChange(x, y, z, type, meta));\n\n  return true;\n}\n\nbool Map::sendNote(int x, int y, int z, char instrument, char pitch, int16_t blocktype)\n{\n  const ChunkMap::const_iterator it = chunks.find(Coords(blockToChunk(x), blockToChunk(z)));\n\n  if (it == chunks.end())\n  {\n    return false;\n  }\n  std::string soundEffect;\n  switch (instrument)\n  {\n    case INSTRUMENT_BASS:\n      soundEffect = \"note.bass\";\n    break;\n    case INSTRUMENT_SNARE:\n      soundEffect = \"note.snare\";\n    break;\n    case INSTRUMENT_STICK:\n      soundEffect = \"note.hat\";\n    break;\n    case INSTRUMENT_BASSDRUM:\n      soundEffect = \"note.bd\";\n    break;\n    case INSTRUMENT_HARP:\n      soundEffect = \"note.harp\";\n    break;\n\n  }\n  const uint8_t pitchToEffectPitch[25] = {31, 33, 35, 38, 39, 42, 44, 46, 50, 53, 57, 60, 63, \n                                          66, 69, 75, 79, 83, 88, 94, 101, 107, 113, 120, 126};\n\n  it->second->sendPacket(Protocol::blockAction(x,y,z,instrument,pitch,blocktype));\n  it->second->sendPacket(Protocol::namedSoundEffect(soundEffect, x,y,z,100.0f,pitchToEffectPitch[pitch]));\n  return true;\n}\n\nbool Map::sendPickupSpawn(spawnedItem item)\n{\n  //Push to global item storage\n  spawnedItem* storedItem = new spawnedItem;\n  *storedItem     = item;\n  items[item.EID] = storedItem;\n\n  //Push to local item storage\n  int chunk_x = blockToChunk(item.pos.x() / 32);\n  int chunk_z = blockToChunk(item.pos.z() / 32);\n\n  const ChunkMap::const_iterator it = chunks.find(Coords(chunk_x, chunk_z));\n\n  if (it == chunks.end())\n  {\n    return false;\n  }\n\n  it->second->items.push_back(storedItem);\n\n  MetaData meta;\n  MetaDataElemByte* entity_attributes = new MetaDataElemByte(0,0x00);\n  meta.set(entity_attributes);\n\n  MetaDataElemShort* entity_attributes_2 = new MetaDataElemShort(1,300);\n  meta.set(entity_attributes_2);\n\n  MetaDataElemSlot* entity_item_type = new MetaDataElemSlot(10, Item(item.item, item.count, item.health));\n  meta.set(entity_item_type);\n\n  it->second->sendPacket(Protocol::spawnObject(item.EID, OBJECT_TYPE_ITEM_STACK,item.pos.x(), item.pos.y(),item.pos.z(), 1, 0, 0, 0));\n  it->second->sendPacket(Protocol::entityMetadata(item.EID, meta));\n\n  return true;\n}\n\nvoid Map::createPickupSpawn(int x, int y, int z, int type, int count, int health, User* user)\n{\n  spawnedItem item;\n  item.EID      = Mineserver::generateEID();\n  item.health   = health;\n  item.item     = type;\n  item.count    = count;\n  if (user != NULL)\n  {\n    item.spawnedBy = user->UID;\n  }\n  item.spawnedAt = time(NULL);\n\n  // Check to see if the block we're being asked to put the pickup spawn in is air\n  // If so, find the lowest air block at x,*,z that we can place it in and move it there\n  // Effectively we get... Gravity!\n  uint8_t temp_type = 0, temp_meta = 0;\n  int16_t temp_y = y;\n  if (getBlock(x, temp_y, z, &temp_type, &temp_meta, false) && (temp_type == BLOCK_AIR))\n  {\n    while (getBlock(x, temp_y, z, &temp_type, &temp_meta, false) && (temp_type == BLOCK_AIR))\n    {\n      temp_y--;\n    }\n    // We've actually moved down past the last air block, so we need to go back up one\n    temp_y++;\n\n    y = temp_y;\n  }\n\n  item.pos.x()  = x * 32;\n  item.pos.y()  = y * 32;\n  item.pos.z()  = z * 32;\n  //Randomize spawn position a bit\n  item.pos.x() += 5 + (rand() % 22);\n  item.pos.z() += 5 + (rand() % 22);\n\n  sendPickupSpawn(item);\n}\n\nbool Map::sendProjectileSpawn(User* user, int8_t projID)\n{\n  if (!projID)\n  {\n    return false;\n  }\n\n  int32_t EID = Mineserver::generateEID();\n  float   tempMult = 1.f - abs(user->pos.pitch / 90.f);\n\n  //\n  // Below is for position and velocity\n  //\n  double tempx = ( user->pos.x * 32 );\n  double tempy = ( user->pos.y + 1.5f ) * 32;\n  double tempz = ( user->pos.z * 32 );\n  int distFromUser = 50; // 32 is one whole block away, 50 seems to work while walking\n\n  //userYaw makes the player's yaw between 0-359\n  float userYaw = ((int)user->pos.yaw % 360) + (user->pos.yaw - (int)user->pos.yaw);\n  if( user->pos.yaw < 0 )\n  {\n    userYaw += 360;\n  }\n\n  if( user->pos.pitch < 0 )\n  {\n    tempy = ( distFromUser * abs(sin(user->pos.pitch / 90.f))) + (user->pos.y + 1.5f) * 32;\n  }\n  else if ( user->pos.pitch > 0 )\n  {\n    tempy = -( distFromUser * abs(sin(user->pos.pitch / 90.f))) + (user->pos.y + 1.5f) * 32;\n  }\n\n  if( userYaw != 0 && userYaw != 180 )\n  {\n    tempx = ( ( -distFromUser * sin(user->pos.yaw * (M_PI / 180.0f) ) ) * cos( user->pos.pitch * (M_PI / 180.0f) ) ) + (user->pos.x * 32);\n  }\n  if( userYaw != 90 && userYaw != 270 )\n  {\n    tempz = ( ( distFromUser * cos(user->pos.yaw * (M_PI / 180.0f) ) ) * cos( user->pos.pitch * (M_PI / 180.0f) ) ) + (user->pos.z * 32);\n  }\n\n  vec pos = vec((int)tempx, (int)tempy, (int)tempz);\n\n  //The 9000 and 14000 are based off of trial and error.  Not calculated to exactly mimic notchian projectile.\n  vec vel = vec((int)(sin(-(user->pos.yaw / 360.f) * 2.f * M_PI) * cos(user->pos.pitch * (M_PI / 180.0f)) * 9000.f),\n                (int)(sinf(-(user->pos.pitch / 90.f)) * 14000.f),\n                (int)(cos(-(user->pos.yaw / 360.f) * 2.f * M_PI) * cos(user->pos.pitch * (M_PI / 180.0f)) * 9000.f));\n\n  user->sendAll(Protocol::entity(EID));\n  user->sendAll(Protocol::spawnObject(EID,projID, pos.x(), pos.y(), pos.z(), user->UID,(int16_t)vel.x(),(int16_t)vel.y(),(int16_t)vel.z(),0,0));\n\n  //Add to simulation  \n  ServerInstance->physics(user->pos.map)->addEntitySimulation(projID,\n                                                             entity_position(pos.x()/32.0,\n                                                                             pos.y()/32.0,\n                                                                             pos.z()/32.0,\n                                                                             (vel.x()/8000.0)*20.0,\n                                                                             (vel.y()/8000.0)*20.0,\n                                                                             (vel.z()/8000.0)*20.0),\n                                                             EID,\n                                                             user->UID);\n\n  return true;\n}\n\nbool Map::sendExplosion(int x, int y, int z, float radius, std::vector<vec>&record, float velocity_x, float velocity_y, float velocity_z)\n{\n  //Push to local item storage\n  int chunk_x = blockToChunk(x);\n  int chunk_z = blockToChunk(z);\n\n  const ChunkMap::const_iterator it = chunks.find(Coords(chunk_x, chunk_z));\n\n  if (it == chunks.end())\n  {\n    return false;\n  }\n\n  it->second->sendPacket(Protocol::explosion(x, y, z, radius, record, velocity_x, velocity_y, velocity_z));\n  it->second->sendPacket(Protocol::namedSoundEffect(\"random.explode\", x, y, z, 100.0f, 63.0f));\n  return true;\n}\n\n\nbool Map::suitableForSpawn(const vec &pos)\n{\n  uint8_t block, meta;\n  if (!getBlock(pos.x(), pos.y()-1, pos.z(), &block, &meta, false)) return false;\n  return block != BLOCK_AIR && block != BLOCK_WATER && block != BLOCK_STATIONARY_WATER\n      && block != BLOCK_LAVA && block != BLOCK_STATIONARY_LAVA\n      && (getBlock(pos.x(), pos.y(), pos.z(), &block, &meta, false) && block == BLOCK_AIR)\n      && (getBlock(pos.x(), pos.y()+1, pos.z(), &block, &meta, false) && block == BLOCK_AIR);\n}\n\nbool Map::chooseSpawnPosition()\n{\n  uint8_t block, meta;\n  bool found = false;\n  // Make sure spawn position is not underground!\n  uint8_t new_y;\n  int new_x, new_z;\n  for (new_x = spawnPos.x(); new_x < spawnPos.x() + 100; new_x += 5)\n  {\n    for (new_z = spawnPos.z(); new_z < spawnPos.z() + 100; new_z += 5)\n    {\n      for (new_y = spawnPos.y(); new_y > 30; new_y--)\n      {\n        // Skip this colomn, we don't want to be underground\n        if (!getBlock(new_x, new_y, new_z, &block, &meta, false) ||\n            block != BLOCK_AIR) break;\n        if (suitableForSpawn(vec(new_x, new_y, new_z)))\n        {\n          found = true;\n          goto labelFound;\n        }\n      }\n    }\n  }\nlabelFound:\n  if (found)\n  {\n    //Store new spawn position to level.dat\n    spawnPos.x() = new_x;\n    spawnPos.y() = new_y;\n    spawnPos.z() = new_z;\n    std::string infile = mapDirectory + \"/level.dat\";\n    NBT_Value* root = NBT_Value::LoadFromFile(infile);\n    if (root != NULL)\n    {\n      NBT_Value& data = *((*root)[\"Data\"]);\n      *data[\"SpawnX\"] = (int32_t)spawnPos.x();\n      *data[\"SpawnY\"] = (int32_t)spawnPos.y();\n      *data[\"SpawnZ\"] = (int32_t)spawnPos.z();\n\n      root->SaveToFile(infile);\n\n      delete root;\n    }\n  }\n  return found;\n}\n\nsChunk* Map::loadMap(int x, int z, bool generate)\n{\n  const ChunkMap::const_iterator it = chunks.find(Coords(x, z));\n\n  // Case 1: We already have the chunk.\n  if (it != chunks.end())\n  {\n    return it->second;\n  }\n\n  // Case 2: We don't have the chunk but it's on file. Try to open region file.\n  RegionFile* newRegion = new RegionFile;\n  if (!newRegion->openFile(mapDirectory, x, z))\n  {\n    std::cout << \"Error loading file\" << std::endl;\n    delete newRegion;\n    return NULL;\n  }\n\n  //Allocate memory for uncompressed chunk data\n  uint8_t* chunkPointer =  new uint8_t[ALLOCATE_NBTFILE*10];\n  uint32_t chunkLen = 0;\n\n  // Try to load chunk. If fails, Case 3: Generate a new chunk.\n  if (!newRegion->readChunk(chunkPointer, &chunkLen, x, z))\n  {\n    // If generate (false only for lightmapgenerator)\n    if (generate)\n    {\n      // Re-seed! We share map gens with other maps\n      ServerInstance->mapGen(m_number)->init((int32_t)mapSeed);\n      ServerInstance->mapGen(m_number)->generateChunk(x, z, m_number);\n      generateLight(x, z);\n      delete newRegion;\n      delete [] chunkPointer;\n      return getChunk(x, z);\n    }\n    else\n    {\n      delete newRegion;\n      delete [] chunkPointer;\n      return NULL;\n    }\n  }\n\n  delete newRegion;\n\n  sChunk* chunk = new sChunk();\n\n  //Load NBT from memory\n  chunk->nbt = NBT_Value::LoadFromMemory(chunkPointer, chunkLen);\n\n\n  delete [] chunkPointer;\n\n\n  if (chunk->nbt == NULL)\n  {\n    LOGLF(\"Error in loading map (unable to load file)\");\n    delete chunk;\n    ServerInstance->mapGen(m_number)->init((int32_t)mapSeed);\n    ServerInstance->mapGen(m_number)->generateChunk(x, z, m_number);\n    generateLight(x, z);\n    return getChunk(x, z);\n  }\n\n  NBT_Value* level = (*chunk->nbt)[\"Level\"];\n\n  if (level == NULL)\n  {\n    LOGLF(\"Error in loading map (unable to find Level)\");\n    delete chunk;\n    ServerInstance->mapGen(m_number)->init((int32_t)mapSeed);\n    ServerInstance->mapGen(m_number)->generateChunk(x, z, m_number);\n    generateLight(x, z);\n    return getChunk(x, z);\n  }\n\n  NBT_Value* xPos = (*level)[\"xPos\"];\n  NBT_Value* zPos = (*level)[\"zPos\"];\n\n  if (xPos && zPos)\n  {\n    chunk->x = *xPos;\n    chunk->z = *zPos;\n  }\n  else\n  {\n    LOG(WARNING, \"Map\", \"incorrect chunk (missing xPos or zPos) regenerating\");\n    delete chunk;\n    ServerInstance->mapGen(m_number)->init((int32_t)mapSeed);\n    ServerInstance->mapGen(m_number)->generateChunk(x, z, m_number);\n    generateLight(x, z);\n    return getChunk(x, z);\n  }\n\n  NBT_Value* nbt_heightmap  = (*level)[\"HeightMap\"];\n\n  size_t fullLen = (16 * 256 * 16);\n  size_t halfLen = fullLen >> 1;\n  //chunk->blocks     = new uint8_t[fullLen];\n  //chunk->addblocks  = new uint8_t[halfLen];\n  //chunk->data       = new uint8_t[halfLen];\n  //chunk->blocklight = new uint8_t[halfLen];\n  //chunk->skylight   = new uint8_t[halfLen];\n  chunk->heightmap  = nbt_heightmap->GetIntArray()->data();\n  chunk->chunks_present = 0;\n  chunk->addblocks_present = 0;\n\n\n  //Clear all because there might not be every 16x16 block in the file\n  memset(chunk->blocks,    0, fullLen);\n  memset(chunk->addblocks, 0, halfLen);\n  memset(chunk->data,      0, halfLen);\n  memset(chunk->blocklight,0, halfLen);\n  memset(chunk->skylight,  0, halfLen);\n\n  //Loading \"Anvil\" type data structure\n  NBT_Value* nbt_sections     = (*level)[\"Sections\"];\n  std::vector<NBT_Value*>* nbt_list = nbt_sections->GetList();\n\n  std::vector<NBT_Value*>::iterator nbt_list_iter;\n  \n  for(nbt_list_iter = nbt_list->begin(); nbt_list_iter != nbt_list->end(); nbt_list_iter++)\n  {\n    NBT_Value& compound = *(*nbt_list_iter);\n    int16_t Y = (uint8_t)((int8_t) *compound[\"Y\"]);\n    chunk->chunks_present |= 1<<Y;\n    NBT_Value* nbt_blocks     = compound[\"Blocks\"];  \n    NBT_Value* nbt_data       = compound[\"Data\"];\n    NBT_Value* nbt_blocklight = compound[\"BlockLight\"];\n    NBT_Value* nbt_skylight   = compound[\"SkyLight\"];\n    NBT_Value* nbt_addblocks  = compound[\"AddBlocks\"];\n\n    if (nbt_blocks->GetByteArray()->size()     != 16*16*16   ||\n        nbt_data->GetByteArray()->size()       != 16*16*16/2 ||\n        nbt_blocklight->GetByteArray()->size() != 16*16*16/2 ||\n        nbt_skylight->GetByteArray()->size()   != 16*16*16/2)\n    {\n      LOGLF(\"Error in loading map (corrupt?)\");\n      delete chunk;\n      return NULL;\n    }\n    uint32_t offset = 16*16*16*Y;\n    memcpy(chunk->blocks+offset, nbt_blocks->GetByteArray()->data(), 16*16*16);\n    memcpy(chunk->data+offset/2, nbt_data->GetByteArray()->data(), 16*16*16/2);\n    memcpy(chunk->blocklight+offset/2, nbt_blocklight->GetByteArray()->data(), 16*16*16/2);\n    memcpy(chunk->skylight+offset/2, nbt_skylight->GetByteArray()->data(), 16*16*16/2);\n\n    if (nbt_blocks->GetByteArray()->size() == 16*16*16/2)\n    {\n      chunk->addblocks_present |= 1<<Y;\n      memcpy(chunk->addblocks+offset/2, nbt_addblocks->GetByteArray()->data(), 16*16*16/2);\n    }\n\n    //Clear the data from the NBT\n    delete *nbt_list_iter;\n  }\n  nbt_list->clear();\n\n  chunks.insert(ChunkMap::value_type(ChunkMap::key_type(x, z), chunk));\n\n  // Update last used time\n  chunk->lastused = time(NULL);\n\n  // Not changed\n  chunk->changed    = false;\n  chunk->lightRegen = false;\n\n  //Get list of chests,furnaces etc on the chunk\n  NBT_Value* entityList = (*level)[\"TileEntities\"];\n\n  //Verify the type\n  if (entityList && entityList->GetType() == NBT_Value::TAG_LIST && entityList->GetListType() == NBT_Value::TAG_COMPOUND)\n  {\n    std::vector<NBT_Value*>* const entities = entityList->GetList();\n\n    for (std::vector<NBT_Value*>::iterator iter = entities->begin(); iter != entities->end() ; ++iter)\n    {\n      std::vector<uint8_t> buffer;\n      NBT_Value* idVal = (**iter)[\"id\"];\n      if (idVal == NULL)\n      {\n        continue;\n      }\n\n      //Get TileEntity ID\n      std::string* id = idVal->GetString();\n      if (id == NULL)\n      {\n        continue;\n      }\n\n      //Check that x,y and z are present and in correct format\n      if ((**iter)[\"x\"]->GetType() != NBT_Value::TAG_INT ||\n          (**iter)[\"y\"]->GetType() != NBT_Value::TAG_INT ||\n          (**iter)[\"z\"]->GetType() != NBT_Value::TAG_INT)\n      {\n        continue;\n      }\n\n      int32_t entityX = *(**iter)[\"x\"];\n      int32_t entityY = *(**iter)[\"y\"];\n      int32_t entityZ = *(**iter)[\"z\"];\n\n      uint8_t entityBlock, entityMeta;\n      getBlock(entityX, entityY, entityZ, &entityBlock, &entityMeta, false);\n\n      //Extract sign data\n      if ((*id == \"Sign\"))\n      {\n        // Make sure this block exists\n        if (entityBlock != BLOCK_SIGN_POST && entityBlock != BLOCK_WALL_SIGN) continue;\n                \n        // Check for duplicates\n        bool blockEntityFound = false;\n        for (auto &entitySign : chunk->signs) {\n          if (entitySign->x == entityX && entitySign->y == entityY && entitySign->z == entityZ) {\n            blockEntityFound = true;\n            break;\n          }\n        }\n        if (blockEntityFound) continue;\n\n        signDataPtr newSign(new signData);\n        newSign->x = entityX;\n        newSign->y = entityY;\n        newSign->z = entityZ;\n        newSign->text1 = *(**iter)[\"Text1\"]->GetString();\n        newSign->text2 = *(**iter)[\"Text2\"]->GetString();\n        newSign->text3 = *(**iter)[\"Text3\"]->GetString();\n        newSign->text4 = *(**iter)[\"Text4\"]->GetString();\n\n        chunk->signs.push_back(newSign);\n      }\n      //Extract chest data\n      else if ((*id == \"Chest\"))\n      {\n        // Make sure this block exists\n        if (entityBlock != BLOCK_CHEST) continue;\n\n        // Check for duplicates\n        bool blockEntityFound = false;\n        for (auto &chest : chunk->chests) {\n          if (chest->x() == entityX && chest->y() == entityY && chest->z() == entityZ) {\n            blockEntityFound = true;\n            break;\n          }\n        }\n        if (blockEntityFound) continue;\n\n        NBT_Value* chestItems = (**iter)[\"Items\"];\n\n        if (chestItems->GetType() == NBT_Value::TAG_LIST)\n        {\n          if (chestItems->GetListType() != NBT_Value::TAG_COMPOUND)\n          {\n            continue;\n          }\n\n          std::vector<NBT_Value*>* itemList = chestItems->GetList();\n\n          chestDataPtr newChest(new chestData);\n          newChest->x(entityX);\n          newChest->y(entityY);\n          newChest->z(entityZ);\n\n          //Loop items\n          for (std::vector<NBT_Value*>::iterator itemIterator = itemList->begin(); itemIterator != itemList->end(); ++itemIterator)\n          {\n            //Check that all info exists and is the right type\n            if ((**itemIterator)[\"Count\"]  == NULL || (**itemIterator)[\"Slot\"] == NULL ||\n                (**itemIterator)[\"Damage\"] == NULL || (**itemIterator)[\"id\"] == NULL   ||\n\n                (**itemIterator)[\"Count\"]->GetType() != NBT_Value::TAG_BYTE ||\n                (**itemIterator)[\"Slot\"]->GetType() != NBT_Value::TAG_BYTE ||\n                (**itemIterator)[\"Damage\"]->GetType() != NBT_Value::TAG_SHORT ||\n                (**itemIterator)[\"id\"]->GetType() != NBT_Value::TAG_SHORT ||\n                (int8_t) *(**itemIterator)[\"Slot\"] > 26 ||\n                (int8_t) *(**itemIterator)[\"Slot\"] < 0) // Ignore slots going off limits\n            {\n              continue;\n            }\n            (*newChest->items())[(int8_t) *(**itemIterator)[\"Slot\"]]->setCount((int8_t)   *(**itemIterator)[\"Count\"]);\n            (*newChest->items())[(int8_t) *(**itemIterator)[\"Slot\"]]->setHealth((int16_t) *(**itemIterator)[\"Damage\"]);\n            (*newChest->items())[(int8_t) *(**itemIterator)[\"Slot\"]]->setType((int16_t)   *(**itemIterator)[\"id\"]);\n          }\n          //Push to our chest storage at chunk\n          chunk->chests.push_back(newChest);\n        }\n      }\n\n      //Next, furnace data\n      else if ((*id == \"Furnace\"))\n      {\n        // Make sure this block exists\n        if (entityBlock != BLOCK_FURNACE) continue;\n        \n        // Check for duplicates\n        bool blockEntityFound = false;\n        for (auto &furnace : chunk->furnaces) {\n          if (furnace->x == entityX && furnace->y == entityY && furnace->z == entityZ) {\n            blockEntityFound = true;\n            break;\n          }\n        }\n        if (blockEntityFound) continue;\n\n        NBT_Value* chestItems = (**iter)[\"Items\"];\n\n        if (chestItems->GetType() == NBT_Value::TAG_LIST)\n        {\n          if (chestItems->GetListType() != NBT_Value::TAG_COMPOUND)\n          {\n            continue;\n          }\n\n          std::vector<NBT_Value*>* itemList = chestItems->GetList();\n\n          if ((**iter)[\"BurnTime\"] == NULL || (**iter)[\"CookTime\"] == NULL)\n          {\n            //Skip\n            continue;\n          }\n\n          furnaceDataPtr newFurnace(new furnaceData);\n          newFurnace->x = entityX;\n          newFurnace->y = entityY;\n          newFurnace->z = entityZ;\n          newFurnace->map = m_number;\n          newFurnace->burnTime = (int16_t) * (**iter)[\"BurnTime\"];\n          newFurnace->cookTime = (int16_t) * (**iter)[\"CookTime\"];\n\n          //Loop through all items\n          for (std::vector<NBT_Value*>::iterator itemIterator = itemList->begin(); itemIterator != itemList->end(); ++itemIterator)\n          {\n            //Check that all info exists and is the right type\n            if ((**itemIterator)[\"Count\"] == NULL || (**itemIterator)[\"Slot\"] == NULL ||\n                (**itemIterator)[\"Damage\"] == NULL || (**itemIterator)[\"id\"] == NULL ||\n\n                (**itemIterator)[\"Count\"]->GetType()  != NBT_Value::TAG_BYTE  ||\n                (**itemIterator)[\"Slot\"]->GetType()   != NBT_Value::TAG_BYTE  ||\n                (**itemIterator)[\"Damage\"]->GetType() != NBT_Value::TAG_SHORT ||\n                (**itemIterator)[\"id\"]->GetType()     != NBT_Value::TAG_SHORT ||\n                (int8_t) *(**itemIterator)[\"Slot\"] > 3 || (int8_t) *(**itemIterator)[\"Slot\"] < 0)\n            {\n              //Skip\n              continue;\n            }\n            newFurnace->items[(int8_t) *(**itemIterator)[\"Slot\"]].setCount((int8_t)   *(**itemIterator)[\"Count\"]);\n            newFurnace->items[(int8_t) *(**itemIterator)[\"Slot\"]].setHealth((int16_t) *(**itemIterator)[\"Damage\"]);\n            newFurnace->items[(int8_t) *(**itemIterator)[\"Slot\"]].setType((int16_t)   *(**itemIterator)[\"id\"]);\n          }\n\n          //Push to our furnace storage at chunk and check for possible activity\n          chunk->furnaces.push_back(newFurnace);\n          ServerInstance->furnaceManager()->handleActivity(newFurnace);\n        }\n      }\n\n      //Delete list item\n      delete(*iter);\n      (*iter) = NULL;\n    }\n\n    //Clear the list\n    entityList->GetList()->clear();\n  }\n\n  return chunk;\n}\n\nbool Map::saveMap(int x, int z)\n{\n  sChunk* chunk = getChunk(x, z);\n\n  if (!chunk->changed)\n  {\n    return true;\n  }\n\n  // Recalculate light maps\n  if (chunk->lightRegen)\n  {\n    generateLight(x, z, chunk);\n  }\n\n  //Create directory for region files\n  struct stat stFileInfo;\n  std::string regionDir = mapDirectory + \"/region\";\n  if (stat(regionDir.c_str(), &stFileInfo) != 0)\n  {\n    if (!makeDirectory(regionDir))\n    {\n      LOG(EMERG, \"Map\", \"Error: Could not create map/region directory.\");\n\n      exit(EXIT_FAILURE);\n    }\n  }\n\n  //Store tile entities separately because they are stored in our own arrays with chunk data\n  NBT_Value* entityList = (*(*chunk->nbt)[\"Level\"])[\"TileEntities\"];\n\n  if (!entityList)\n  {\n    entityList = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);\n    chunk->nbt->Insert(\"TileEntities\", entityList);\n  }\n\n  //Save signs\n  for (uint32_t i = 0; i < chunk->signs.size(); i++)\n  {\n    NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n    val->Insert(\"id\", new NBT_Value(std::string(\"Sign\")));\n    val->Insert(\"x\", new NBT_Value((int32_t)chunk->signs[i]->x));\n    val->Insert(\"y\", new NBT_Value((int32_t)chunk->signs[i]->y));\n    val->Insert(\"z\", new NBT_Value((int32_t)chunk->signs[i]->z));\n    val->Insert(\"Text1\", new NBT_Value(chunk->signs[i]->text1));\n    val->Insert(\"Text2\", new NBT_Value(chunk->signs[i]->text2));\n    val->Insert(\"Text3\", new NBT_Value(chunk->signs[i]->text3));\n    val->Insert(\"Text4\", new NBT_Value(chunk->signs[i]->text4));\n\n    entityList->GetList()->push_back(val);\n  }\n\n  //Save chests\n  for (uint32_t i = 0; i < chunk->chests.size(); i++)\n  {\n    NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n    val->Insert(\"id\", new NBT_Value(std::string(\"Chest\")));\n    val->Insert(\"x\", new NBT_Value((int32_t)chunk->chests[i]->x()));\n    val->Insert(\"y\", new NBT_Value((int32_t)chunk->chests[i]->y()));\n    val->Insert(\"z\", new NBT_Value((int32_t)chunk->chests[i]->z()));\n\n    NBT_Value* nbtInv = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);\n    for (uint32_t slot = 0; slot < chunk->chests[i]->size(); slot++)\n    {\n      if ((*chunk->chests[i]->items())[slot]->getCount() && (*chunk->chests[i]->items())[slot]->getType() != -1)\n      {\n        NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n        val->Insert(\"Count\", new NBT_Value((int8_t)(*chunk->chests[i]->items())[slot]->getCount()));\n        val->Insert(\"Slot\", new NBT_Value((int8_t)slot));\n        val->Insert(\"Damage\", new NBT_Value((int16_t)(*chunk->chests[i]->items())[slot]->getHealth()));\n        val->Insert(\"id\", new NBT_Value((int16_t)(*chunk->chests[i]->items())[slot]->getType()));\n        nbtInv->GetList()->push_back(val);\n      }\n    }\n    val->Insert(\"Items\", nbtInv);\n\n    entityList->GetList()->push_back(val);\n  }\n\n  //Save furnaces\n  for (uint32_t i = 0; i < chunk->furnaces.size(); i++)\n  {\n    NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n    val->Insert(\"id\", new NBT_Value(std::string(\"Furnace\")));\n    val->Insert(\"x\", new NBT_Value((int32_t)chunk->furnaces[i]->x));\n    val->Insert(\"y\", new NBT_Value((int32_t)chunk->furnaces[i]->y));\n    val->Insert(\"z\", new NBT_Value((int32_t)chunk->furnaces[i]->z));\n    val->Insert(\"BurnTime\", new NBT_Value((int16_t)chunk->furnaces[i]->burnTime));\n    val->Insert(\"CookTime\", new NBT_Value((int16_t)chunk->furnaces[i]->cookTime));\n    NBT_Value* nbtInv = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);\n\n    for (uint32_t slot = 0; slot < 3; slot++)\n    {\n      //Store only non-null info\n      if (chunk->furnaces[i]->items[slot].getCount() && chunk->furnaces[i]->items[slot].getType() != 0 && chunk->furnaces[i]->items[slot].getType() != -1)\n      {\n        NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n        val->Insert(\"Count\", new NBT_Value((int8_t)chunk->furnaces[i]->items[slot].getCount()));\n        val->Insert(\"Slot\", new NBT_Value((int8_t)slot));\n        val->Insert(\"Damage\", new NBT_Value((int16_t)chunk->furnaces[i]->items[slot].getHealth()));\n        val->Insert(\"id\", new NBT_Value((int16_t)chunk->furnaces[i]->items[slot].getType()));\n        nbtInv->GetList()->push_back(val);\n      }\n    }\n    val->Insert(\"Items\", nbtInv);\n\n    entityList->GetList()->push_back(val);\n  }\n\n  NBT_Value* sections = (*(*chunk->nbt)[\"Level\"])[\"Sections\"];\n  //Store chunk data to NBT\n  for(uint32_t Y = 0; Y < 16; Y++)\n  {\n    uint32_t offset = 16*16*16*Y;\n    if(chunk->chunks_present & (1<<Y))\n    {\n      NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n      val->Insert(\"Y\", new NBT_Value((int8_t)Y));\n      val->Insert(\"Blocks\", new NBT_Value(&chunk->blocks[offset], 16*16*16));\n      val->Insert(\"Data\", new NBT_Value(&chunk->data[offset>>1], 16*16*16/2));\n      val->Insert(\"SkyLight\", new NBT_Value(&chunk->skylight[offset>>1], 16*16*16/2));\n      val->Insert(\"BlockLight\", new NBT_Value(&chunk->blocklight[offset>>1], 16*16*16/2));\n      if(chunk->addblocks_present & (1<<Y))\n      {\n        val->Insert(\"AddBlocks\", new NBT_Value(&chunk->addblocks[offset>>1], 16*16*16/2));\n      }\n      sections->GetList()->push_back(val);\n    }\n  }\n\n\n  //Allocate memory for NBT and save (+deflate) it\n  uint8_t* buffer = new uint8_t[ALLOCATE_NBTFILE];\n  uint32_t len;\n  chunk->nbt->SaveToMemory(buffer, &len);\n\n\n  //Clear off the chunk data\n  NBT_Value* nbt_sections     = (*(*chunk->nbt)[\"Level\"])[\"Sections\"];\n  std::vector<NBT_Value*>* nbt_list = nbt_sections->GetList();\n  std::vector<NBT_Value*>::iterator nbt_list_iter;\n  \n  for(nbt_list_iter = nbt_list->begin(); nbt_list_iter != nbt_list->end(); nbt_list_iter++)\n  {\n    delete *nbt_list_iter;\n  }\n  nbt_list->clear();\n\n\n  //Open regionfile and write chunk\n  RegionFile newRegion;\n  newRegion.openFile(mapDirectory, x, z);\n  newRegion.writeChunk(buffer, len, x, z);\n\n  delete [] buffer;\n\n  // Set \"not changed\"\n  chunk->changed    = false;\n  chunk->lightRegen = false;\n\n  return true;\n}\n\nbool Map::releaseMap(int x, int z)\n{\n  // save first\n  saveMap(x, z);\n\n  // free the memory allocated to the sChunk\n  delete getChunk(x, z);\n\n  // erase the chunk pointer from the collection\n  chunks.erase(Coords(x, z));\n\n  return true;\n}\n\nbool Map::sendMultiBlocks(std::set<vec>& blocks)\n{\n  while (!blocks.empty())\n  {\n    std::set<vec> toRem;\n    const vec firstblock = *blocks.begin();\n    const int chunk_x = blockToChunk(firstblock.x());\n    const int chunk_z = blockToChunk(firstblock.z());\n\n    for (std::set<vec>::const_iterator it = blocks.begin(); it != blocks.end(); ++it)\n    {\n      const int t_chunk_x = blockToChunk(it->x());\n      const int t_chunk_z = blockToChunk(it->z());\n\n      if (chunk_x == t_chunk_x && chunk_z == t_chunk_z)\n      {\n        toRem.insert(*it);\n      }\n    }\n\n    Packet packet;\n    unsigned int offsetx = chunk_x << 4;\n    unsigned int offsetz = chunk_z << 4;\n\n    // ToDo: Move to Protocol\n    packet << MS_VarInt((uint32_t)PACKET_OUT_MULTI_BLOCK_CHANGE) << (int32_t) chunk_x << (int32_t) chunk_z \n           << MS_VarInt((uint32_t)toRem.size());\n\n    for (std::set<vec>::const_iterator it = toRem.begin(); it != toRem.end(); ++it)\n    {\n      uint8_t block, meta;\n      ServerInstance->map(m_number)->getBlock(it->x(), it->y(), it->z(), &block, &meta);\n\n      uint8_t coord = ((it->x() - offsetx) << 4) + ((it->z() - offsetz));\n\n      packet << coord;\n      packet << (uint8_t)it->y();\n      packet << MS_VarInt((uint32_t)( (block<<4) | (meta & 0xf) ));\n      \n      std::set<vec>::iterator jt = blocks.find(*it);\n      if (jt != blocks.end())\n      {\n        blocks.erase(jt);\n      }\n    }\n\n    toRem.clear();\n\n    const ChunkMap::const_iterator it = chunks.find(Coords(chunk_x, chunk_z));\n\n    if (it == chunks.end())\n    {\n      //return false;\n      continue;\n    }\n\n    it->second->sendPacket(packet);\n  }\n\n  return true;\n}\n\n// Send chunk to user\nvoid Map::sendToUser(User* user, int x, int z, bool login)\n{\n\n  Packet p;\n\n  sChunk* chunk = loadMap(x, z);\n  if (chunk == NULL)\n  {\n    return;\n  }\n  const int mapdataLen = 98304*2+256;\n  uint8_t* mapdata = new uint8_t[mapdataLen];\n  int32_t mapposx    = x;\n  int32_t mapposz    = z;\n\n  //Regenerate lighting if needed\n  if (chunk->lightRegen)\n  {\n    generateLight(x, z, chunk);\n    chunk->lightRegen = false;\n  }\n\n  \n  //ToDo: now sending all 16 16x16 chunks, limit to only those with blocks.\n  // Chunk\n  p << MS_VarInt((uint32_t)PACKET_OUT_MAP_CHUNK) << (int32_t)(mapposx) << (int32_t)(mapposz)\n       << (int8_t)1 /* Ground-Up Continuous */ << (int16_t)0xffff /* Enabled chunks 0..15 */;\n\n\n  //ToDo: Do this when loading the map instead\n  for (int i = 0; i < 65536; i++) {\n    mapdata[i << 1] = ((chunk->blocks[i] & 0xf) << 4) | (i & 1 ? chunk->data[i>>1]>>4 : chunk->data[i>>1]&0xf);\n    mapdata[(i<<1)+1] = chunk->blocks[i]>>4;\n  }\n\n  memcpy(&mapdata[(65536)*2], chunk->blocklight, 16384*2);\n  memcpy(&mapdata[(65536 + 16384)*2], chunk->skylight, 16384*2);\n\n  //Biome data\n  memset(&mapdata[(65536 + 16384 + 16384)*2], 0, 256);\n\n\n  p << MS_VarInt((uint32_t)mapdataLen);\n  p.addToWrite(mapdata, mapdataLen);\n\n  user->writePacket(p);\n\n  //Push sign data to player\n  for (size_t i = 0; i < chunk->signs.size(); ++i)\n  {\n    user->writePacket(Protocol::updateSign(chunk->signs[i]->x, chunk->signs[i]->y, chunk->signs[i]->z,\n      chunk->signs[i]->text1,chunk->signs[i]->text2, chunk->signs[i]->text3, chunk->signs[i]->text4));\n  }\n\n  delete[] mapdata;\n}\n\n"
  },
  {
    "path": "src/map.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _MAP_H_\n#define _MAP_H_\n\n#include <map>\n#include <list>\n#include <ctime>\n\n#include \"vec.h\"\n#include \"chunkmap.h\"\n\nstruct sTree\n{\n  int32_t x, y, z;\n  int64_t plantedTime;\n  uint32_t plantedBy;\n\n  sTree(int32_t _x, int32_t _y, int32_t _z, int64_t _plantedTime, uint32_t _plantedBy) :\n    x(_x), y(_y), z(_z),\n    plantedTime(_plantedTime), plantedBy(_plantedBy) {}\n};\n\nstruct MinecartData\n{\n  uint32_t EID;\n  vec pos;\n  vec speed;\n  uint64_t timestamp;\n  vec lastBlock;\n  MinecartData(uint32_t EID, vec pos, vec speed, uint64_t timestamp)\n  {\n    this->EID = EID;\n    this->pos = pos;\n    this->speed = speed;\n    this->timestamp = timestamp;\n    lastBlock = vec(0,0,0);\n  }\n};\n\nclass Map\n{\npublic:\n  Map();\n  Map(const Map& oldmap);\n  ~Map();\n\n  std::string mapDirectory;\n\n  Physics* physics;\n\n  // List of saplings ready to grow\n  std::list<sTree> saplings;\n  void addSapling(User* user, int x, int y, int z);\n  void checkGenTrees();\n\n  // Map spawn position\n  vec spawnPos;\n\n  // Map number\n  int m_number;\n\n  // How blocks affect light\n  int stopLight[256];\n\n  // Blocks that emit light\n  int emitLight[256];\n\n  // Store chunks here (remove maps)\n  ChunkMap chunks;\n\n  // Store the time map chunk has been last used\n  std::map<uint32_t, int> mapLastused;\n\n  // Store if map has been modified\n  std::map<uint32_t, bool> mapChanged;\n\n  // Do we need light regeneration\n  std::map<uint32_t, bool> mapLightRegen;\n\n  // Store item pointers for each chunk\n  //std::map<uint32, std::vector<spawnedItem *> > mapItems;\n  std::vector<MinecartData> minecarts;\n\n  //All spawned items on map\n  std::map<uint32_t, spawnedItem*> items;\n\n  //  void posToId(int x, int z, uint32_t *id);\n  //  void idToPos(uint32_t id, int *x, int *z);\n\n  void init(int number);\n  void sendToUser(User* user, int x, int z, bool login = false);\n\n  //Time in the map\n  int64_t mapTime;\n\n  // Map seed\n  int64_t mapSeed;\n\n  // Get pointer to struct\n  sChunk* getMapData(int x, int z, bool generate = true);\n\n  // Is specified position suitable for spawn position\n  bool suitableForSpawn(const vec &pos);\n\n  // Make sure spawn position is not underground\n  bool chooseSpawnPosition();\n\n  // Load map chunk\n  sChunk* loadMap(int x, int z, bool generate = true);\n\n  // Save map chunk to disc\n  bool saveMap(int x, int z);\n  inline bool saveMap(const Coords& c) { return saveMap(c.first, c.second); }\n\n  // Save whole map to disc (/save command)\n  bool saveWholeMap();\n\n  // Generate light maps for chunk. Optional chunk hint.\n  bool generateLight(int x, int z, sChunk* chunk = NULL);\n\n  // Release/save map chunk\n  bool releaseMap(int x, int z);\n  inline bool releaseMap(const Coords& c) { return releaseMap(c.first, c.second); }\n\n  // Get a chunk pointer or NULL on failure\n  inline sChunk* getChunk(int x, int z) const\n  {\n    const ChunkMap::const_iterator it = chunks.find(Coords(x, z));\n    return it == chunks.end() ? NULL : it->second;\n  }\n\n  // Light get/set\n  bool getLight(int x, int y, int z, uint8_t* blocklight, uint8_t* skylight);\n  bool getLight(int x, int y, int z, uint8_t* blocklight, uint8_t* skylight, sChunk* chunk);\n  bool setLight(int x, int y, int z, int blocklight, int skylight, int setLight);\n  bool setLight(int x, int y, int z, int blocklight, int skylight, int setLight, sChunk* chunk);\n  void spreadLight(int x, int y, int z, int light_value, uint8_t type /* 0: sky, 1: block */);\n\n  // Block value/meta get/set\n  bool getBlock(int x, int y, int z, uint8_t* type, uint8_t* meta, bool generate = true);\n  bool getBlock(int x, int y, int z, uint8_t* type, uint8_t* meta, bool generate, sChunk* chunk);\n  bool getBlock(vec pos, uint8_t* type, uint8_t* meta)\n  {\n    return getBlock(pos.x(), pos.y(), pos.z(), type, meta);\n  }\n  bool setBlock(int x, int y, int z, char type, char meta);\n  bool setBlock(vec pos, char type, char meta)\n  {\n    return setBlock(pos.x(), pos.y(), pos.z(), type, meta);\n  }\n\n  bool sendBlockChange(int x, int y, int z, int16_t type, char meta);\n  bool sendBlockChange(vec pos, int16_t type, char meta)\n  {\n    return sendBlockChange(pos.x(), pos.y(), pos.z(), type, meta);\n  }\n  bool sendNote(int x, int y, int z, char instrument, char pitch, int16_t blocktype);\n  bool sendNote(vec pos, char instrument, char pitch, int16_t blocktype)\n  {\n    return sendNote(pos.x(), pos.y(), pos.z(), instrument, pitch, blocktype);\n  }\n\n  bool sendPickupSpawn(spawnedItem item);\n  void createPickupSpawn(int x, int y, int z, int type, int count, int health, User* user);\n\n  bool sendProjectileSpawn(User* user, int8_t projID);\n\n  bool sendMultiBlocks(std::set<vec>& blocks);\n\n  bool sendExplosion(int x, int y, int z, float radius, std::vector<vec>&record, float velocity_x, float velocity_y, float velocity_z);\n};\n\n#endif\n"
  },
  {
    "path": "src/mcregion.cpp",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/*\n Original code: http://pastebin.com/niWTqLvk\n*/\n\n/*\nstruct RegionFile {\n    struct ChunkOffset {\n        int sector_number;\n        char sector_count;\n    } chunk_offsets[1024];\n\n    struct ChunkTimestamp {\n        int timestamp;\n    } chunk_timestamps[1024];\n\n    struct Sector {\n        int length;\n        char version;\n        char data[length - 1];\n    } sectors[file_length / 4096 - 1];\n}\n*/\n\n#include <vector>\n#include <cstdio>\n#include <cstring>\n#include <ctime>\n#include <sys/stat.h>\n\n#ifdef __unix__\n#include <dirent.h>\n#endif\n\n#ifdef __APPLE__\n#include <dirent.h>\n#endif\n\n#include \"mcregion.h\"\n#include \"constants.h\"\n#include \"logger.h\"\n#include \"nbt.h\"\n\nRegionFile::RegionFile(): sizeDelta(0), x(0), z(0)\n{\n\n}\n\nRegionFile::~RegionFile()\n{\n  //If open file, close it\n  if (regionFile != NULL)\n  {\n    fclose(regionFile);\n  }\n}\n\n//Opens the region file and reads offset and timestamp tables\nbool RegionFile::openFile(std::string mapDir, int32_t chunkX, int32_t chunkZ)\n{\n  this->x = chunkX;\n  this->z = chunkZ;\n  std::string strchunkZ;\n  std::string strchunkX;\n\n  //Convert chunk x and z pos to strings\n  my_itoa(abs(chunkZ >> 5), strchunkZ, 10);\n  //If negative, add - in front\n  if ((chunkZ < 0))\n  {\n    strchunkZ = \"-\" + strchunkZ;\n  }\n  my_itoa(abs(chunkX >> 5), strchunkX, 10);\n  if ((chunkX < 0))\n  {\n    strchunkX = \"-\" + strchunkX;\n  }\n\n  //Make sure we have the region directory inside mapDir\n  struct stat stFileInfo;\n  std::string regionDir = mapDir + PATH_SEPARATOR + \"region\";\n\n  if (stat(regionDir.c_str(), &stFileInfo) != 0)\n  {\n    if (!makeDirectory(regionDir))\n    {\n\n      exit(EXIT_FAILURE);\n    }\n  }\n\n  //If the file doesn't exist, create it, otherwise open it for reading and writing\n  if (stat(std::string(mapDir + \"/region/r.\" + strchunkX + \".\" + strchunkZ + \".mca\").c_str(), &stFileInfo) != 0)\n  {\n    //This will overwrite existing file\n    regionFile = fopen(std::string(mapDir + \"/region/r.\" + strchunkX + \".\" + strchunkZ + \".mca\").c_str(), \"wb+\");\n  }\n  else\n  {\n    regionFile = fopen(std::string(mapDir + \"/region/r.\" + strchunkX + \".\" + strchunkZ + \".mca\").c_str(), \"rb+\");\n  }\n\n  //Couldn't open the file?\n  if (regionFile == NULL)\n  {\n    std::cout << \"Failed to open file \" << std::string(mapDir + \"/region/r.\" + strchunkX + \".\" + strchunkZ + \".mca\") << std::endl;\n    return false;\n  }\n\n  //Store file length\n  fseek(regionFile, 0, SEEK_END);\n  fileLength = (uint32_t)ftell(regionFile);\n  fseek(regionFile, 0, SEEK_SET);\n\n\n  //New file?\n  if (fileLength < SECTOR_BYTES)\n  {\n    int zeroInt = 0;\n    //Offsets\n    for (unsigned int i = 0; i < SECTOR_INTS; i++)\n    {\n      fwrite(reinterpret_cast<const char*>(&zeroInt), 4, 1, regionFile);\n    }\n    //Timestamps\n    for (unsigned int i = 0; i < SECTOR_INTS; i++)\n    {\n      fwrite(reinterpret_cast<const char*>(&zeroInt), 4, 1, regionFile);\n    }\n\n    //Get new size\n    fseek(regionFile, 0, SEEK_END);\n    fileLength = (uint32_t)ftell(regionFile);\n    fseek(regionFile, 0, SEEK_SET);\n  }\n  //If not multiple of 4096, expand\n  if ((fileLength & 0xfff) != 0)\n  {\n    int zeroInt = 0;\n    for (uint32_t i = 0; i < 0xfff - (fileLength & 0xfff); i++)\n    {\n      fwrite(reinterpret_cast<const char*>(&zeroInt), 1, 1, regionFile);\n    }\n    //Get new size\n    fseek(regionFile, 0, SEEK_END);\n    fileLength = (uint32_t)ftell(regionFile);\n    fseek(regionFile, 0, SEEK_SET);\n  }\n  int sectorCount = fileLength / SECTOR_BYTES;\n\n  sectorFree.clear();\n  sectorFree.resize(sectorCount, true);\n  //Offsets\n  sectorFree[0] = false;\n  //Timestamps\n  sectorFree[1] = false;\n\n  fseek(regionFile, 0, SEEK_SET);\n\n  //Read sectors and mark used\n  for (uint32_t i = 0; i < SECTOR_INTS; i++)\n  {\n    uint32_t offset = 0;\n    fread(reinterpret_cast<char*>(&offset), 4, 1, regionFile);\n    offset = ntohl(offset);\n    offsets[i] = offset;\n    if (offset != 0 && (offset >> 8) + (offset & 0xFF) <= sectorFree.size())\n    {\n      for (uint32_t sectorNum = 0; sectorNum < (offset & 0xFF); sectorNum++)\n      {\n        sectorFree[(offset >> 8) + sectorNum] = false;\n      }\n    }\n  }\n  //Read timestamps\n  for (uint32_t i = 0; i < SECTOR_INTS; ++i)\n  {\n    uint32_t lastModValue = 0;\n    fread(reinterpret_cast<char*>(&lastModValue), 4, 1, regionFile);\n    lastModValue = ntohl(lastModValue);\n    timestamps[i] = lastModValue;\n  }\n  return true;\n}\n\n//Write chunk data to regionfile\nbool RegionFile::writeChunk(uint8_t* chunkdata, uint32_t datalen, int32_t x, int32_t z)\n{\n\n  x = x & 31;\n  z = z & 31;\n\n  uint32_t offset = getOffset(x, z);\n  uint32_t sectorNumber = offset >> 8;\n  uint32_t sectorsAllocated = offset & 0xFF;\n  uint32_t sectorsNeeded = (datalen + CHUNK_HEADER_SIZE) / SECTOR_BYTES + 1;\n\n  // maximum chunk size is 1MB\n  if (sectorsNeeded >= 256)\n  {\n    return false;\n  }\n\n  //Current space is large enought\n  if (sectorNumber != 0 && sectorsAllocated == sectorsNeeded)\n  {\n    //std::cout << \"Save rewrite\" << std::endl;\n    write(sectorNumber, chunkdata, datalen);\n  }\n  //Need more space!\n  else\n  {\n    //Free current sectors\n    for (uint32_t i = 0; i < sectorsAllocated; i++)\n    {\n      sectorFree[sectorNumber + i] = true;\n    }\n\n    //Search for first free sector\n    int runStart = -1;\n    for (uint32_t i = 2; i < sectorFree.size(); i++)\n    {\n      if (sectorFree[i])\n      {\n        runStart = i;\n        break;\n      }\n    }\n    uint32_t runLength = 0;\n\n    //Start searching for a free sector\n    if (runStart != -1)\n    {\n      for (uint32_t i = runStart; i < sectorFree.size(); i++)\n      {\n        //Not first?\n        if (runLength != 0)\n        {\n          if (sectorFree[i])\n          {\n            runLength++;\n          }\n          else\n          {\n            runLength = 0;\n          }\n        }\n        //Reset on first\n        else if (sectorFree[i])\n        {\n          runStart = i;\n          runLength = 1;\n        }\n\n        //We have the space\n        if (runLength >= sectorsNeeded)\n        {\n          break;\n        }\n      }\n    }\n\n    //Did we find the space we need?\n    if (runLength >= sectorsNeeded)\n    {\n      //std::cout << \"Save reuse\" << std::endl;\n      sectorNumber = runStart;\n      setOffset(x, z, (sectorNumber << 8) | sectorsNeeded);\n\n      //Reserve space\n      for (uint32_t i = 0; i < sectorsNeeded; i++)\n      {\n        sectorFree[sectorNumber + i] = false;\n      }\n      //Write data\n      write(sectorNumber, chunkdata, datalen);\n    }\n    //If no space, grow file\n    else\n    {\n      //std::cout << \"Save grow\" << std::endl;\n      fseek(regionFile, 0, SEEK_END);\n      sectorNumber = sectorFree.size();\n      char* zerobytes = new char[SECTOR_BYTES*sectorsNeeded];\n      memset(zerobytes, 0, SECTOR_BYTES * sectorsNeeded);\n      fwrite(zerobytes, SECTOR_BYTES * sectorsNeeded, 1, regionFile);\n      for (uint32_t i = 0; i < sectorsNeeded; i++)\n      {\n        sectorFree.push_back(false);\n      }\n      delete [] zerobytes;\n      sizeDelta += SECTOR_BYTES * sectorsNeeded;\n\n      //Write chunk data\n      write(sectorNumber, chunkdata, datalen);\n      //Write offset info to the file\n      setOffset(x, z, (sectorNumber << 8) | sectorsNeeded);\n    }\n  }\n  setTimestamp(x, z, int(std::time(NULL)));\n\n  return true;\n}\n\n//Read chunk data from the file\nbool RegionFile::readChunk(uint8_t* chunkdata, uint32_t* datalen, int32_t x, int32_t z)\n{\n  x = x & 31;\n  z = z & 31;\n\n  //std::cout << \"readChunk(\" << x << \",\" << z << \");\" << std::endl;\n\n  int offset = getOffset(x, z);\n  //std::cout << \"offset: \" << offset << std::endl;\n\n  //Chunk not found\n  if (offset == 0)\n  {\n    return false;\n  }\n  uint32_t sectorNumber = offset >> 8;\n  uint32_t numSectors = offset & 0xFF;\n\n  //Invalid sector\n  if (sectorNumber + numSectors > sectorFree.size())\n  {\n    std::cout << \"Invalid sector \" << offset << std::endl;\n    return false;\n  }\n\n  //Get to the chunk data\n  fseek(regionFile, sectorNumber * SECTOR_BYTES, SEEK_SET);\n\n  //Read chunkdata length from the file\n  uint32_t length = 0;\n  fread(reinterpret_cast<char*>(&length), 4, 1, regionFile);\n  length = ntohl(length); //Change byte order is not on big endian system\n\n  //Invalid length?\n  if (length > SECTOR_BYTES * numSectors)\n  {\n    std::cout << \"Invalid length \" << length << std::endl;\n    return false;\n  }\n\n  //Read version info\n  char version;\n  fread(&version, 1, 1, regionFile);\n  //TODO: do something with version?\n  if (version != VERSION_DEFLATE)\n  {\n    std::cout << \"Found gzipped region file, abort!\" << std::endl;\n    return false;\n  }\n\n  //Read chunkdata to the given buffer\n  *datalen = length - 1;\n  fread((char*)chunkdata, length - 1, 1, regionFile);\n\n  //std::cout << \"Read \" << *datalen << \" bytes!\" << std::endl;\n  return true;\n\n}\n\nvoid RegionFile::setOffset(int x, int z, int offset)\n{\n  offsets[(x + z * 32)] = offset;\n  fseek(regionFile, (x + z * 32) * 4, SEEK_SET);\n\n  offset = htonl(offset);\n  const char* tempBuf = (const char*)&offset;\n  fwrite(tempBuf, 4, 1, regionFile);\n}\n\nvoid RegionFile::setTimestamp(int x, int z, int timestamp)\n{\n  timestamps[(x + z * 32)] = timestamp;\n  fseek(regionFile, SECTOR_BYTES + (x + z * 32) * 4, SEEK_SET);\n  timestamp = htonl(timestamp);\n  fwrite(reinterpret_cast<const char*>(&timestamp), 4, 1, regionFile);\n}\n\nvoid RegionFile::write(int sectorNumber, uint8_t* data, uint32_t datalen)\n{\n  fseek(regionFile, sectorNumber * SECTOR_BYTES, SEEK_SET);\n  int chunklen = datalen + 1;\n  chunklen = htonl(chunklen);\n  fwrite(reinterpret_cast<const char*>(&chunklen), 4, 1, regionFile); // chunk length\n  char version = VERSION_DEFLATE;\n  fwrite(&version, 1, 1, regionFile); // chunk version number\n  fwrite((char*)data, datalen, 1, regionFile); // chunk data\n}\n\n\n//Function to grab a list of all the files in a folder, both win32 and linux\nint getdir(std::string dir, std::vector<std::string> &files)\n{\n#ifdef WIN32\n  HANDLE hFind = INVALID_HANDLE_VALUE;\n  WIN32_FIND_DATAA ffd; // File information\n  dir += \"\\\\*.*\";\n  hFind = FindFirstFileA(dir.c_str(), &ffd);\n\n  if (INVALID_HANDLE_VALUE == hFind)\n  {\n    return 0;\n  }\n\n  // List all the files in the directory with some info about them.\n  do\n  {\n    if (std::string(ffd.cFileName) != \".\" && std::string(ffd.cFileName) != \"..\")\n    {\n      files.push_back(ffd.cFileName);\n    }\n  }\n  while (FindNextFile(hFind, &ffd) != 0);\n\n  FindClose(hFind);\n#else\n  DIR* dp = NULL;\n  struct dirent* dirp = NULL;\n  if ((dp  = opendir(dir.c_str())) == NULL)\n  {\n    //std::cout << \"Error(\" << errno << \") opening \" << dir << std::endl;\n    return 0;\n  }\n\n  while ((dirp = readdir(dp)) != NULL)\n  {\n    if (std::string(dirp->d_name) != \".\" && std::string(dirp->d_name) != \"..\")\n    {\n      files.push_back(std::string(dirp->d_name));\n    }\n  }\n  closedir(dp);\n\n#endif\n  return 1;\n}\n\n//Simple check that a folder is like in old chunk format, not perfect\nbool isMapDir(std::string filename)\n{\n  std::string hexarray(\"0123456789abcdefghijklmnopqrstuvwxyz\");\n  if (filename.size() < 3)\n  {\n    for (size_t ch = 0; ch < filename.size(); ch ++)\n    {\n      bool found = false;\n      for (size_t check = 0; check < hexarray.length(); check++)\n      {\n        if (filename[ch] == hexarray[check])\n        {\n          found = true;\n          break;\n        }\n      }\n      if (!found)\n      {\n        return false;\n      }\n    }\n    return true;\n  }\n  return false;\n}\n\nbool convertMap(std::string mapDir)\n{\n  std::cout << \"Start conversion of \" << mapDir << std::endl;\n\n  struct stat stFileInfo;\n  std::string regionDir = mapDir + \"/region\";\n  if (stat(regionDir.c_str(), &stFileInfo) != 0)\n  {\n    std::cout << \"Creating region dir\" << std::endl;\n    if (!makeDirectory(regionDir))\n    {\n      exit(EXIT_FAILURE);\n    }\n  }\n  std::vector<std::string> files;\n  std::vector<std::string> files2;\n  std::vector<std::string> files3;\n  getdir(mapDir, files);\n  uint8_t* buffer = new uint8_t[ALLOCATE_NBTFILE*10];\n\n  RegionFile* region;\n  std::map<uint32_t, RegionFile*> fileMap;\n\n  //Loop every folder and subfolder there is\n  for (size_t i = 0; i < files.size(); i++)\n  {\n    if (isMapDir(files[i]))\n    {\n      std::string filename = mapDir + \"/\" + files[i];\n      files2.clear();\n      getdir(filename, files2);\n      for (size_t ii = 0; ii < files2.size(); ii++)\n      {\n        if (isMapDir(files2[ii]))\n        {\n          int32_t x, z;\n          filename = mapDir + \"/\" + files[i] + \"/\" + files2[ii];\n          files3.clear();\n\n          //Here we finally get to the chunk files\n          getdir(filename, files3);\n          for (size_t j = 0; j < files3.size(); j++)\n          {\n            if (files3[j].length() > 7 && files3[j].substr(files3[j].length() - 3) == \"dat\" && files3[j][0] == 'c')\n            {\n              filename = mapDir + \"/\" + files[i] + \"/\" + files2[ii] + \"/\" + files3[j];\n\n              //Load chunk file\n              NBT_Value* chunk = NBT_Value::LoadFromFile(filename);\n\n              if (chunk == NULL)\n              {\n                continue;\n              }\n\n              NBT_Value* level = (*chunk)[\"Level\"];\n\n              if (level == NULL)\n              {\n                delete chunk;\n                continue;\n              }\n\n              //Get chunk x and z pos\n              NBT_Value* xPos = (*level)[\"xPos\"];\n              NBT_Value* zPos = (*level)[\"zPos\"];\n              if (xPos && zPos)\n              {\n                x = *xPos;\n                z = *zPos;\n\n                //Optimization, store opened RegionFiles to array with hash\n                uint32_t hash = (((x >> 5) & 0xffff) << 16) | ((z >> 5) & 0xffff);\n\n                //Check for hash and correct chunk\n                if (fileMap.count(hash) && fileMap[hash]->x == x && fileMap[hash]->z == z)\n                {\n                  region = fileMap[hash];\n                }\n                else\n                {\n                  //If old hash exists\n                  if (fileMap.count(hash))\n                  {\n                    delete fileMap[hash];\n                    fileMap[hash] = NULL;\n                  }\n                  //std::cout << \"Create new file \"  << hash << std::endl;\n\n                  //Open up new RegionFile\n                  region = new RegionFile;\n                  fileMap[hash] = region;\n                  region->openFile(mapDir, x, z);\n                }\n\n                //Store NBT to memory (deflated)\n                uint32_t len = 0;\n                chunk->SaveToMemory(buffer, &len);\n\n                //Make sure deflation produces something\n                if (len > 0)\n                {\n                  region->writeChunk(buffer, len, x, z);\n                }\n                else\n                {\n                  std::cout << \"Chunk saving error at \" << x << \",\" << z << std::endl;\n                }\n              }\n              delete chunk;\n            }\n          }\n          std::cout << \".\";\n        }\n      }\n      std::cout << \"|\";\n    }\n  }\n\n  //Cleanup\n  delete [] buffer;\n\n  //Free RegionFiles\n  for (std::map<uint32_t, RegionFile*>::iterator it = fileMap.begin(); it != fileMap.end(); ++it)\n  {\n    if (fileMap[it->first] != NULL)\n    {\n      delete fileMap[it->first];\n    }\n  }\n  std::cout << \"converted\" << std::endl;\n\n  return true;\n}\n"
  },
  {
    "path": "src/mcregion.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _MCREGION_H_\n#define _MCREGION_H_\n\n#include <stdint.h>\n#include <string>\n\nenum { VERSION_GZIP = 1, VERSION_DEFLATE };\n\nclass RegionFile\n{\nprivate:\n  static const uint32_t SECTOR_BYTES = 4096;\n  static const uint32_t SECTOR_INTS = SECTOR_BYTES / 4;\n  static const uint32_t CHUNK_HEADER_SIZE = 5;\n\n  FILE* regionFile;\n  uint32_t fileLength;\n\n  uint32_t offsets[SECTOR_INTS];\n  int timestamps[SECTOR_INTS];\n  int sizeDelta; //Not used\n  std::vector<bool> sectorFree;\n\npublic:\n\n  int x, z; //The loaded chunk\n\n  RegionFile();\n  ~RegionFile();\n\n  bool openFile(std::string mapDir, int32_t x, int32_t z);\n  bool writeChunk(uint8_t* chunkdata, uint32_t datalen, int32_t x, int32_t z);\n  bool readChunk(uint8_t* chunkdata, uint32_t* datalen, int32_t x, int32_t z);\n\nprivate:\n\n  /* is this an invalid chunk coordinate? */\n  inline bool outOfBounds(int x, int z) const\n  {\n    return x < 0 || x >= 32 || z < 0 || z >= 32;\n  }\n\n  //Get chunk offset from the table\n  inline uint32_t getOffset(int x, int z) const\n  {\n    return offsets[(x + z * 32)];\n  }\n\n  //Check if the chunk at (x,z) exists\n  inline bool hasChunk(int x, int z) const\n  {\n    return getOffset(x, z) != 0;\n  }\n\n  //Set new offset for a chunk\n  void setOffset(int x, int z, int offset);\n\n  //Set timestamp\n  void setTimestamp(int x, int z, int timestamp);\n\n  // write a chunk data to the region file at specified sector number\n  void write(int sectorNumber, uint8_t* data, uint32_t datalen);\n};\n\n//For converting old mapformat to McRegion\nbool convertMap(std::string mapDir);\n\n#endif\n"
  },
  {
    "path": "src/metadata.cpp",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"metadata.h\"\n#include \"protocol.h\"\n\n\nvoid MetaDataElemByte::output(Packet& p) const\n{\n  int header = idx; /* 0 << 5 + idx */\n  p << (int8_t)header << (int8_t)val;\n}\n\nMetaDataElemByte::MetaDataElemByte(int8_t _idx, int8_t _val)\n{\n  idx = _idx;\n  val = _val;\n}\n\nvoid MetaDataElemShort::output(Packet& p) const\n{\n  int header = 1 << 5 | idx;\n  p << (int8_t)header << (int16_t)val;\n}\n\nMetaDataElemShort::MetaDataElemShort(int8_t _idx, int16_t _val)\n{\n  idx = _idx;\n  val = _val;\n}\n\nvoid MetaDataElemSlot::output(Packet& p) const\n{\n  int header = 5 << 5 | idx;\n  p << (int8_t)header << Protocol::slot(val);\n}\n\nMetaDataElemSlot::MetaDataElemSlot(int8_t _idx, Item _val)\n{\n  idx = _idx;\n  val = _val;\n}\n\n\nPacket& operator<<(Packet& p, const MetaData& m)\n{\n  for (std::vector<MetaDataElemPtr>::const_iterator i = m.m_elem.begin(); i != m.m_elem.end(); ++i)\n  {\n    (*i)->output(p);\n  }\n  p << (int8_t)127;\n  return p;\n}\n\nvoid MetaData::set(MetaDataElem* el)\n{\n  for (std::vector<MetaDataElemPtr>::iterator i = m_elem.begin(); i != m_elem.end(); ++i)\n  {\n    if ((*i)->idx == el->idx)\n    {\n      i->reset(el);\n      return;\n    }\n  }\n  m_elem.push_back(MetaDataElemPtr(el));\n}\n\nMetaDataElemPtr MetaData::get(int8_t idx)\n{\n  for (std::vector<MetaDataElemPtr>::iterator i = m_elem.begin(); i != m_elem.end(); ++i)\n  {\n    if ((*i)->idx == idx)\n    {\n      return *i;\n    }\n  }\n  return MetaDataElemPtr();\n}\n"
  },
  {
    "path": "src/metadata.h",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _METAINFO_H\n#define _METAINFO_H\n\n#include <vector>\n#include \"packets.h\"\n#include <memory>\n#include \"inventory.h\"\n\nclass MetaDataElem\n{\n  public:\n    virtual void output(Packet& p) const=0; // Pure Virtual\n    int8_t idx;\n};\n\nclass MetaDataElemByte : public MetaDataElem\n{\n  public:\n    MetaDataElemByte(int8_t _idx, int8_t _val);\n    void output(Packet& p) const;\n    int8_t val;\n};\n\nclass MetaDataElemShort : public MetaDataElem\n{\n  public:\n    MetaDataElemShort(int8_t _idx, int16_t _val);\n    void output(Packet& p) const;\n    int16_t val;\n};\n\nclass MetaDataElemSlot : public MetaDataElem\n{\n  public:\n    MetaDataElemSlot(int8_t _idx, Item _val);\n    void output(Packet& p) const;\n    Item val;\n};\n\ntypedef std::shared_ptr<MetaDataElem> MetaDataElemPtr;\n\n/* The MetaInfo class for storing and sending metainfo packages */\nclass MetaData\n{\n  friend Packet& operator<<(Packet& p, const MetaData& m);\n  public:\n    void set(MetaDataElem* p);\n    MetaDataElemPtr get(int8_t idx);\n  private:\n    std::vector<MetaDataElemPtr> m_elem;\n};\n\n#endif\n"
  },
  {
    "path": "src/mineserver.cpp",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"threadpool.h\"\n\n#ifdef DEBUG\n#ifdef _MSC_VER\n#define _CRTDBG_MAP_ALLOC\n#include <stdlib.h>\n#include <crtdbg.h>\n#endif\n#endif\n\n#ifdef  _WIN32\n#include <process.h>\n#include <direct.h>\n#else\n#include <netdb.h>  // for gethostbyname()\n#endif\n\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <signal.h>\n#include <errno.h>\n\n#include <sstream>\n#include <fstream>\n#include <iostream>\n\n#include \"mineserver.h\"\n#include \"signalhandler.h\"\n#include \"configure.h\"\n#include \"constants.h\"\n#include \"logger.h\"\n#include \"sockets.h\"\n#include \"tools.h\"\n#include \"random.h\"\n#include \"map.h\"\n#include \"user.h\"\n#include \"chat.h\"\n#include \"worldgen/mapgen.h\"\n#include \"worldgen/nethergen.h\"\n#include \"worldgen/heavengen.h\"\n#include \"worldgen/biomegen.h\"\n#include \"worldgen/eximgen.h\"\n#include \"config.h\"\n#include \"config/node.h\"\n#include \"nbt.h\"\n#include \"packets.h\"\n#include \"physics.h\"\n#include \"redstoneSimulation.h\"\n#include \"plugin.h\"\n#include \"furnaceManager.h\"\n#include \"cliScreen.h\"\n#include \"mob.h\"\n#include \"protocol.h\"\n//#include \"minecart.h\"\n#ifdef WIN32\nstatic bool quit = false;\n#endif\n\nint setnonblock(int fd)\n{\n#ifdef WIN32\n  u_long iMode = 1;\n  ioctlsocket(fd, FIONBIO, &iMode);\n#else\n  int flags;\n\n  flags  = fcntl(fd, F_GETFL);\n  flags |= O_NONBLOCK;\n  fcntl(fd, F_SETFL, flags);\n#endif\n\n  return 1;\n}\n\nMineserver *ServerInstance = NULL;\n\nstd::string removeChar(std::string str, const char* c)\n{\n  const size_t loc = str.find(c);\n  if (loc != std::string::npos)\n  {\n    return str.replace(loc, 1, \"\");\n  }\n  return str;\n}\n\n// What is the purpose of \"code\"? -- louisdx\n// God I have no clue.. some day someone will fix it - Justasic\nint printHelp(int code)\n{\n  std::cout\n      << \"Mineserver \" << VERSION << \"\\n\"\n      << \"Usage: mineserver [CONFIG_FILE] [OVERRIDE]...\\n\"\n      << \"   or: mineserver -h|--help\\n\"\n      << \"\\n\"\n      << \"Syntax for overrides is: +VARIABLE=VALUE\\n\"\n      << \"\\n\"\n      << \"Examples:\\n\"\n      << \"  mineserver /etc/mineserver/config.cfg +system.path.home=\\\"/var/lib/mineserver\\\" +net.port=25565\\n\";\n  return code;\n}\n\n#include <stdtime.h>\n\nTime systemboot;\n\n// Main :D\nint main(int argc, char* argv[])\n{\n#ifdef _WIN32\n    /// Initialize systemboot Time object\n    LARGE_INTEGER c;\n    QueryPerformanceCounter(&c);\n    auto current_time = std::chrono::system_clock::now();\n    LARGE_INTEGER freq;\n    QueryPerformanceFrequency(&freq);\n    auto boot_time = current_time - std::chrono::milliseconds(uint64_t(double(c.QuadPart) * 1000 / freq.QuadPart));\n\n    uint64_t msecs = std::chrono::duration_cast<std::chrono::microseconds>(boot_time.time_since_epoch()).count();\n    systemboot = Time(msecs/1000000,msecs % 1000000);\n#endif\n\n  bool ret = false;\n#ifdef DEBUG\n#ifdef _MSC_VER\n  _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );\n#endif\n#endif\n\n  using namespace std;\n  // Try and start a new server instance\n  try{\n    new Mineserver(argc, argv);\n  }\n  catch (CoreException &e)\n  {\n    cout<<\"new Mineserver() raised CoreException of type '\"<<typeid(e).name()<<\n          \"' reason: \"<<e.GetReason()<<endl;\n    return EXIT_FAILURE;\n  }\n  catch (std::exception& e){\n    cout<<\"new Mineserver() raised std::exception of type '\"<<typeid(e).name()<<\n          \"' reason: \"<<e.what()<<endl;\n    return EXIT_FAILURE;\n  }\n\n  try{\n    try{\n      ret = ServerInstance->run();\n    }\n    catch (CoreException &e)\n    {\n      cout<<\"Mineserver::run() raised CoreException of type '\"<<typeid(e).name()<<\n            \"' reason: \"<<e.GetReason()<<endl;\n      throw;\n    }\n    catch (std::exception& e){\n      cout<<\"Mineserver::run() raised std::exception of type '\"<<typeid(e).name()<<\n            \"' reason: \"<<e.what()<<endl;\n      throw;\n    }\n  }\n  catch(...){\n    LOG2(CRITICAL, \"Saving worlds.\");\n    ServerInstance->saveAll();\n    LOG2(NOTICE, \"Worlds saved successfully!\");\n    return EXIT_FAILURE;\n  }\n\n  delete ServerInstance;\n  \n  return ret ? EXIT_SUCCESS : EXIT_FAILURE;\n}\n\nMineserver::Mineserver(int args, char **argarray)\n  :  argv(argarray),\n     argc(args),\n     m_socketlisten  (0),\n     m_saveInterval  (0),\n     m_lastSave      (std::time(NULL)),\n     m_pvp_enabled   (false),\n     m_damage_enabled(false),\n     m_only_helmets  (false),\n     m_running       (false),\n     m_eventBase     (nullptr),\n\n     // core modules\n     m_config        (new Config()),\n     m_screen        (new CliScreen()),\n     m_logger        (new Logger()),\n\n     m_plugin        (nullptr),\n     m_chat          (nullptr),\n     m_furnaceManager(nullptr),\n     m_packetHandler (nullptr),\n     m_inventory     (nullptr),\n     m_mobs          (nullptr),\n     m_threadpool    (nullptr)\n{\n  ServerInstance = this;\n  InitSignals();\n  \n  std::srand((uint32_t)std::time(NULL));\n  initPRNG();\n  \n  std::string cfg;\n  std::vector<std::string> overrides;\n\n  for (int i = 1; i < argc; i++)\n  {\n    const std::string arg(argv[i]);\n    \n    switch (arg[0])\n    {\n    case '-':   // option\n      // we have only '-h' and '--help' now, so just return with help\n      printHelp(0);\n      throw CoreException();\n      \n    case '+':   // override\n      overrides.push_back(arg.substr(1));\n      break;\n      \n    default:    // otherwise, it is config file\n      if (!cfg.empty())\n        throw CoreException(\"Only single CONFIG_FILE argument is allowed!\");\n      cfg = arg;\n      break;\n    }\n  }\n  \n  const std::string path_exe = \"./\";\n  \n  // If config file is provided as an argument\n  if (!cfg.empty())\n  {\n    std::cout << \"Searching for configuration file...\" << std::endl;\n    if (fileExists(cfg))\n    {\n      const std::pair<std::string, std::string> fullpath = pathOfFile(cfg);\n      cfg = fullpath.first + PATH_SEPARATOR + fullpath.second;\n      this->config()->config_path = fullpath.first;\n    }\n    else\n    {\n      std::cout << \"Config not found...\\n\";;\n      cfg.clear();\n    }\n  }\n  \n  if (cfg.empty())\n  {\n    if (fileExists(path_exe + PATH_SEPARATOR + CONFIG_FILE))\n    {\n      cfg = path_exe + PATH_SEPARATOR + CONFIG_FILE;\n      this->config()->config_path = path_exe;\n    }\n    else\n    {\n      std::cout << \"Config not found\\n\";\n    }\n  }\n  \n  // load config\n  Config &configvar = *this->config();\n  if (!configvar.load(cfg))\n  {\n    throw CoreException(\"Could not load config!\");\n  }  \n  \n  m_plugin = new Plugin();\n\n  LOG2(INFO, \"Using config: \" + cfg);\n  \n  if (overrides.size())\n  {\n    std::stringstream override_config;\n    for (size_t i = 0; i < overrides.size(); i++)\n    {\n      LOG2(INFO, \"Overriden: \" + overrides[i]);\n      override_config << overrides[i] << ';' << std::endl;\n    }\n    // override config\n    if (!configvar.load(override_config))\n      throw CoreException(\"Error when parsing overrides: maybe you forgot to doublequote string values?\");\n  }\n\n  initConstants();\n  // Write PID to file\n  std::ofstream pid_out((config()->sData(\"system.pid_file\")).c_str());\n  if (!pid_out.fail())\n  {\n    pid_out << getpid();\n  }\n  pid_out.close();\n    \n  // Init threadpool with thread count\n  // ToDo: thread count from the config\n  setThreadpool(new ThreadPool());\n  getThreadpool()->setThreadCount(2);\n\n  init_plugin_api();\n\n  if (config()->bData(\"system.interface.use_cli\"))\n  {\n    // Init our Screen\n    screen()->init(VERSION);\n  }\n\n\n  LOG2(INFO, \"Welcome to Mineserver v\" + VERSION);\n  LOG2(INFO, \"Using:\");\n  LOG2(INFO, \"  zlib \"+std::string(ZLIB_VERSION));\n  LOG2(INFO, \"  libevent \"+std::string(event_get_version()));\n  LOG2(INFO, \"  \"+std::string(OPENSSL_VERSION_TEXT));\n\n#ifdef PROTOCOL_ENCRYPTION\n\n  SSL_library_init();\n\n  LOG2(INFO, \"Generating RSA key pair for protocol encryption\");\n  //Protocol encryption\n  srand(microTime());\n  #if OPENSSL_VERSION_NUMBER < 0x10000000L\n  if((rsa = RSA_generate_key(1024, 17, 0, 0)) == NULL)\n  #else\n  EVP_PKEY_CTX *temp_ctx;\n  temp_ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);\n  if (!temp_ctx) {\n      LOG2(ERROR, \"ctx is NULL\");\n      goto keygenfail;\n  }\n  if (EVP_PKEY_keygen_init(temp_ctx) <= 0) {\n      LOG2(ERROR, \"EVP_PKEY_keygen_init failed\");\n      goto keygenfail;\n  }\n  if (EVP_PKEY_CTX_set_rsa_keygen_bits(temp_ctx, 1024) <= 0) {\n      LOG2(ERROR, \"EVP_PKEY_CTX_set_rsa_keygen_bits failed\");\n      goto keygenfail;\n  }\n  \n  BIGNUM* exponent_bn = BN_new();\n  BN_set_word(exponent_bn, 17);\n  if(EVP_PKEY_CTX_set_rsa_keygen_pubexp(temp_ctx, exponent_bn) <= 0) {\n      LOG2(ERROR, \"EVP_PKEY_CTX_set_rsa_keygen_pubexp failed\");\n      goto keygenfail;\n  } \n  \n  /* Generate key */\n  if (EVP_PKEY_keygen(temp_ctx, &pk) <= 0) {\n      LOG2(ERROR, \"EVP_PKEY_keygen failed\");\n      goto keygenfail;\n  }\n\n  //BN_free(exponent_bn);\n  EVP_PKEY_CTX_free(temp_ctx);\n  goto keygenpass;\n  #endif\n  {\n    keygenfail:\n    LOG2(INFO, \"KEY GENERATION FAILED!\");\n    exit(1);\n  }\n  keygenpass:\n  LOG2(INFO, \"RSA key pair generated.\");\n  #if OPENSSL_VERSION_NUMBER < 0x10000000L\n  EVP_PKEY_assign_RSA(pk,rsa);\n  /* Get ASN.1 format public key */\n  x=X509_new();\n\n  X509_set_version(x,0);\n  X509_set_pubkey(x,pk);\n\n  int len;\n  unsigned char *buf;\n  buf = NULL;\n  len = i2d_X509(x, &buf);\n\n  //Glue + jesus tape, dont ask - Fador\n  publicKey = std::string((char *)(buf+28),160);\n  OPENSSL_free(buf);\n  #else\n  char rawBuffer[8192];  \n  unsigned char* ptr = (unsigned char*)&rawBuffer[0];\n  int buffSize = i2d_PUBKEY(pk, (unsigned char**)&ptr);\n  std::string pubkey_temp(rawBuffer, buffSize);\n  publicKey = pubkey_temp;\n  eng = ENGINE_get_default_RSA();\n  crypto_ctx = EVP_PKEY_CTX_new(pk, eng);\n  if (!crypto_ctx) {\n    LOG2(INFO, \"KEY GENERATION FAILED!\");\n    exit(1);\n  }\n  if (EVP_PKEY_decrypt_init(crypto_ctx) <= 0) {\n    LOG2(INFO, \"KEY GENERATION FAILED!\");\n    exit(1);\n  }\n  if (EVP_PKEY_CTX_set_rsa_padding(crypto_ctx, RSA_PKCS1_PADDING) <= 0) {\n    LOG2(INFO, \"KEY GENERATION FAILED!\");\n    exit(1);\n  }\n\n  #endif\n  \n\n#endif\n\n  /* END key fetching */\n\n  const std::string temp_nums=\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-\";\n\n  const std::string temp_hex=\"0123456789abcdef\";\n\n  for(int i = 0; i < 4; i++)\n  {\n    encryptionBytes += (char)(temp_nums[rand()%temp_nums.size()]);\n  }\n  \n  for(int i = 0; i < 16; i++)\n  {\n    serverID += (char)(temp_hex[rand()%temp_hex.size()]);\n  }\n\n  LOG2(INFO, \"ServerID: \" + serverID);\n  \n  if(!m_config->bData(\"system.user_validation\"))\n  {\n    serverID = \"-\";\n  }\n\n  MapGen* mapgen = new MapGen();\n  MapGen* nethergen = new NetherGen();\n  MapGen* heavengen = new HeavenGen();\n  MapGen* biomegen = new BiomeGen();\n  MapGen* eximgen = new EximGen();\n  m_mapGenNames.push_back(mapgen);\n  m_mapGenNames.push_back(nethergen);\n  m_mapGenNames.push_back(heavengen);\n  m_mapGenNames.push_back(biomegen);\n  m_mapGenNames.push_back(eximgen);\n\n  m_saveInterval = m_config->iData(\"map.save_interval\");\n\n  m_only_helmets = m_config->bData(\"system.armour.helmet_strict\");\n  m_pvp_enabled = m_config->bData(\"system.pvp.enabled\");\n  m_damage_enabled = m_config->bData(\"system.damage.enabled\");\n\n  const char* key = \"map.storage.nbt.directories\"; // Prefix for worlds config\n  if (m_config->has(key) && (m_config->type(key) == CONFIG_NODE_LIST))\n  {\n    std::list<std::string> tmp = m_config->mData(key)->keys();\n    int n = 0;\n    for (std::list<std::string>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)\n    {\n      Map* map = new Map();\n      m_map.push_back(map);\n\n      Physics* phy = map->physics = new Physics(map);\n\n      m_physics.push_back(map->physics);\n      RedstoneSimulation* red = new RedstoneSimulation;\n      red->map = n;\n      m_redstone.push_back(red);\n      int k = m_config->iData((std::string(key) + \".\") + (*it));\n      if ((uint32_t)k >= m_mapGenNames.size())\n      {\n        std::ostringstream s;\n        s << \"Error! Mapgen number \" << k << \" in config. \" << m_mapGenNames.size() << \" Mapgens known\";\n        LOG2(INFO, s.str());\n      }\n      // WARNING: if k is too big this will be an access error! -- louisdx\n      MapGen* m = m_mapGenNames[k];\n      m_mapGen.push_back(m);\n      n++;\n    }\n  }\n  else\n  {\n    LOG2(WARNING, \"Cannot find map.storage.nbt.directories.*\");\n  }\n\n  if (m_map.size() == 0)\n    throw CoreException(\"No worlds in Config\");\n\n  m_chat           = new Chat;\n  m_furnaceManager = new FurnaceManager;\n  m_packetHandler  = new PacketHandler;\n  m_inventory      = new Inventory(m_config->sData(\"system.path.data\") + '/' + \"recipes\", \".recipe\", \"ENABLED_RECIPES.cfg\");\n  m_mobs           = new Mobs;\n\n  std::ostringstream s;\n  s << \"Known recipes for crafting: \" << m_inventory->recipes.size();\n  LOG2(INFO, s.str());\n\n} // End Mineserver constructor\n\nMineserver::~Mineserver()\n{\n  // Let the user know we're shutting the server down cleanly\n  LOG2(INFO, \"Shutting down...\");\n\n  // Close the cli session if its in use\n  if (config() && config()->bData(\"system.interface.use_cli\"))\n    screen()->end();\n\n  \n  if (m_threadpool != nullptr)\n  {\n    m_threadpool->shutdown();\n    delete m_threadpool;\n  }\n\n  // Free memory\n  for (std::vector<Map*>::size_type i = 0; i < m_map.size(); i++)\n  {\n    delete m_map[i];\n    delete m_physics[i];\n    delete m_redstone[i];\n    m_mapGen.clear();\n  }\n\n  delete m_chat;\n  delete m_furnaceManager;\n  delete m_packetHandler;\n  delete m_inventory;\n  delete m_mobs;\n\n  for(int i = m_mapGenNames.size()-1; i >= 0 ; i--)\n  {\n    delete m_mapGenNames[i];\n  }\n\n  if (m_plugin)\n  {\n    delete m_plugin;\n    m_plugin = NULL;\n  }\n\n  // Remove the PID file\n  unlink((config()->sData(\"system.pid_file\")).c_str());\n#ifdef PROTOCOL_ENCRYPTION\n  //RSA_free(rsa);\n  //X509_free(x);  \n  EVP_PKEY_free(pk);\n  pk = NULL;\n#endif\n}\n\n\nevent_base* Mineserver::getEventBase()\n{\n  return m_eventBase;\n}\n\nvoid Mineserver::saveAll()\n{\n  for (std::vector<Map*>::size_type i = 0; i < m_map.size(); i++)\n  {\n    m_map[i]->saveWholeMap();\n  }\n  saveAllPlayers();\n}\n\nvoid Mineserver::saveAllPlayers()\n{\n  for (std::set<User*>::const_iterator it = users().begin(); it != users().end(); ++it)\n  {\n    if ((*it)->logged) (*it)->saveData();\n  }\n}\n\nsize_t Mineserver::getLoggedUsersCount()\n{\n  size_t count = 0;\n  for(std::set<User*>::const_iterator it = users().begin(); it != users().end(); ++it) {\n    if((*it)->logged) count++;\n  }\n  return count;\n}\n\n\nvoid timer200ms(int fd, short event, void *arg) {\n  timeval timerTime200ms;\n  timerTime200ms.tv_sec  = 0;\n  timerTime200ms.tv_usec = 200000; // 200ms\n  evtimer_add(&ServerInstance->ev_200ms, &timerTime200ms);\n  ServerInstance->timed_200ms();\n}\n\nvoid timer1000ms(int fd, short event, void *arg) {\n\n  timeval timerTime1000ms;\n  timerTime1000ms.tv_sec  = 1;\n  timerTime1000ms.tv_usec = 0;\n  evtimer_add(&ServerInstance->ev_1000ms, &timerTime1000ms);\n  ServerInstance->timed_1s();\n}\n\nvoid timer10s(int fd, short event, void *arg) {\n\n  timeval timerTime10s;\n  timerTime10s.tv_sec  = 10;\n  timerTime10s.tv_usec = 0;\n  evtimer_add(&ServerInstance->ev_10s, &timerTime10s);\n  ServerInstance->timed_10s();\n}\n\nbool Mineserver::run()\n{\n  uint32_t starttime = (uint32_t)time(0);\n  uint32_t tick      = (uint32_t)time(0);\n\n\n  // load plugins\n  if (config()->has(\"system.plugins\") && (config()->type(\"system.plugins\") == CONFIG_NODE_LIST))\n  {\n    std::list<std::string> tmp = config()->mData(\"system.plugins\")->keys();\n    for (std::list<std::string>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)\n    {\n      std::string path  = config()->sData(\"system.path.plugins\");\n      std::string name  = config()->sData(\"system.plugins.\" + (*it));\n      std::string alias = *it;\n      if (name[0] == '_')\n      {\n        path = \"\";\n        alias = name;\n        name = name.substr(1);\n      }\n\n      plugin()->loadPlugin(name, path, alias);\n    }\n  }\n\n  // Initialize map\n  for (int i = 0; i < (int)m_map.size(); i++)\n  {\n    physics(i)->enabled = (config()->bData(\"system.physics.enabled\"));\n    redstone(i)->enabled = (config()->bData(\"system.redstone.enabled\"));\n\n    m_map[i]->init(i);\n    if (config()->bData(\"map.generate_spawn.enabled\"))\n    {\n      LOG2(INFO, \"Generating spawn area...\");\n      int size = config()->iData(\"map.generate_spawn.size\");\n      bool show_progress = config()->bData(\"map.generate_spawn.show_progress\");\n#ifdef __FreeBSD__\n      show_progress = false;\n#endif\n\n#ifdef WIN32\n      DWORD t_begin = 0, t_end = 0;\n#else\n      clock_t t_begin = 0, t_end = 0;\n#endif\n\n      for (int x = -size; x <= size; x++)\n      {\n        if (show_progress)\n        {\n#ifdef WIN32\n          t_begin = timeGetTime();\n#else\n          t_begin = clock();\n#endif\n        }\n        for (int z = -size; z <= size; z++)\n        {\n          m_map[i]->loadMap(x, z);\n        }\n\n        if (show_progress)\n        {\n#ifdef WIN32\n          t_end = timeGetTime();\n          LOG2(INFO, dtos((x + size + 1) *(size * 2 + 1)) + \"/\" + dtos((size * 2 + 1) *(size * 2 + 1)) + \" done. \" + dtos((t_end - t_begin) / (size * 2 + 1)) + \"ms per chunk\");\n#else\n          t_end = clock();\n          LOG2(INFO, dtos((x + size + 1) *(size * 2 + 1)) + \"/\" + dtos((size * 2 + 1) *(size * 2 + 1)) + \" done. \" + dtos(((t_end - t_begin) / (CLOCKS_PER_SEC / 1000)) / (size * 2 + 1)) + \"ms per chunk\");\n#endif\n        }\n      }\n    }\n    // Choose proper spawn position\n    m_map[i]->chooseSpawnPosition();\n#ifdef DEBUG\n    LOG(DEBUG, \"Map\", \"Spawn area ready!\");\n#endif\n  }\n\n  // Initialize packethandler\n  packetHandler()->init();\n\n  // Load ip from config\n  const std::string ip = config()->sData(\"net.ip\");\n\n  // Load port from config\n  const int port = config()->iData(\"net.port\");\n\n#ifdef WIN32\n  WSADATA wsaData;\n  int iResult;\n  // Initialize Winsock\n  iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);\n  if (iResult != 0)\n  {\n    LOG2(ERROR, std::string(\"WSAStartup failed with error: \" + iResult));\n    return false;\n  }\n#endif\n\n  struct sockaddr_in addresslisten;\n  int reuse = 1;\n\n  m_eventBase = reinterpret_cast<event_base*>(event_init());\n#ifdef WIN32\n  m_socketlisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n#else\n  m_socketlisten = socket(AF_INET, SOCK_STREAM, 0);\n#endif\n\n  if (m_socketlisten < 0)\n  {\n    LOG2(ERROR, \"Failed to create listen socket\");\n    return false;\n  }\n\n  memset(&addresslisten, 0, sizeof(addresslisten));\n\n  addresslisten.sin_family      = AF_INET;\n  addresslisten.sin_addr.s_addr = inet_addr(ip.c_str());\n  addresslisten.sin_port        = htons(port);\n\n  //Reuse the socket\n  setsockopt(m_socketlisten, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse));\n\n  // Bind to port\n  if (bind(m_socketlisten, (struct sockaddr*)&addresslisten, sizeof(addresslisten)) < 0)\n  {\n    LOG2(ERROR, \"Failed to bind to \" + ip + \":\" + dtos(port));\n    return false;\n  }\n\n  if (listen(m_socketlisten, 5) < 0)\n  {\n    LOG2(ERROR, \"Failed to listen to socket\");\n    return false;\n  }\n\n  setnonblock(m_socketlisten);\n\n  m_listenEvent = event_new(m_eventBase, m_socketlisten, EV_WRITE | EV_READ | EV_PERSIST, accept_callback, 0);\n  event_add(m_listenEvent, 0);\n\n  LOG2(INFO, \"Listening on: \");\n  if (ip == \"0.0.0.0\")\n  {\n    // Print all local IPs\n    char name[255];\n    gethostname(name, sizeof(name));\n    struct hostent* hostinfo = gethostbyname(name);\n    int ipIndex = 0;\n    while (hostinfo && hostinfo->h_addr_list[ipIndex])\n    {\n      const std::string ip(inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[ipIndex++]));\n      LOG2(INFO, ip + \":\" + dtos(port));\n    }\n  }\n  else\n  {\n    LOG2(INFO, ip + \":\" + dtos(port));\n  }\n\n  //Let event_base_loop lock for 200ms\n  timeval loopTime;\n  loopTime.tv_sec  = 0;\n  loopTime.tv_usec = 200000; // 200ms\n\n  timeval timerTime200ms;\n  timerTime200ms.tv_sec  = 0;\n  timerTime200ms.tv_usec = 200000; // 200ms\n\n  timeval timerTime1000ms;\n  timerTime1000ms.tv_sec  = 1;\n  timerTime1000ms.tv_usec = 0;\n\n  timeval timerTime10s;\n  timerTime10s.tv_sec  = 10;\n  timerTime10s.tv_usec = 0;\n\n  m_running = true;\n\n  // Set timed functions to run\n  evtimer_set(&ev_200ms, timer200ms, NULL);\n  evtimer_add(&ev_200ms, &timerTime200ms);\n\n  evtimer_set(&ev_1000ms, timer1000ms, NULL);\n  evtimer_add(&ev_1000ms, &timerTime1000ms);\n\n  evtimer_set(&ev_10s, timer10s, NULL);\n  evtimer_add(&ev_10s, &timerTime10s);\n\n  /// #mainloop\n  while (m_running)\n  {\n    event_base_loopexit(m_eventBase, &loopTime);\n\n    if(event_base_loop(m_eventBase, 0) != 0)\n      break;\n  }\n\n#ifdef WIN32\n  closesocket(m_socketlisten);\n#else\n  close(m_socketlisten);\n#endif\n\n  saveAll();\n\n  event_base_free(m_eventBase);\n\n  return true;\n}\n\nvoid Mineserver::timed_200ms()\n{\n  // Run 200ms timer hook\n  runAllCallback(\"Timer200\");\n\n  // Alert any block types that care about timers\n  for (size_t i = 0 ; i < plugin()->getBlockCB().size(); ++i)\n  {\n    const BlockBasicPtr blockcb = plugin()->getBlockCB()[i];\n    if (blockcb != NULL)\n    {\n      blockcb->timer200();\n    }\n  }\n\n  //Update physics every 200ms\n  for (std::vector<Map*>::size_type i = 0 ; i < m_map.size(); i++)\n  {\n    physics(i)->update();\n    redstone(i)->update();\n  }\n\n  /// Drowning/suffocating\n  for ( User* const& u : m_users)\n  {\n    u->isUnderwater();\n    if (u->pos.y < 0)\n    {\n      u->sethealth(u->health - 5);\n    }\n  }\n}\n\nvoid Mineserver::timed_1s()\n{\n  // Run 1s timer hook\n  runAllCallback(\"Timer1000\");\n\n  // Loop users\n  for (User* const &u : m_users)\n  {\n    // No data received in 30s, timeout\n    if (u->logged && time(0)- u->lastData > 30)\n    {\n      LOG2(INFO, \"Player \" + u->nick + \" timed out\");\n      m_usersToRemove.insert(u);\n\n    }\n    else if (!u->logged && time(0) - u->lastData > 100)\n    {\n      m_usersToRemove.insert(u);\n    }\n    else\n    {\n#ifdef DEBUG\n      std::stringstream temp; temp << u->packetsPerSecond;\n      LOG2(INFO, \"Player \" + u->nick + \" \" + temp.str() + \" packets per second\");\n#endif\n      u->packetsPerSecond = 0;   \n      if (m_damage_enabled)\n      {\n        u->checkEnvironmentDamage();\n      }\n      u->pushMap();\n      u->popMap();\n    }\n  }\n\n  \n  //Remove any users pending removal\n  if(m_usersToRemove.size())\n  {\n    for (std::set<User*>::iterator it = m_usersToRemove.begin(); it != m_usersToRemove.end(); it++)\n    {\n      User* u = *it;\n      delete u;\n      u = 0;\n    }\n    m_usersToRemove.clear();\n  }\n\n  for (std::vector<Map*>::size_type i = 0 ; i < m_map.size(); i++)\n  {\n    m_map[i]->mapTime += 20;\n    if (m_map[i]->mapTime >= 24000)\n    {\n      m_map[i]->mapTime = 0;\n    }\n  }\n\n  // Check for Furnace activity\n  furnaceManager()->update();\n\n  // Check for user validation results\n  std::unique_lock<std::mutex> l(ServerInstance->m_validation_mutex);\n  for(size_t i = 0; i < ServerInstance->validatedUsers.size(); i++)\n  {\n    //To make sure user hasn't timed out or anything while validating\n    User *tempuser = NULL;\n    for (std::set<User*>::const_iterator it = users().begin(); it != users().end(); ++it)\n    {\n      if((*it)->UID == ServerInstance->validatedUsers[i].UID)\n      {\n        tempuser = (*it);\n        break;\n      }\n    }\n\n    if(tempuser != NULL)\n    {\n      if(ServerInstance->validatedUsers[i].valid)\n      {\n        LOG(INFO, \"Packets\", tempuser->nick + \" is VALID \");\n        tempuser->sendLoginInfo();        \n      }\n      else\n      {\n        tempuser->kick(\"User not Premium\");\n      }\n    }\n  }\n  ServerInstance->validatedUsers.clear();\n  l.unlock();\n\n}\n\nvoid Mineserver::timed_10s()\n{\n  // Run 10s timer hook\n  runAllCallback(\"Timer10000\");\n\n  //Map saving on configurable interval\n  if (m_saveInterval != 0 && time(0) - m_lastSave >= m_saveInterval)\n  {\n    //Save\n    saveAll();\n\n    m_lastSave = time(0);\n  }\n\n  // If users, ping them\n  if (!User::all().empty())\n  {\n    // Send server time and keepalive\n    (*User::all().begin())->sendAll(Protocol::timeUpdate(m_map[0]->mapTime));\n    (*User::all().begin())->sendAll(Protocol::keepalive(0));\n    //(*User::all().begin())->sendAll(Protocol::playerlist());\n  }\n\n  //Check for tree generation from saplings\n  for (size_t i = 0; i < m_map.size(); ++i)\n  {\n    m_map[i]->checkGenTrees();\n  }\n\n  // Loop every loaded chunk and release unused  \n  for (Map* map : m_map)\n  {\n    std::vector<vec> mapsToRemove;\n    for (auto it : map->chunks)\n    {      \n      if (time(0) - it.second->lastused > 60 && it.second->users.empty())\n      {\n        mapsToRemove.push_back(vec(it.first.first, 0, it.first.second));\n      }\n    }\n    for (vec rem : mapsToRemove)\n    {\n      map->releaseMap(rem.x(), rem.z());\n    }\n  }\n}\n\nbool Mineserver::stop()\n{\n  m_running = false;\n  return true;\n}\n\nMap* Mineserver::map(size_t n) const\n{\n  if (n < m_map.size())\n  {\n    return m_map[n];\n  }\n  LOG2(WARNING, \"Nonexistent map requested. Map 0 passed\");\n  return m_map[0];\n}\n"
  },
  {
    "path": "src/mineserver.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _MINESERVER_H\n#define _MINESERVER_H\n\n#include <vector>\n#include <set>\n#include <string>\n#include <memory>\n#include <mutex>\n\n//Enable protocol encryption\n#define PROTOCOL_ENCRYPTION\n\n\n#ifdef WIN32\n// This is needed for event to work on Windows.\n#define NOMINMAX\n#include <winsock2.h>\n#else\n//Do not remove!! Required on Debian\n#include <sys/types.h>\n#endif\n#include <event.h>\n\n#ifdef PROTOCOL_ENCRYPTION\n#include <openssl/rsa.h>\n#include <openssl/x509v3.h>\n#include <openssl/rc4.h>\n#include <openssl/ssl.h>\n#if OPENSSL_VERSION_NUMBER > 0x10000000L\n#include <openssl/engine.h>\n#endif\n#endif\n\n#include \"extern.h\"\n\n#define MINESERVER\n#include \"plugin_api.h\"\n#undef MINESERVER\n\n#include \"threadpool.h\"\n\nstruct event_base;\n\nclass Mineserver\n{\npublic:\n  // Variables\n  char** argv;\n  int argc;\n  int m_socketlisten;\n  int m_saveInterval;\n  time_t m_lastSave;\n  bool m_pvp_enabled;\n  bool m_damage_enabled;\n  bool m_only_helmets;\n  struct event* m_listenEvent;\n  std::mutex m_validation_mutex;\n  struct userValidation { User* user; bool valid; uint32_t UID; };\n  std::vector<userValidation> validatedUsers;\n\n  #ifdef PROTOCOL_ENCRYPTION\n  //Protocol encryption\n  X509 *x;\n  EVP_PKEY *pk;\n  #if OPENSSL_VERSION_NUMBER < 0x10000000L\n  RSA *rsa;\n  #else\n  EVP_PKEY_CTX *crypto_ctx;  \n  ENGINE *eng;\n  #endif\n  std::string encryptionBytes;\n  std::string serverID;\n  std::string publicKey;\n  #endif\n\n  // Constructor/Destructor\n  Mineserver(int, char**);\n  ~Mineserver();\n\n  // Non-inline functions\n  bool run();\n\n  // Timed functions\n  void timed_200ms();\n  void timed_1s();\n  void timed_10s();\n\n  struct event ev_200ms;\n  struct event ev_1000ms;\n  struct event ev_10s;\n\n  bool stop();\n  \n  event_base* getEventBase();\n  Map* map(size_t n) const;\n  void saveAllPlayers();\n  void saveAll();\n  size_t getLoggedUsersCount();\n  bool configDirectoryPrepare(const std::string& path);\n  \n  static uint32_t generateEID()\n  {\n    static uint32_t m_EID = 0;\n    return ++m_EID;\n  }\n\n  // Inline functions\n  // Get the total number of connected users\n  inline std::set<User*>& users()\n  {\n    return m_users;\n  }\n\n  inline std::set<User*>& usersToRemove()\n  {\n    return m_usersToRemove;\n  }\n\n  inline const std::set<User*>& users() const\n  {\n    return m_users;\n  }\n\n  inline void setMap(Map* map, size_t n = 0)\n  {\n    m_map[n] = map;\n  }\n  \n  inline size_t mapCount()\n  {\n    return m_map.size();\n  }\n  \n  inline Chat* chat() const\n  {\n    return m_chat;\n  }\n  \n  inline void setChat(Chat* chat)\n  {\n    m_chat = chat;\n  }\n  \n  inline Mobs* mobs() const\n  {\n    return m_mobs;\n  }\n  \n  inline Plugin* plugin() const\n  {\n    return m_plugin;\n  }\n  \n  inline void setPlugin(Plugin* plugin)\n  {\n    m_plugin = plugin;\n  }\n  \n  inline std::shared_ptr<Screen> screen() const\n  {\n    return m_screen;\n  }\n  \n  inline void setScreen(std::shared_ptr<Screen> screen)\n  {\n    m_screen = screen;\n  }\n  \n  inline Physics* physics(size_t n) const\n  {\n    return m_physics[n];\n  }\n\n  inline RedstoneSimulation* redstone(size_t n) const\n  {\n    return m_redstone[n];\n  }\n\n  // Get the configuration pointer\n  inline std::shared_ptr<Config> config() const\n  {\n    return m_config;\n  }\n\n  // Set a pointer to the configuration file\n  inline void setConfig(std::shared_ptr<Config> config)\n  {\n    m_config = config;\n  }\n\n  inline FurnaceManager* furnaceManager() const\n  {\n    return m_furnaceManager;\n  }\n  \n  inline void setFurnaceManager(FurnaceManager* furnaceManager)\n  {\n    m_furnaceManager = furnaceManager;\n  }\n  \n  inline PacketHandler* packetHandler() const\n  {\n    return m_packetHandler;\n  }\n  \n  inline void setPacketHandler(PacketHandler* packetHandler)\n  {\n    m_packetHandler = packetHandler;\n  }\n  \n  inline MapGen* mapGen(size_t n) const\n  {\n    return m_mapGen[n];\n  }\n  \n  inline std::shared_ptr<Logger> logger() const\n  {\n    return m_logger;\n  }\n\n  // Set the logger to use\n  inline void setLogger(std::shared_ptr<Logger> logger)\n  {\n    m_logger = logger;\n  }\n  \n  inline Inventory* inventory() const\n  {\n    return m_inventory;\n  }\n\n  // Set a pointer to the inventory\n  inline void setInventory(Inventory* inventory)\n  {\n    m_inventory = inventory;\n      // was m_inventory = m_inventory before,\n      // which seems redundant. -- gk\n  }\n\n  inline void setThreadpool(ThreadPool* threadpool)\n  {\n    m_threadpool = threadpool;\n  }\n\n  inline ThreadPool* getThreadpool() const\n  {\n    return m_threadpool;\n  }\n\nprivate:\n\n  bool m_running;\n\n  event_base* m_eventBase;\n\n  // holds all connected users\n  std::set<User*>    m_users;\n  //Delayed user removal\n  std::set<User*>    m_usersToRemove;\n\n  std::vector<Map*>                m_map;\n  std::vector<Physics*>            m_physics;\n  std::vector<RedstoneSimulation*> m_redstone;\n  std::vector<MapGen*>             m_mapGenNames;\n  std::vector<MapGen*>             m_mapGen;\n\n  // core modules\n  std::shared_ptr<Config> m_config;\n  std::shared_ptr<Screen> m_screen;\n  std::shared_ptr<Logger> m_logger;\n\n  Plugin*         m_plugin;\n  Chat*           m_chat;\n  FurnaceManager* m_furnaceManager;\n  PacketHandler*  m_packetHandler;\n  Inventory*      m_inventory;\n  Mobs*           m_mobs;\n  ThreadPool*     m_threadpool;\n};\n\n#endif\n"
  },
  {
    "path": "src/mineserver.pro",
    "content": "TEMPLATE = app\nCONFIG += console\nCONFIG -= qt\n\n## TO Use this project file in windows:\n## set env var 'MINESERVER_WIN32_LIBS' to the directory containing mineservermingw libs\n\nwin32{\n\tLIBS += -L$$(MINESERVER_WIN32_LIBS)/lib\n\n\tLIBS += -lnoise -leay32 -lssleay32 -lssl32 -lpdcurses -lz -levent -lWs2_32 -lwinmm -lpthread\n\n\tINCLUDEPATH += $$(MINESERVER_WIN32_LIBS)/include\n\n\tQMAKE_LFLAGS += -Wl,--large-address-aware\n}\n\nunix{\n        LIBS += -lnoise -lssl -lcrypto -lcurses -lz -levent -ldl -lpthread\n}\n\nINCLUDEPATH += \"../include\"\n\nDEFINES = __GXX_EXPERIMENTAL_CXX0X__ MINESERVER_BUILD\n\nQMAKE_CXX += -std=c++0x\n\nSOURCES += \\\n    user.cpp \\\n    tree.cpp \\\n    tools.cpp \\\n    sockets.cpp \\\n    signalhandler.cpp \\\n    screenBase.cpp \\\n    redstoneSimulation.cpp \\\n    random.cpp \\\n    plugin_api.cpp \\\n    plugin.cpp \\\n    physics.cpp \\\n    packets.cpp \\\n    nbt.cpp \\\n    mob.cpp \\\n    mineserver.cpp \\\n    metadata.cpp \\\n    mcregion.cpp \\\n\t\tmap.cpp \\\n    logger.cpp \\\n    lighting.cpp \\\n    inventory.cpp \\\n    furnaceManager.cpp \\\n    furnace.cpp \\\n    constants.cpp \\\n    cliScreen.cpp \\\n    chat.cpp \\\n    config/scanner.cpp \\\n    config/parser.cpp \\\n    config/node.cpp \\\n    config/lexer.cpp \\\n    blocks/workbench.cpp \\\n    blocks/wool.cpp \\\n    blocks/wood.cpp \\\n    blocks/tracks.cpp \\\n    blocks/torch.cpp \\\n    blocks/tnt.cpp \\\n    blocks/step.cpp \\\n    blocks/stair.cpp \\\n    blocks/snow.cpp \\\n    blocks/sign.cpp \\\n    blocks/redstoneutil.cpp \\\n    blocks/redstone.cpp \\\n    blocks/pumpkin.cpp \\\n    blocks/plant.cpp \\\n    blocks/note.cpp \\\n    blocks/liquid.cpp \\\n    blocks/leaves.cpp \\\n    blocks/ladder.cpp \\\n    blocks/jackolantern.cpp \\\n    blocks/ice.cpp \\\n    blocks/fire.cpp \\\n    blocks/falling.cpp \\\n    blocks/door.cpp \\\n    blocks/default.cpp \\\n    blocks/chest.cpp \\\n    blocks/cake.cpp \\\n    blocks/blockfurnace.cpp \\\n    blocks/bed.cpp \\\n    blocks/basic.cpp \\\n    items/projectile.cpp \\\n    items/itembasic.cpp \\\n    items/food.cpp \\\n    worldgen/nethergen.cpp \\\n    worldgen/mapgen.cpp \\\n    worldgen/heavengen.cpp \\\n    worldgen/eximgen.cpp \\\n    worldgen/cavegen.cpp \\\n    worldgen/biomegen.cpp\n\nHEADERS += \\\n    config/scanner.h \\\n    config/parser.h \\\n    config/node.h \\\n    config/lexer.h \\\n    blocks/workbench.h \\\n    blocks/wool.h \\\n    blocks/wood.h \\\n    blocks/tracks.h \\\n    blocks/torch.h \\\n    blocks/tnt.h \\\n    blocks/step.h \\\n    blocks/stair.h \\\n    blocks/snow.h \\\n    blocks/sign.h \\\n    blocks/redstoneutil.h \\\n    blocks/redstone.h \\\n    blocks/pumpkin.h \\\n    blocks/plant.h \\\n    blocks/note.h \\\n    blocks/liquid.h \\\n    blocks/leaves.h \\\n    blocks/ladder.h \\\n    blocks/jackolantern.h \\\n    blocks/ice.h \\\n    blocks/fire.h \\\n    blocks/falling.h \\\n    blocks/door.h \\\n    blocks/default.h \\\n    blocks/chest.h \\\n    blocks/cake.h \\\n    blocks/blockfurnace.h \\\n    blocks/bed.h \\\n    blocks/basic.h \\\n    items/projectile.h \\\n    items/itembasic.h \\\n    items/food.h \\\n    worldgen/nethergen.h \\\n    worldgen/mapgen.h \\\n    worldgen/heavengen.h \\\n    worldgen/eximgen.h \\\n    worldgen/cavegen.h \\\n    worldgen/biomegen.h \\\n    ../include/vec.h \\\n    ../include/utf8.h \\\n    ../include/user.h \\\n    ../include/tree.h \\\n    ../include/tools.h \\\n    ../include/sockets.h \\\n    ../include/SystemExceptions.h \\\n    ../include/signalhandler.h \\\n    ../include/screenBase.h \\\n    ../include/redstoneSimulation.h \\\n    ../include/random.h \\\n    ../include/protocol.h \\\n    ../include/plugin_api.h \\\n    ../include/plugin.h \\\n    ../include/physics.h \\\n    ../include/permissions.h \\\n    ../include/packets.h \\\n    ../include/nbt.h \\\n    ../include/mob.h \\\n    ../include/mineserver.h \\\n    ../include/metadata.h \\\n    ../include/mcregion.h \\\n    ../include/map.h \\\n    ../include/logtype.h \\\n    ../include/logger.h \\\n    ../include/lighting.h \\\n    ../include/inventory.h \\\n    ../include/hook.h \\\n    ../include/furnaceManager.h \\\n    ../include/furnace.h \\\n    ../include/extern.h \\\n    ../include/constants_num.h \\\n    ../include/constants.h \\\n    ../include/config.h \\\n    ../include/cliScreen.h \\\n    ../include/chunkmap.h \\\n    ../include/chat.h \\\n    configure.h \\\n    ../include/stdtime.h\n"
  },
  {
    "path": "src/mob.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"mob.h\"\n#include \"protocol.h\"\n#include <algorithm>\n\nMob::Mob()\n  :\n  UID(Mineserver::generateEID()),\n  type(0),\n  x(0),\n  y(0),\n  z(0),\n  map(0),\n  yaw(0),\n  pitch(0),\n  head_yaw(0), // TODO: actually use head_yaw\n  spawned(false),\n  respawnable(false),\n  health(0)\n{\n}\n\n//Can be 0 (no animation), 1 (swing arm), 2 (damage animation)\n//, 3 (leave bed), 104 (crouch), or 105 (uncrouch). Getting 102 somewhat often, too. \nvoid Mob::animateMob(int animID)\n{\n  User::sendAll(Protocol::animation(UID, animID));\n}\n\nvoid Mob::sethealth(int health)\n{\n  if (health < 0)\n  {\n    health = 0;\n  }\n  if (health > 30)\n  {\n    health = 30;\n  }\n  if (health == 0)\n  {\n    animateDamage(ANIMATE_DEAD);\n//    deSpawnToAll();\n  }\n  else if (health < this->health)\n  {\n    animateDamage(ANIMATE_HURT);\n    animateMob(ANIMATE_DAMAGE);\n  }\n  this->health = health;\n}\n//Possible values: 2 (entity hurt), 3 (entity dead?), 4, 5\nvoid Mob::animateDamage(int animID)\n{\n  User::sendAll(Protocol::entityStatus(UID, animID));\n}\n\nvoid Mob::updateMetadata()\n{\n  User::sendAll(Protocol::entityMetadata(UID, metadata));\n}\n\nvoid Mob::moveAnimal()\n{\n  /*std::string user2(userIn);\n  User* user = User::byNick(user2);\n  float tempMult = 1.f - abs(user->pos.pitch / 25.f);\n    vec pos = vec(user->pos.x * 32, (user->pos.y + 1.5) * 32, user->pos.z * 32);\n    vec vel = vec(\n      sinf(-(user->pos.yaw / 360.f) * 2.f * M_PI) * tempMult * 32768.f,\n      -(user->pos.pitch / 90.f) * 32768.f,\n      cosf(-(user->pos.yaw / 360.f) * 2.f * M_PI) * tempMult * 32768.f\n      );\n    x=vel.x(); y=vel.y();z=vel.z();\n  x += vel.x()*0.01;\n  y += vel.y()*0.01;  \n  z += vel.z()*0.01;  \n  for (int i = 0; i < ServerInstance->users().size(); i++) {\n    User* user2 = ServerInstance->users()[i];\n  user2->buffer << (int8_t)PACKET_OUT_ENTITY_VELOCITY << (int32_t)UID << (int16_t)vel.x() << (int16_t)vel.y() << (int16_t)vel.z();\n  }*/\n}\n\nvoid Mob::spawnToAll()\n{\n  User::sendAll(Protocol::mobSpawn(*this));\n  spawned = true;\n}\n\nvoid Mob::deSpawnToAll()\n{\n  User::sendAll(Protocol::destroyEntity(UID));\n  spawned = false;\n}\n\nvoid Mob::relativeMoveToAll()\n{\n\n}\n\nvoid Mob::teleportToAll()\n{\n  if (spawned)\n  {\n    // ToDo: fix yaw/pitch type\n    User::sendAll(Protocol::entityTeleport(UID, x, y, z, yaw, pitch));\n  }\n}\n\nvoid Mob::moveTo(double to_x, double to_y, double to_z, int to_map)\n{\n  double dx = to_x - x,\n         dy = to_y - y,\n         dz = to_z - z;\n\n  x = to_x;\n  y = to_y;\n  z = to_z;\n  if (to_map != -1)\n  {\n    map = to_map;\n  }\n  if(dx <= 4 && dy <= 4 && dz <= 4)\n  {\n    User::sendAll(Protocol::entityRelativeMove(UID, dx, dy, dz, 1));\n  }\n  else\n  {\n    teleportToAll();\n  }\n}\n\nvoid Mob::look(int16_t yaw, int16_t pitch)\n{\n  // Yaw and Pitch need to be between 0 and 360\n  while (yaw < 0)\n  {\n    yaw += 360;\n  }\n  while (pitch < 0)\n  {\n    pitch += 360;\n  }\n  yaw = yaw % 360;\n  pitch = pitch % 360;\n  int8_t y_byte = (int8_t)((yaw * 1.0) / 360.0 * 256.0);\n  int8_t p_byte = (int8_t)((pitch * 1.0) / 360.0 * 256.0);\n  if(y_byte != this->yaw || p_byte != this->pitch)\n  {\n    User::sendAll(Protocol::entityLook(UID, yaw, pitch));\n  }\n  this->pitch = p_byte;\n  this->yaw = y_byte;\n}\n\nvoid Mob::headLook(int16_t head_yaw)\n{\n  while(head_yaw < 0) {\n    head_yaw += 360;\n  }\n  head_yaw = head_yaw % 360;\n  int8_t h_byte = (int8_t)((head_yaw * 1.0) / 360.0 * 256.0);\n  if(h_byte != this->head_yaw)\n  {\n    User::sendAll(Protocol::entityHeadLook(UID, head_yaw));\n  }\n  this->head_yaw = h_byte;\n}\n"
  },
  {
    "path": "src/mob.h",
    "content": "#ifndef _MOB_H\n#define _MOB_H\n/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cstdlib>\n#include <vector>\n#include <string>\n#include <stdint.h>\n\n#include <memory>\n\n#include \"user.h\"\n#include \"constants.h\"\n#include \"packets.h\"\n#include \"mineserver.h\"\n#include \"metadata.h\"\n\n\nuint32_t generateEID();\n\nclass Mob\n{\npublic:\n  Mob(); // Dont create your own Mob, use Mobs.createMob()\n\n  // Singular\n  uint32_t UID;\n  int8_t type;\n  double x, y, z;\n  size_t map;\n  int8_t yaw, pitch, head_yaw;\n  MetaData metadata;\n  bool spawned;\n  bool respawnable;\n  int health;\n\n  void sethealth(int health);\n\n  // Specifically packet-based commands\n  void spawnToAll();\n  void deSpawnToAll();\n  void relativeMoveToAll();\n  void teleportToAll();\n  void animateMob(int animID);\n  void animateDamage(int animID);\n  void updateMetadata();\n  void moveAnimal();\n\n  void moveTo(double to_x, double to_y, double to_z, int to_map = -1);\n  void look(int16_t yaw, int16_t pitch);\n  void headLook(int16_t head_yaw);\n};\n\ntypedef std::shared_ptr<Mob> MobPtr;\n\nclass Mobs\n{\npublic:\n  inline MobPtr getMobByID(size_t id) const\n  {\n    return id < m_moblist.size() ? m_moblist[id] : MobPtr();\n  }\n\n  inline size_t getMobByTarget(uint32_t mobID) const\n  {\n    for (size_t i = 0; i < m_moblist.size(); ++i)\n    {\n      if (mobID == m_moblist[i]->UID)\n      {\n        return i;\n      }\n    }\n    return -1; // louisdx: This should be checked; at least it should cause a crash if used unchecked.\n  }\n\n  inline size_t getMobCount()\n  {\n    return m_moblist.size();\n  }\n\n  inline std::vector<MobPtr>& getAll()\n  {\n    return m_moblist;\n  }\n\n  inline const std::vector<MobPtr>& getAll() const\n  {\n    return m_moblist;\n  }\n\n  inline void addMob(MobPtr mob)\n  {\n    m_moblist.push_back(mob);\n  }\n\n  inline MobPtr createMob()\n  {\n    MobPtr mob(new Mob);\n    addMob(mob);\n    return mob;\n  }\n\nprivate:\n  std::vector<MobPtr> m_moblist;\n};\n#endif\n"
  },
  {
    "path": "src/nbt.cpp",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <iostream>\n#include <fstream>\n#include <cstring>\n\n#ifdef WIN32\n#include <winsock2.h>\n#endif\n\n#include \"nbt.h\"\n#include \"tools.h\"\n#include \"logger.h\"\n#include \"mineserver.h\"\n#include \"constants.h\"\n\n\n\n//NBT level file reading\n//More info: http://www.minecraft.net/docs/NBT.txt\n\nNBT_Value::NBT_Value(eTAG_Type type, eTAG_Type listType) : m_type(type)\n{\n  memset(&m_value, 0, sizeof(m_value));\n  if (type == TAG_LIST)\n  {\n    m_value.listVal.type = listType;\n  }\n}\n\nNBT_Value::NBT_Value(int8_t value) : m_type(TAG_BYTE)\n{\n  m_value.byteVal = value;\n}\n\nNBT_Value::NBT_Value(int16_t value) : m_type(TAG_SHORT)\n{\n  m_value.shortVal = value;\n}\n\nNBT_Value::NBT_Value(int32_t value) : m_type(TAG_INT)\n{\n  m_value.intVal = value;\n}\n\nNBT_Value::NBT_Value(int64_t value) : m_type(TAG_LONG)\n{\n  m_value.longVal = value;\n}\n\nNBT_Value::NBT_Value(float value) : m_type(TAG_FLOAT)\n{\n  m_value.floatVal = value;\n}\n\nNBT_Value::NBT_Value(double value) : m_type(TAG_DOUBLE)\n{\n  m_value.doubleVal = value;\n}\n\nNBT_Value::NBT_Value(uint8_t* buf, int32_t len) : m_type(TAG_BYTE_ARRAY)\n{\n  m_value.byteArrayVal = new std::vector<uint8_t>(buf, buf + len);\n}\n\nNBT_Value::NBT_Value(int32_t* buf, int32_t len) : m_type(TAG_INT_ARRAY)\n{\n  m_value.intArrayVal = new std::vector<int32_t>(buf, buf + len);\n}\n\nNBT_Value::NBT_Value(std::vector<uint8_t> const& bytes) : m_type(TAG_BYTE_ARRAY)\n{\n  m_value.byteArrayVal = new std::vector<uint8_t>(bytes);\n}\n\nNBT_Value::NBT_Value(std::vector<int32_t> const& bytes) : m_type(TAG_INT_ARRAY)\n{\n  m_value.intArrayVal = new std::vector<int32_t>(bytes);\n}\n\nNBT_Value::NBT_Value(const std::string& str) : m_type(TAG_STRING)\n{\n  m_value.stringVal = new std::string(str);\n}\n\nNBT_Value::NBT_Value(eTAG_Type type, uint8_t** buf, int& remaining) : m_type(type)\n{\n  switch (m_type)\n  {\n  case TAG_BYTE:\n    remaining--;\n    if (remaining >= 0)\n    {\n      m_value.byteVal = **buf;\n      (*buf)++;\n    }\n    break;\n  case TAG_SHORT:\n    remaining -= 2;\n    if (remaining >= 0)\n    {\n      m_value.shortVal = getSint16(*buf);\n      *buf += 2;\n    }\n    break;\n  case TAG_INT:\n    remaining -= 4;\n    if (remaining >= 0)\n    {\n      m_value.intVal = getSint32(*buf);\n      *buf += 4;\n    }\n    break;\n  case TAG_LONG:\n    remaining -= 8;\n    if (remaining >= 0)\n    {\n      m_value.longVal = getSint64(*buf);\n      *buf += 8;\n    }\n    break;\n  case TAG_FLOAT:\n    remaining -= 4;\n    if (remaining >= 0)\n    {\n      m_value.floatVal = getFloat(*buf);\n      *buf += 4;\n    }\n    break;\n  case TAG_DOUBLE:\n    remaining -= 8;\n    if (remaining >= 0)\n    {\n      m_value.doubleVal = getDouble(*buf);\n      *buf += 8;\n    }\n    break;\n  case TAG_BYTE_ARRAY:\n    remaining -= 4;\n    if (remaining >= 0)\n    {\n      int32_t bufLen = getSint32(*buf);\n      remaining -= bufLen;\n      *buf += 4;\n      if (remaining >= 0)\n      {\n        m_value.byteArrayVal = new std::vector<uint8_t>();\n        m_value.byteArrayVal->assign(*buf, (*buf) + bufLen);\n        *buf += bufLen;\n      }\n    }\n    break;\n  case TAG_INT_ARRAY:\n    remaining -= 4;\n    if (remaining >= 0)\n    {\n      int32_t bufLen = getSint32(*buf);\n      remaining -= bufLen;\n      *buf += 4;\n      if (remaining >= 0)\n      {\n        m_value.intArrayVal = new std::vector<int32_t>();\n        for(int i = 0; i < bufLen; i++)\n        {\n          m_value.intArrayVal->push_back(getSint32((*buf+i*4)));\n        }\n        *buf += 4*bufLen;\n      }\n    }\n    break;\n  case TAG_STRING:\n    remaining -= 2;\n    if (remaining >= 0)\n    {\n      int16_t stringLen = getSint16(*buf);\n      remaining -= stringLen;\n      *buf += 2;\n      if (remaining >= 0)\n      {\n        m_value.stringVal = new std::string((char*)*buf, stringLen);\n        *buf += stringLen;\n      }\n    }\n    break;\n  case TAG_LIST:\n    remaining -= 5;\n    if (remaining >= 0)\n    {\n      int8_t type = **buf;\n      (*buf)++;\n      m_value.listVal.type = (eTAG_Type)type;\n      int32_t count = getSint32(*buf);\n      *buf += 4;\n      m_value.listVal.data = new std::vector<NBT_Value*>();\n      if (count)\n      {\n        m_value.listVal.data->resize(count);\n      }\n\n      for (int i = 0; i < count; i++)\n      {\n        (*m_value.listVal.data)[i] = new NBT_Value((eTAG_Type)type, buf, remaining);\n      }\n    }\n    break;\n  case TAG_COMPOUND:\n    m_value.compoundVal = new std::map<std::string, NBT_Value*>();\n    while (remaining > 0)\n    {\n      remaining--;\n      int8_t type = **buf;\n      (*buf)++;\n      if (type == TAG_END)\n      {\n        break;\n      }\n\n      remaining -= 2;\n      if (remaining <= 0)\n      {\n        break;\n      }\n\n      int16_t stringLen = getSint16(*buf);\n      *buf += 2;\n\n      remaining -= stringLen;\n\n      if (remaining <= 0)\n      {\n        break;\n      }\n\n      std::string key((char*)*buf, stringLen);\n      *buf += stringLen;\n\n      (*m_value.compoundVal)[key] = new NBT_Value((eTAG_Type)type, buf, remaining);\n    }\n    break;\n  case TAG_END:\n    break;\n  }\n}\n\nNBT_Value::~NBT_Value()\n{\n  cleanup();\n}\n\nNBT_Value* NBT_Value::operator[](const std::string& index)\n{\n  if (m_type != TAG_COMPOUND)\n  {\n    return NULL;\n  }\n\n  if (!m_value.compoundVal->count(index))\n  {\n    return NULL;\n  }\n\n  return (*m_value.compoundVal)[index];\n}\n\nNBT_Value* NBT_Value::operator[](const char* index)\n{\n  if (m_type != TAG_COMPOUND)\n  {\n    return NULL;\n  }\n\n  std::string stdIndex(index, strlen(index));\n\n  if (!m_value.compoundVal->count(stdIndex))\n  {\n    return NULL;\n  }\n\n  return (*m_value.compoundVal)[stdIndex];\n}\n\nvoid NBT_Value::Insert(const std::string& str, NBT_Value* val)\n{\n  if (m_type != NBT_Value::TAG_COMPOUND)\n  {\n    return;\n  }\n\n  if (m_value.compoundVal == 0)\n  {\n    m_value.compoundVal = new std::map<std::string, NBT_Value*>();\n  }\n\n  if ((*m_value.compoundVal)[str] != 0)\n  {\n    delete(*m_value.compoundVal)[str];\n  }\n\n  (*m_value.compoundVal)[str] = val;\n}\n\nNBT_Value::operator int8_t()\n{\n  if (!this || m_type != TAG_BYTE)\n  {\n    return 0;\n  }\n\n  return m_value.byteVal;\n}\n\nNBT_Value::operator int16_t()\n{\n  if (!this || m_type != TAG_SHORT)\n  {\n    return 0;\n  }\n\n  return m_value.shortVal;\n}\n\nNBT_Value::operator int32_t()\n{\n  if (!this || m_type != TAG_INT)\n  {\n    return 0;\n  }\n\n  return m_value.intVal;\n}\n\nNBT_Value::operator int64_t()\n{\n  if (!this || m_type != TAG_LONG)\n  {\n    return 0;\n  }\n\n  return m_value.longVal;\n}\n\nNBT_Value::operator float()\n{\n  if (!this || m_type != TAG_FLOAT)\n  {\n    return 0;\n  }\n\n  return m_value.floatVal;\n}\n\nNBT_Value::operator double()\n{\n  if (!this || m_type != TAG_DOUBLE)\n  {\n    return 0;\n  }\n\n  return m_value.doubleVal;\n}\n\nNBT_Value& NBT_Value::operator =(int8_t val)\n{\n  cleanup();\n  m_type = TAG_BYTE;\n  m_value.byteVal = val;\n  return *this;\n}\n\nNBT_Value& NBT_Value::operator =(int16_t val)\n{\n  cleanup();\n  m_type = TAG_SHORT;\n  m_value.shortVal = val;\n  return *this;\n}\n\nNBT_Value& NBT_Value::operator =(int32_t val)\n{\n  cleanup();\n  m_type = TAG_INT;\n  m_value.intVal = val;\n  return *this;\n}\n\nNBT_Value& NBT_Value::operator =(int64_t val)\n{\n  cleanup();\n  m_type = TAG_LONG;\n  m_value.longVal = val;\n  return *this;\n}\n\nNBT_Value& NBT_Value::operator =(float val)\n{\n  cleanup();\n  m_type = TAG_FLOAT;\n  m_value.floatVal = val;\n  return *this;\n}\n\nNBT_Value& NBT_Value::operator =(double val)\n{\n  cleanup();\n  m_type = TAG_DOUBLE;\n  m_value.doubleVal = val;\n  return *this;\n}\n\nstd::vector<uint8_t> *NBT_Value::GetByteArray()\n{\n  if (m_type != TAG_BYTE_ARRAY)\n  {\n    return NULL;\n  }\n  if (m_value.byteArrayVal == NULL)\n  {\n    m_value.byteArrayVal = new std::vector<uint8_t>();\n  }\n  return m_value.byteArrayVal;\n}\n\nstd::vector<int32_t> *NBT_Value::GetIntArray()\n{\n  if (m_type != TAG_INT_ARRAY)\n  {\n    return NULL;\n  }\n  if (m_value.intArrayVal == NULL)\n  {\n    m_value.intArrayVal = new std::vector<int32_t>();\n  }\n  return m_value.intArrayVal;\n}\n\n\nstd::string* NBT_Value::GetString()\n{\n  if (m_type != TAG_STRING)\n  {\n    return NULL;\n  }\n  if (m_value.stringVal == NULL)\n  {\n    m_value.stringVal = new std::string();\n  }\n  return m_value.stringVal;\n}\n\nNBT_Value::eTAG_Type NBT_Value::GetListType()\n{\n  if (m_type != TAG_LIST)\n  {\n    return TAG_END;\n  }\n  return m_value.listVal.type;\n}\n\nstd::vector<NBT_Value*> *NBT_Value::GetList()\n{\n  if (m_type != TAG_LIST)\n  {\n    return NULL;\n  }\n  if (m_value.listVal.data == NULL)\n  {\n    m_value.listVal.data = new std::vector<NBT_Value*>();\n  }\n  return m_value.listVal.data;\n}\n\n\nvoid NBT_Value::SetType(eTAG_Type type, eTAG_Type listType)\n{\n  cleanup();\n  m_type = type;\n\n  if (m_type == TAG_LIST)\n  {\n    m_value.listVal.type = listType;\n  }\n}\n\nNBT_Value::eTAG_Type NBT_Value::GetType()\n{\n  return m_type;\n}\n\nvoid NBT_Value::cleanup()\n{\n  if (m_type == TAG_STRING)\n  {\n    delete m_value.stringVal;\n  }\n  if (m_type == TAG_BYTE_ARRAY)\n  {\n    delete m_value.byteArrayVal;\n  }\n  if (m_type == TAG_INT_ARRAY)\n  {\n    delete m_value.intArrayVal;\n  }\n  if (m_type == TAG_LIST)\n  {\n    if (m_value.listVal.data != NULL)\n    {\n      std::vector<NBT_Value*>::iterator iter = m_value.listVal.data->begin(), end = m_value.listVal.data->end();\n      for (; iter != end ; iter++)\n      {\n        delete *iter;\n      }\n      delete m_value.listVal.data;\n    }\n  }\n  if (m_type == TAG_COMPOUND)\n  {\n    if (m_value.compoundVal != NULL)\n    {\n      std::map<std::string, NBT_Value*>::iterator iter = m_value.compoundVal->begin(), end = m_value.compoundVal->end();\n      for (; iter != end ; iter++)\n      {\n        delete iter->second;\n      }\n\n      delete m_value.compoundVal;\n    }\n  }\n\n  memset(&m_value, 0, sizeof(m_value));\n  m_type = TAG_END;\n}\n\nNBT_Value* NBT_Value::LoadFromFile(const std::string& filename)\n{\n  FILE* fp = fopen(filename.c_str(), \"rb\");\n  if (fp == NULL)\n  {\n    return NULL;\n  }\n  fseek(fp, -4, SEEK_END);\n  uint32_t uncompressedSize = 0;\n  fread(&uncompressedSize, 4, 1, fp);\n  fclose(fp);\n\n  //Do endian testing!\n  int32_t endiantestint = 1;\n  int8_t* endiantestchar = (int8_t*)&endiantestint;\n  if (*endiantestchar != 1)\n  {\n    //Swap order\n    int uncompressedSizeOld = uncompressedSize;\n    uint8_t* newpointer = reinterpret_cast<uint8_t*>(&uncompressedSize);\n    uint8_t* oldpointer = reinterpret_cast<uint8_t*>(&uncompressedSizeOld);\n    newpointer[0] = oldpointer[3];\n    newpointer[1] = oldpointer[2];\n    newpointer[2] = oldpointer[1];\n    newpointer[3] = oldpointer[0];\n  }\n\n  if (uncompressedSize == 0)\n  {\n    LOG2(WARNING, \"Unable to determine uncompressed size of \" + filename);\n    uncompressedSize = ALLOCATE_NBTFILE * 10;\n  }\n\n  uint8_t* uncompressedData = new uint8_t[uncompressedSize];\n  gzFile nbtFile = gzopen(filename.c_str(), \"rb\");\n  if (nbtFile == NULL)\n  {\n    delete[] uncompressedData;\n    return NULL;\n  }\n  gzread(nbtFile, uncompressedData, uncompressedSize);\n  gzclose(nbtFile);\n\n  uint8_t* ptr = uncompressedData + 3; // Jump blank compound\n  int remaining = uncompressedSize;\n\n  NBT_Value* root = new NBT_Value(TAG_COMPOUND, &ptr, remaining);\n\n  delete[] uncompressedData;\n\n  return root;\n}\n\nNBT_Value* NBT_Value::LoadFromMemory(uint8_t* buffer, uint32_t len)\n{\n  //Initialize zstream to handle gzip format\n  z_stream zstream;\n  zstream.zalloc    = (alloc_func)0;\n  zstream.zfree     = (free_func)0;\n  zstream.opaque    = (voidpf)0;\n  zstream.next_in   = buffer;\n  zstream.next_out  = 0;\n  zstream.avail_in  = len;\n  zstream.avail_out = 0;\n  zstream.total_in  = 0;\n  zstream.total_out = 0;\n  zstream.data_type = Z_BINARY;\n  //inflateInit2(&zstream,16+MAX_WBITS);\n  inflateInit(&zstream);\n\n  uint32_t uncompressedSize   = ALLOCATE_NBTFILE * 10;\n  uint8_t* uncompressedBuffer = new uint8_t[uncompressedSize];\n\n  zstream.avail_out = uncompressedSize;\n  zstream.next_out = uncompressedBuffer;\n\n  //Uncompress\n  int returnvalue = 0;\n  if ((returnvalue = inflate(&zstream, Z_FINISH)) != Z_STREAM_END && returnvalue != Z_BUF_ERROR)\n  {\n\n    std::cout << \"Error in inflate! \" << returnvalue << std::endl;\n    delete[] uncompressedBuffer;\n    return NULL;\n  }\n\n  inflateEnd(&zstream);\n\n  uint8_t* ptr = uncompressedBuffer + 3; // Jump blank compound\n  int remaining = uncompressedSize;\n\n  NBT_Value* root = new NBT_Value(TAG_COMPOUND, &ptr, remaining);\n\n  delete[] uncompressedBuffer;\n\n  return root;\n}\n\nvoid NBT_Value::SaveToFile(const std::string& filename)\n{\n  std::vector<uint8_t> buffer;\n\n  // Blank compound tag\n  buffer.push_back(TAG_COMPOUND);\n  buffer.push_back(0);\n  buffer.push_back(0);\n\n  Write(buffer);\n\n  buffer.push_back(0);\n  buffer.push_back(0);\n  buffer.push_back(0);\n\n  gzFile nbtFile = gzopen(filename.c_str(), \"wb\");\n  gzwrite(nbtFile, &buffer[0], buffer.size());\n  gzclose(nbtFile);\n}\n\n\nvoid NBT_Value::SaveToMemory(uint8_t* buffer, uint32_t* len)\n{\n\n  std::vector<uint8_t> NBTBuffer;\n  // Blank compound tag\n  NBTBuffer.push_back(TAG_COMPOUND);\n  NBTBuffer.push_back(0);\n  NBTBuffer.push_back(0);\n\n  Write(NBTBuffer);\n\n  NBTBuffer.push_back(0);\n  NBTBuffer.push_back(0);\n  NBTBuffer.push_back(0);\n\n  uLongf written = ALLOCATE_NBTFILE * 10;\n  compress(buffer, &written, &NBTBuffer[0], NBTBuffer.size());\n  *len = written;\n\n}\n\nvoid NBT_Value::Write(std::vector<uint8_t> &buffer)\n{\n  int storeAt = buffer.size();;\n  switch (m_type)\n  {\n  case TAG_BYTE:\n    buffer.push_back(m_value.byteVal);\n    break;\n  case TAG_SHORT:\n    buffer.resize(storeAt + 2);\n    putSint16(&buffer[storeAt], m_value.shortVal);\n    break;\n  case TAG_INT:\n    buffer.resize(storeAt + 4);\n    putSint32(&buffer[storeAt], m_value.intVal);\n    break;\n  case TAG_LONG:\n    buffer.resize(storeAt + 8);\n    putSint64(&buffer[storeAt], m_value.longVal);\n    break;\n  case TAG_FLOAT:\n    buffer.resize(storeAt + 4);\n    putFloat(&buffer[storeAt], m_value.floatVal);\n    break;\n  case TAG_DOUBLE:\n    buffer.resize(storeAt + 8);\n    putDouble(&buffer[storeAt], m_value.doubleVal);\n    break;\n  case TAG_BYTE_ARRAY:\n  {\n    int arraySize = m_value.byteArrayVal ? m_value.byteArrayVal->size() : 0;\n    buffer.resize(storeAt + 4 + arraySize);\n    putSint32(&buffer[storeAt], arraySize);\n    storeAt += 4;\n    if (arraySize)\n    {\n      memcpy(&buffer[storeAt], &(*m_value.byteArrayVal)[0], arraySize);\n    }\n    break;\n  }\n  case TAG_INT_ARRAY:\n  {\n    int arraySize = m_value.intArrayVal ? m_value.intArrayVal->size() : 0;\n    buffer.resize(storeAt + 4 + arraySize*4);\n    putSint32(&buffer[storeAt], arraySize);\n    storeAt += 4;\n    for(int i = 0; i < arraySize; i++)\n    {\n      putSint32(&buffer[storeAt+i*4], (*m_value.intArrayVal)[i]);\n    }\n    storeAt += 4*arraySize;\n    break;\n  }\n  case TAG_STRING:\n  {\n    int stringLen = m_value.stringVal ? m_value.stringVal->size() : 0;\n    buffer.resize(storeAt + 2 + stringLen);\n    putSint16(&buffer[storeAt], (int16_t)stringLen);\n    storeAt += 2;\n    if (stringLen > 0)\n    {\n      memcpy(&buffer[storeAt], m_value.stringVal->c_str(), stringLen);\n    }\n    break;\n  }\n  case TAG_LIST:\n  {\n    buffer.resize(storeAt + 5);\n    int listCount = m_value.listVal.data ? m_value.listVal.data->size() : 0;\n    buffer[storeAt] = m_value.listVal.type;\n    storeAt++;\n    putSint32(&buffer[storeAt], listCount);\n    for (int i = 0; i < listCount; i++)\n    {\n      (*m_value.listVal.data)[i]->Write(buffer);\n    }\n    break;\n  }\n  case TAG_COMPOUND:\n  {\n    int compoundCount = m_value.compoundVal ? m_value.compoundVal->size() : 0;\n    if (compoundCount)\n    {\n      std::map<std::string, NBT_Value*>::iterator iter = m_value.compoundVal->begin(), end = m_value.compoundVal->end();\n      for (; iter != end; iter++)\n      {\n        const std::string& key = iter->first;\n        int keySize = key.size();\n        NBT_Value* val = iter->second;\n        int curPos = buffer.size();\n        buffer.resize(curPos + 3 + keySize);\n        buffer[curPos] = (uint8_t)val->GetType();\n        curPos++;\n        putSint16(&buffer[curPos], keySize);\n        curPos += 2;\n        if (keySize)\n        {\n          memcpy(&buffer[curPos], key.c_str(), keySize);\n        }\n        val->Write(buffer);\n      }\n    }\n    buffer.push_back(TAG_END);\n    break;\n  }\n  case TAG_END:\n    break; //for completeness\n  }\n}\n\nvoid NBT_Value::Dump(std::string& data, const std::string& name, int tabs)\n{\n  std::string tabPrefix = \"\";\n  for (int i = 0; i < tabs; i++)\n  {\n    tabPrefix += \"  \";\n  }\n\n  switch (m_type)\n  {\n  case TAG_END:\n    data += tabPrefix + \"TAG_End(\\\"\" + name + \"\\\")\\n\";\n    break;\n  case TAG_BYTE:\n    data += tabPrefix + \"TAG_Byte(\\\"\" + name + \"\\\"): \" + dtos(double(int(m_value.byteVal))) + \"\\n\";\n    break;\n  case TAG_SHORT:\n    data += tabPrefix + \"TAG_Short(\\\"\" + name + \"\\\"): \" + dtos(double(m_value.shortVal)) + \"\\n\";\n    break;\n  case TAG_INT:\n    data += tabPrefix + \"TAG_Int(\\\"\" + name + \"\\\"): \" + dtos(double(m_value.intVal)) + \"\\n\";\n    break;\n  case TAG_LONG:\n    data += tabPrefix + \"TAG_Long(\\\"\" + name + \"\\\"): \" + dtos(double(m_value.longVal)) + \"\\n\";\n    break;\n  case TAG_FLOAT:\n    data += tabPrefix + \"TAG_Float(\\\"\" + name + \"\\\"): \" + dtos(double(m_value.floatVal)) + \"\\n\";\n    break;\n  case TAG_DOUBLE:\n    data += tabPrefix + \"TAG_Double(\\\"\" + name + \"\\\"): \" + dtos(m_value.doubleVal) + \"\\n\";\n    break;\n  case TAG_BYTE_ARRAY:\n    data += tabPrefix + \"TAG_Byte_Array(\\\"\" + name + \"\\\"): \\n\";\n    if (m_value.byteArrayVal != NULL)\n    {\n      data += tabPrefix + dtos(m_value.byteArrayVal->size()) + \" bytes\\n\";\n    }\n    else\n    {\n      data += tabPrefix + \"0 bytes\\n\";\n    }\n    break;\n  case TAG_INT_ARRAY:\n    data += tabPrefix + \"TAG_Int_Array(\\\"\" + name + \"\\\"): \\n\";\n    if (m_value.intArrayVal != NULL)\n    {\n      data += tabPrefix + dtos(m_value.intArrayVal->size()) + \" bytes\\n\";\n    }\n    else\n    {\n      data += tabPrefix + \"0 bytes\\n\";\n    }\n    break;\n  case TAG_STRING:\n    data += tabPrefix + \"TAG_String(\\\"\" + name + \"\\\"): \\n\";\n    if (m_value.stringVal != NULL)\n    {\n      data += tabPrefix + *m_value.stringVal + \"\\n\";\n    }\n    else\n    {\n      data += tabPrefix + \"\\n\";\n    }\n    break;\n  case TAG_LIST:\n    data += tabPrefix + \"TAG_List(\\\"\" + name + \"\\\"): Type \" + dtos(m_value.listVal.type) + \"\\n\";\n    if (m_value.listVal.data != NULL)\n    {\n      std::vector<NBT_Value*>::iterator iter = m_value.listVal.data->begin(), end = m_value.listVal.data->end();\n      for (; iter != end ; iter++)\n      {\n        (*iter)->Dump(data, std::string(\"\"), tabs + 1);\n      }\n    }\n    break;\n  case TAG_COMPOUND:\n    data += tabPrefix + \"TAG_Compound(\\\"\" + name + \"\\\"):\\n\";\n    if (m_value.compoundVal != NULL)\n    {\n      std::map<std::string, NBT_Value*>::iterator iter = m_value.compoundVal->begin(), end = m_value.compoundVal->end();\n      for (; iter != end; iter++)\n      {\n        iter->second->Dump(data, iter->first, tabs + 1);\n      }\n    }\n    break;\n  default:\n    data += tabPrefix + \"Invalid TAG:\" + dtos(m_type) + \"\\n\";\n  }\n}\n"
  },
  {
    "path": "src/nbt.h",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _NBT_H\n#define _NBT_H\n\n#include <map>\n#include <string>\n#include <vector>\n\n#include <stdint.h>\n#ifdef WIN32\n  #define _WINSOCKAPI_\n#endif\n#include <zlib.h>\n\nclass NBT_Value\n{\npublic:\n  enum eTAG_Type\n  {\n    TAG_END        = 0,\n    TAG_BYTE       = 1,\n    TAG_SHORT      = 2,\n    TAG_INT        = 3,\n    TAG_LONG       = 4,\n    TAG_FLOAT      = 5,\n    TAG_DOUBLE     = 6,\n    TAG_BYTE_ARRAY = 7,\n    TAG_STRING     = 8,\n    TAG_LIST       = 9,\n    TAG_COMPOUND   = 10,\n    TAG_INT_ARRAY  = 11\n  };\n\n  NBT_Value(eTAG_Type type, eTAG_Type listType = TAG_END);\n  explicit NBT_Value(int8_t value);\n  explicit NBT_Value(int16_t value);\n  explicit NBT_Value(int32_t value);\n  explicit NBT_Value(int64_t value);\n  explicit NBT_Value(float value);\n  explicit NBT_Value(double value);\n\n  NBT_Value(int32_t* buf, int32_t len);\n  NBT_Value(uint8_t* buf, int32_t len);\n  NBT_Value(std::vector<uint8_t> const& bytes);\n  NBT_Value(std::vector<int32_t> const& bytes);\n  NBT_Value(const std::string& str);\n\n  NBT_Value(eTAG_Type type, uint8_t** buf, int& remaining);\n\n  ~NBT_Value();\n\n  NBT_Value* operator[](const std::string& index);\n  NBT_Value* operator[](const char* index);\n\n  void Insert(const std::string& str, NBT_Value* val);\n\n  operator int8_t();\n  operator int16_t();\n  operator int32_t();\n  operator int64_t();\n  operator float();\n  operator double();\n\n  NBT_Value& operator =(int8_t val);\n  NBT_Value& operator =(int16_t val);\n  NBT_Value& operator =(int32_t val);\n  NBT_Value& operator =(int64_t val);\n  NBT_Value& operator =(float val);\n  NBT_Value& operator =(double val);\n\n  std::vector<int32_t>* GetIntArray();\n  std::vector<uint8_t>* GetByteArray();\n  std::string* GetString();\n  eTAG_Type GetListType();\n  std::vector<NBT_Value*>* GetList();\n\n  void SetType(eTAG_Type type, eTAG_Type listType = TAG_END);\n\n  eTAG_Type GetType();\n  void cleanup();\n\n  static NBT_Value* LoadFromFile(const std::string& filename);\n  static NBT_Value* LoadFromMemory(uint8_t* buffer, uint32_t len);\n  void SaveToFile(const std::string& filename);\n  void SaveToMemory(uint8_t* buffer, uint32_t* len);\n\n  void Write(std::vector<uint8_t> &buffer);\n\n  void Dump(std::string& data, const std::string& name = std::string(\"\"), int tabs = 0);\n\nprivate:\n  eTAG_Type m_type;\n  union\n  {\n    int8_t byteVal;\n    int16_t shortVal;\n    int32_t intVal;\n    int64_t longVal;\n    float floatVal;\n    double doubleVal;\n    std::string* stringVal;\n    std::vector<uint8_t>* byteArrayVal;\n    std::vector<int32_t>* intArrayVal;\n    struct\n    {\n      eTAG_Type type;\n      std::vector<NBT_Value*> *data;\n    } listVal;\n    std::map<std::string, NBT_Value*>* compoundVal;\n  } m_value;\n};\n\n#endif\n"
  },
  {
    "path": "src/packets.cpp",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <sys/types.h>\n#ifdef _WIN32\n#include <winsock2.h>\n#else\n#include <netdb.h>       // for gethostbyname()\n#include <netinet/tcp.h> // for TCP constants\n#endif\n\n#include <cmath>\n#include <sstream>\n#include <algorithm>\n\n\n#include \"chat.h\"\n#include \"config.h\"\n#include \"constants.h\"\n#include \"furnaceManager.h\"\n#include \"inventory.h\"\n#include \"logger.h\"\n#include \"map.h\"\n#include \"mineserver.h\"\n#include \"nbt.h\"\n#include \"packets.h\"\n#include \"physics.h\"\n#include \"plugin.h\"\n#include \"sockets.h\"\n#include \"tools.h\"\n#include \"user.h\"\n#include \"blocks/basic.h\"\n#include \"blocks/default.h\"\n#include \"blocks/note.h\"\n#include \"items/itembasic.h\"\n#include \"mob.h\"\n#include \"utf8.h\"\n#include \"protocol.h\"\n#include \"sockets.h\"\n\n#ifdef PROTOCOL_ENCRYPTION\n#include <openssl/rsa.h>\n#include <openssl/err.h>\n#endif\n\n#define _WINSOCKAPI_\n#define NOMINMAX\n#include <zlib.h>\n\nvoid PacketHandler::init()\n{\n  \n  packets[STATE_HANDSHAKE][PACKET_IN_HANDSHAKE]            = Packets(&PacketHandler::handshake);\n\n  packets[STATE_STATUS][PACKET_IN_SERVER_LIST_PING]        = Packets(&PacketHandler::server_list_ping);\n  packets[STATE_STATUS][PACKET_IN_PING]                    = Packets(&PacketHandler::ping);\n\n  packets[STATE_LOGIN][PACKET_IN_LOGIN_REQUEST]            = Packets(&PacketHandler::login_request);\n  packets[STATE_LOGIN][PACKET_IN_ENCRYPTION_RESPONSE]      = Packets(&PacketHandler::encryption_response);\n  \n  packets[STATE_PLAY][PACKET_IN_KEEP_ALIVE]                = Packets(&PacketHandler::keep_alive);\n  packets[STATE_PLAY][PACKET_IN_CHAT_MESSAGE]              = Packets(&PacketHandler::chat_message);\n  packets[STATE_PLAY][PACKET_IN_USE_ENTITY]                = Packets(&PacketHandler::use_entity);\n  packets[STATE_PLAY][PACKET_IN_PLAYER]                    = Packets(&PacketHandler::player);\n  packets[STATE_PLAY][PACKET_IN_PLAYER_POSITION]           = Packets(&PacketHandler::player_position);\n  packets[STATE_PLAY][PACKET_IN_PLAYER_LOOK]               = Packets(&PacketHandler::player_look);\n  packets[STATE_PLAY][PACKET_IN_PLAYER_POSITION_AND_LOOK]  = Packets(&PacketHandler::player_position_and_look);\n  packets[STATE_PLAY][PACKET_IN_PLAYER_DIGGING]            = Packets(&PacketHandler::player_digging);\n  packets[STATE_PLAY][PACKET_IN_PLAYER_BLOCK_PLACEMENT]    = Packets(&PacketHandler::player_block_placement);\n  packets[STATE_PLAY][PACKET_IN_HELD_ITEM_CHANGE]          = Packets(&PacketHandler::held_item_change);\n  packets[STATE_PLAY][PACKET_IN_ANIMATION]                 = Packets(&PacketHandler::animation);\n  //packets[STATE_PLAY][PACKET_IN_PICKUP_SPAWN]            = Packets(&PacketHandler::pickup_spawn);\n\n  packets[STATE_PLAY][PACKET_IN_CLIENT_STATUS]             = Packets(&PacketHandler::client_status);\n  packets[STATE_PLAY][PACKET_IN_CLICK_WINDOW]              = Packets(&PacketHandler::click_window);\n  packets[STATE_PLAY][PACKET_IN_CLOSE_WINDOW]              = Packets(&PacketHandler::close_window);\n  packets[STATE_PLAY][PACKET_IN_UPDATE_SIGN]               = Packets(&PacketHandler::update_sign);\n  packets[STATE_PLAY][PACKET_IN_CONFIRM_TRANSACTION]       = Packets(&PacketHandler::confirm_transaction);\n  packets[STATE_PLAY][PACKET_IN_ENTITY_ACTION]             = Packets(&PacketHandler::entity_action);\n  packets[STATE_PLAY][PACKET_IN_BLOCK_CHANGE]              = Packets(&PacketHandler::block_change);\n  packets[STATE_PLAY][PACKET_IN_TAB_COMPLETE]              = Packets(&PacketHandler::tab_complete);\n  packets[STATE_PLAY][PACKET_IN_CLIENT_SETTINGS]           = Packets(&PacketHandler::client_settings);\n\n  packets[STATE_PLAY][PACKET_IN_PLUGIN_MESSAGE]            = Packets(&PacketHandler::plugin_message);\n  packets[STATE_PLAY][PACKET_IN_CREATIVE_INVENTORY_ACTION] = Packets(&PacketHandler::creative_inventory);\n  packets[STATE_PLAY][PACKET_IN_PLAYER_ABILITIES]          = Packets(&PacketHandler::player_abilities);\n}\n\nint PacketHandler::unhandledPacket(User* user)\n{\n\n  return PACKET_OK;\n}\n\nint PacketHandler::plugin_message(User* user)\n{\n\n  if (!user->buffer.haveData(4))\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  \n  std::string channel;\n  int16_t datalen;\n\n  user->buffer >> channel;\n\n  if (!user->buffer || !user->buffer.haveData(2))\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  user->buffer >> datalen;\n\n  if (!user->buffer.haveData(datalen))\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  for(int i = 0; i < datalen; i++)\n  {\n    int8_t byte;\n    user->buffer >> byte;\n  }\n\n  LOG2(INFO, \"Plugin message: \"+channel);\n\n\n  return PACKET_OK;\n}\n\n\n#ifdef PROTOCOL_ENCRYPTION\nint PacketHandler::encryption_response(User* user)\n{\n\n  MS_VarInt secretLen, verifyLen;\n  std::string secret,verify;\n  std::string decryptedSecret(' ', 16);\n\n  user->buffer >> secretLen;\n\n  if (!user->buffer.haveData((int)secretLen))\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  for(int i = 0; i < secretLen; i++)\n  {\n    int8_t byte;\n    user->buffer >> byte;\n    secret.push_back(byte);\n  }\n\n  user->buffer >> verifyLen;\n\n\n  for(int i = 0; i < (int)verifyLen; i++)\n  {\n    int8_t byte;\n    user->buffer >> byte;\n    verify.push_back(byte);\n  }\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n  \n  //Those should be around 128 bytes\n  if((int)verifyLen > 1023 || (int)secretLen > 1023)\n  {\n    user->kick(\"Invalid verify/secret size\");\n    return PACKET_OK;\n  }\n\n  \n  uint8_t buffer[1024];\n  memset(buffer, 0, 1024);\n  //Decrypt the verification bytes\n  #if OPENSSL_VERSION_NUMBER < 0x10000000L\n  int ret = RSA_private_decrypt((int)verifyLen,(const uint8_t *)verify.c_str(),buffer,ServerInstance->rsa,RSA_PKCS1_PADDING);\n  #else\n  size_t outlen = 1024;\n  int ret = EVP_PKEY_decrypt(ServerInstance->crypto_ctx, buffer, &outlen, (const uint8_t *)verify.c_str(), verifyLen);\n  #endif\n  //Check they match with the ones sent\n  if(outlen != 4 || std::string((char *)buffer, outlen) != ServerInstance->encryptionBytes)\n  {\n    LOG2(INFO, \"Expected: \" + ServerInstance->encryptionBytes + \" Got: \" + std::string((char *)buffer, outlen));\n    user->kick(\"Decryption failed\");\n    return PACKET_OK;\n  }\n\n  //Decrypt secret sent by the client and store\n  memset(buffer, 0, 1024);\n  #if OPENSSL_VERSION_NUMBER < 0x10000000L\n  ret = RSA_private_decrypt((int)secretLen,(const uint8_t *)secret.c_str(),buffer,ServerInstance->rsa,RSA_PKCS1_PADDING);\n  #else\n  outlen = 1024;\n  ret = EVP_PKEY_decrypt(ServerInstance->crypto_ctx, buffer, &outlen, (const uint8_t *)secret.c_str(), secretLen);\n  #endif\n  user->secret = std::string((char *)buffer, outlen);\n  //We're going crypted!\n  user->initCipher();\n  \n  user->crypted = true;\n  if(!ServerInstance->config()->bData(\"system.user_validation\"))\n  {\n    //Response    \n    user->sendLoginInfo();\n  }\n  else\n  {\n    ThreadTask* task = new ThreadTask(THREAD_VALIDATEUSER, user);\n    ServerInstance->getThreadpool()->newTask(task);\n  }\n  \n\n  return PACKET_OK;\n}\n#endif\n\nint PacketHandler::client_status(User* user)\n{\n  MS_VarInt action_id;\n\n  user->buffer >> action_id;\n  \n  //0: Initial spawn, 1: Respawn after death\n  LOG2(INFO, \"client_status.\");\n  if(action_id.val == 0 && !user->logged && user->crypted)\n  {\n    LOG2(INFO, \"Sending login info..\");\n    user->sendLoginInfo();\n  }\n  //player respawns\n  else if(action_id.val == 0)\n  {\n    user->dropInventory();\n    user->respawn();\n  }\n\n  return PACKET_OK;\n}\n\nint PacketHandler::creative_inventory(User *user)\n{\n    int16_t slot, itemID;\n\n    user->buffer >> slot >> itemID;\n\n    int8_t count = -1;\n    int16_t meta = -1;\n    int8_t nbt = 0;\n    NBT_Value* nbtdata = nullptr;\n\n    if (itemID != -1) {\n      user->buffer >> count >> meta;\n\n      user->buffer >> nbt;\n      if (nbt != 0)\n      {\n        int32_t nbtlen = user->packetLen - (user->buffer.m_readPos-1);  \n        if (nbtlen > 3)\n        {\n          uint8_t *buf = (uint8_t*)malloc(nbtlen-3);\n\n          std::copy(user->buffer.m_readBuffer.begin() + user->buffer.m_readPos+2, \n                    user->buffer.m_readBuffer.begin() + user->buffer.m_readPos-1 + nbtlen, buf);\n          nbtlen -= 3;\n          nbtdata = new NBT_Value(NBT_Value::eTAG_Type::TAG_COMPOUND, &buf,nbtlen);\n\n          #ifdef DEBUG\n          std::string data, name;\n          nbtdata->Dump(data);\n\n          std::cout << data << std::endl;\n          #endif\n        \n          delete[] buf;      \n        }\n      }\n    }\n\n    if (!user->buffer) {\n      delete nbtdata;\n      return PACKET_NEED_MORE_DATA;\n    }\n\n    Item& it = user->inv[slot];\n\n    it.setType(itemID);\n    it.setCount(count);\n    it.setHealth(meta);\n    it.setData(nbtdata);\n\n  \n    return PACKET_OK;\n}\n\nint PacketHandler::player_abilities(User *user)\n{\n    /// TODO: use this somewhere!\n    int8_t flags, fspeed, wspeed;\n\n    user->buffer >> flags >> fspeed >> wspeed;\n\n    return PACKET_OK;\n}\n\nint PacketHandler::client_settings(User* user)\n{\n  // Wait for length-short. HEHE\n  if (!user->buffer.haveData(2))\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  std::string locale;\n  int8_t viewDistance,chatFlags,difficulty,showCape;\n\n  user->buffer >> locale;\n\n  if (!user->buffer || !user->buffer.haveData(4))\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  user->buffer >> viewDistance >> chatFlags >> difficulty >> showCape;\n\n\n\n  //ToDo: Do something with the values\n\n\n  return PACKET_OK;\n}\n\n\nint PacketHandler::tab_complete(User* user)\n{\n  // Wait for length-short. HEHE\n  if (!user->buffer.haveData(2))\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  std::string msg;\n  int8_t hasPosition;\n\n  user->buffer >> msg >> hasPosition;\n\n  if (hasPosition) {\n    uint64_t position;\n    int32_t x,z;\n    int16_t y;\n    user->buffer >> position;\n    positionToXYZ(position, x, y, z);\n  }\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n\n  std::vector<std::string> completion;\n  completion.push_back(msg+\"test1\");\n  completion.push_back(msg+\"test2\");\n  //ToDo: autocomplete!\n  user->writePacket(Protocol::tabComplete(completion));\n\n  return PACKET_OK;\n}\n\nint PacketHandler::entity_action(User* user)\n{\n  int32_t EID;\n  int8_t action;\n  int32_t horseJumpBoost; // range: 0 -> 100; (Notch Logic)\n\n  MetaData meta;\n  MetaDataElemByte *element;\n\n  user->buffer >> EID >> action >> horseJumpBoost;\n  Packet pkt;\n  bool packetData = false;\n\n  //ToDo: handle other actions\n  switch(action)\n  {\n  //Crouch\n  case 1:    \n    element = new MetaDataElemByte(0,0x02);\n    meta.set(element);\n    pkt << Protocol::animation(user->UID, 104) << Protocol::entityMetadata(user->UID,meta);\n    packetData = true;\n    break;\n    //Uncrouch\n  case 2:\n    element = new MetaDataElemByte(0,0x00);\n    meta.set(element);\n    pkt << Protocol::animation(user->UID, 105) << Protocol::entityMetadata(user->UID,meta);\n    packetData = true;\n    break;\n  default:\n    break;\n  }\n  \n  if(packetData)\n  {\n    sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk((int32_t)user->pos.x), blockToChunk((int32_t)user->pos.z));\n    if (chunk != NULL)\n    {\n      chunk->sendPacket(pkt);\n    }\n  }\n\n\n  return PACKET_OK;\n}\n\nint PacketHandler::update_sign(User* user)\n{\n  uint64_t position;\n  int32_t x, z;\n  int16_t y;\n  std::string strings1, strings2, strings3, strings4;\n\n  user->buffer >> position;\n\n  positionToXYZ(position, x, y, z);\n\n  user->buffer >> strings1;\n\n  user->buffer >> strings2;\n\n  user->buffer >> strings3;\n\n  user->buffer >> strings4;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n  \n  signDataPtr newSign(new signData);\n  newSign->x = x;\n  newSign->y = y;\n  newSign->z = z;\n  newSign->text1 = strings1;\n  newSign->text2 = strings2;\n  newSign->text3 = strings3;\n  newSign->text4 = strings4;\n\n  sChunk* chunk = ServerInstance->map(user->pos.map)->getChunk(blockToChunk(x), blockToChunk(z));\n\n  if (chunk != NULL)\n  {\n    //Check if this sign data already exists and remove\n    chunk->signs.erase(std::remove_if(chunk->signs.begin(), chunk->signs.end(), DataFinder<signData>(x,y,z)), chunk->signs.end());\n\n    // Insert new sign\n    chunk->signs.push_back(newSign);\n\n    //Send sign packet to everyone\n    user->sendAll(Protocol::updateSign(x, y, z, strings1, strings2, strings3, strings4));\n  }\n\n  LOG2(INFO, \"Sign: \" + strings1 + strings2 + strings3 + strings4);\n\n  //No need to do anything\n\n  return PACKET_OK;\n}\n\n\nint PacketHandler::close_window(User* user)\n{\n  int8_t windowID;\n\n  user->buffer >> windowID;\n\n  ServerInstance->inventory()->windowClose(user, windowID);\n\n\n  return PACKET_OK;\n}\n\n\nint PacketHandler::confirm_transaction(User* user)\n{\n  int8_t windowID;\n  int16_t action;\n  int8_t accepted;\n\n  user->buffer >> windowID >> action >> accepted;\n\n  //No need to do anything\n\n  return PACKET_OK;\n}\n\nint PacketHandler::click_window(User* user)\n{\n  int8_t windowID = 0;\n  int16_t slot = 0;\n  int8_t rightClick = 0;\n  int16_t actionNumber = 0;\n  int8_t shift = 0;\n  int16_t itemID = 0;\n  int8_t itemCount = 0;\n  int16_t itemUses  = 0;\n  NBT_Value* nbtdata = nullptr;\n\n  user->buffer >> windowID >> slot >> rightClick >> actionNumber >> shift >> itemID;\n  if (itemID != -1)\n  {\n    uint8_t nbt;\n    if (!user->buffer.haveData(4))\n    {\n      return PACKET_NEED_MORE_DATA;\n    }\n    user->buffer >> itemCount >> itemUses;\n    user->buffer >> nbt;\n    if (nbt != 0)\n    {\n      int32_t nbtlen = user->packetLen - (user->buffer.m_readPos-1);  \n      if (nbtlen > 3)\n      {\n        uint8_t *buf = (uint8_t*)malloc(nbtlen-3);\n\n        std::copy(user->buffer.m_readBuffer.begin() + user->buffer.m_readPos+2, \n                  user->buffer.m_readBuffer.begin() + user->buffer.m_readPos-1 + nbtlen, buf);\n        nbtlen -= 3;\n        nbtdata = new NBT_Value(NBT_Value::eTAG_Type::TAG_COMPOUND, &buf,nbtlen);\n\n        #ifdef DEBUG\n        std::string data, name;\n        nbtdata->Dump(data);\n\n        std::cout << data << std::endl;\n        #endif\n        \n        delete[] buf;      \n      }\n    }\n  }\n\n  //ToDo: push nbtdata to the windowClick()\n  if (nbtdata) delete nbtdata;\n  ServerInstance->inventory()->windowClick(user, windowID, slot, rightClick, actionNumber, itemID, itemCount, itemUses, shift);\n\n\n  return PACKET_OK;\n}\n\n// Keep Alive (http://mc.kev009.com/wiki/Protocol#Keep_Alive_.280x00.29)\nint PacketHandler::keep_alive(User* user)\n{\n  //No need to do anything\n  MS_VarInt time;\n  user->buffer >> time;\n\n  return PACKET_OK;\n}\n\n// Login request\nint PacketHandler::login_request(User* user)\n{\n\n  std::string player;\n\n  user->buffer >> player;\n\n  // Check for data\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n\n  user->nick = player;\n\n  char* kickMessage = NULL;\n  runCallbackUntilFalse(\"PlayerLoginPre\",player.c_str(), &kickMessage);\n  if (callbackReturnValue)\n  {\n    user->kick(std::string(kickMessage));\n  }\n  else\n  {\n    //We can skip the protocol encryption\n    if(!ServerInstance->config()->bData(\"system.protocol_encryption\"))\n    {\n      user->sendLoginInfo();\n    }\n    else\n    {\n      user->writePacket(Protocol::encryptionRequest());\n    }\n    runAllCallback(\"PlayerLoginPost\",player.c_str());\n  }\n\n  return PACKET_OK;\n}\n\nint PacketHandler::handshake(User* user)\n{\n  std::string host;\n  MS_VarInt version;\n  int16_t port;\n  MS_VarInt nextState;\n\n  user->buffer >> version >> host >> port >> nextState;\n\n  // Check for data\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  LOG(INFO, \"Packets\", \"Player \" + dtos((double)user->UID) + \" login v.\" + dtos((double)version) + \" : \");\n\n\n  // If version is not the current version\n  if (static_cast<int64_t>(version) != PROTOCOL_VERSION)\n  {\n    user->kick(ServerInstance->config()->sData(\"strings.wrong_protocol\"));\n    return PACKET_OK;\n  }\n  \n  // If userlimit is reached\n  if ((int)User::all().size() > ServerInstance->config()->iData(\"system.user_limit\"))\n  {\n    user->kick(ServerInstance->config()->sData(\"strings.server_full\"));\n    return PACKET_OK;\n  }\n\n  // Move to the next state\n  if (nextState >= 0 && nextState < 4)\n    user->gameState = (uint8_t)nextState;\n  \n  return PACKET_OK;\n}\n\nint PacketHandler::chat_message(User* user)\n{\n  std::string msg;\n\n  user->buffer >> msg;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  ServerInstance->chat()->handleMsg(user, msg);\n\n  return PACKET_OK;\n}\n\nint PacketHandler::player(User* user)\n{\n  //OnGround packet\n  int8_t onground;\n  user->buffer >> onground;\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  return PACKET_OK;\n}\n\nint PacketHandler::player_position(User* user)\n{\n  double x, y, z;\n  int8_t onground;\n\n  user->buffer >> x >> y >> z >> onground;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  user->updatePos(x, y, z, 0.0);\n\n\n  return PACKET_OK;\n}\n\nint PacketHandler::player_look(User* user)\n{\n  float yaw, pitch;\n  int8_t onground;\n\n  user->buffer >> yaw >> pitch >> onground;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  user->updateLook(yaw, pitch);\n\n\n\n  return PACKET_OK;\n}\n\nint PacketHandler::player_position_and_look(User* user)\n{\n  double x, y, z;\n  float yaw, pitch;\n  int8_t onground;\n\n  user->buffer >> x >> y >> z\n               >> yaw >> pitch >> onground;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  //Update user data\n  user->updatePos(x, y, z, 0.0);\n  user->updateLook(yaw, pitch);\n\n\n\n  return PACKET_OK;\n}\n\nint PacketHandler::player_digging(User* user)\n{\n  int8_t status;\n  int32_t x;\n  int16_t  y;\n  int32_t z;\n  int8_t direction;\n  uint8_t block;\n  uint8_t meta;\n  uint64_t position;\n  BlockBasicPtr blockcb;\n  BlockDefault blockD;\n\n  user->buffer >> status >> position >> direction;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  positionToXYZ(position, x, y, z);\n\n\n  if (!ServerInstance->map(user->pos.map)->getBlock(x, y, z, &block, &meta))\n  {\n    blockD.revertBlock(user, x, y, z, user->pos.map);\n    return PACKET_OK;\n  }\n\n  // Blocks that break with first hit\n  if(status == BLOCK_STATUS_STARTED_DIGGING)\n  {\n      if( user->creative || (block == BLOCK_SNOW || block == BLOCK_REED || block == BLOCK_TORCH\n                             || block == BLOCK_REDSTONE_WIRE || block == BLOCK_RED_ROSE || block == BLOCK_YELLOW_FLOWER\n                             || block == BLOCK_BROWN_MUSHROOM || block == BLOCK_RED_MUSHROOM\n                             || block == BLOCK_REDSTONE_TORCH_OFF || block == BLOCK_REDSTONE_TORCH_ON))\n      {\n          status = BLOCK_STATUS_BLOCK_BROKEN;\n      }\n  }\n\n  switch (status)\n  {\n  case BLOCK_STATUS_STARTED_DIGGING:\n  {\n    runAllCallback(\"PlayerDiggingStarted\",user->nick.c_str(), x, y, z, direction);\n\n    for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      blockcb = ServerInstance->plugin()->getBlockCB()[i];\n      if (blockcb != NULL && blockcb->affectedBlock(block))\n      {\n        blockcb->onStartedDigging(user, status, x, y, z, user->pos.map, direction);\n      }\n    }\n    break;\n  }\n\n  case BLOCK_STATUS_BLOCK_BROKEN:\n  {\n    //Player tool usage calculation etc\n\n    bool rightUse;\n    int16_t itemSlot = user->currentItemSlot() + 36;\n    int16_t itemHealth = ServerInstance->inventory()->itemHealth(user->inv[itemSlot].getType(), block, rightUse);\n    if (itemHealth > 0)\n    {\n      user->inv[itemSlot].incHealth();\n      if (!rightUse)\n      {\n        user->inv[itemSlot].incHealth();\n      }\n\n      if (itemHealth <= user->inv[itemSlot].getHealth())\n      {\n        user->inv[itemSlot].decCount();\n\n        if (user->inv[itemSlot].getCount() == 0)\n        {\n          user->inv[itemSlot].setHealth(0);\n          user->inv[itemSlot].setType(-1);\n        }\n      }\n      ServerInstance->inventory()->setSlot(user, WINDOW_PLAYER, itemSlot, &user->inv[itemSlot]);\n    }\n\n    runCallbackUntilFalse(\"BlockBreakPre\",user->nick.c_str(), x, y, z);\n    if (callbackReturnValue)\n    {\n      blockD.revertBlock(user, x, y, z, user->pos.map);\n      return PACKET_OK;\n    }\n\n    runAllCallback(\"BlockBreakPost\",user->nick.c_str(), x, y, z);\n\n    for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      blockcb = ServerInstance->plugin()->getBlockCB()[i];\n      if (blockcb != NULL && blockcb->affectedBlock(block))\n      {\n        if (blockcb->onBroken(user, status, x, y, z, user->pos.map, direction))\n        {\n          // Do not break\n          return PACKET_OK;\n        }\n        else\n        {\n          break;\n        }\n      }\n    }\n\n    /* notify neighbour blocks of the broken block */\n    status = block;\n    if (ServerInstance->map(user->pos.map)->getBlock(x + 1, y, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      runAllCallback(\"BlockNeighbourBreak\",user->nick.c_str(), x + 1, y, z, x, int8_t(y), z);\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))\n        {\n          blockcb->onNeighbourBroken(user, status, x + 1, y, z, user->pos.map, BLOCK_SOUTH);\n        }\n      }\n\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x - 1, y, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      runAllCallback(\"BlockNeighbourBreak\",user->nick.c_str(), x - 1, y, z, x, int8_t(y), z);\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))\n        {\n          blockcb->onNeighbourBroken(user, status, x - 1, y, z, user->pos.map, BLOCK_NORTH);\n        }\n      }\n\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y + 1, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      runAllCallback(\"BlockNeighbourBreak\",user->nick.c_str(), x, y + 1, z, x, int8_t(y), z);\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))\n        {\n          blockcb->onNeighbourBroken(user, status, x, y + 1, z, user->pos.map, BLOCK_TOP);\n        }\n      }\n\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y - 1, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      runAllCallback(\"BlockNeighbourBreak\",user->nick.c_str(), x, y - 1, z, x, int8_t(y), z);\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))\n        {\n          blockcb->onNeighbourBroken(user, status, x, y - 1, z, user->pos.map, BLOCK_BOTTOM);\n        }\n      }\n\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y, z + 1, &block, &meta) && block != BLOCK_AIR)\n    {\n      runAllCallback(\"BlockNeighbourBreak\",user->nick.c_str(), x, y, z + 1, x, int8_t(y), z);\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))\n        {\n          blockcb->onNeighbourBroken(user, status, x, y, z + 1, user->pos.map, BLOCK_WEST);\n        }\n      }\n\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y, z - 1, &block, &meta) && block != BLOCK_AIR)\n    {\n      runAllCallback(\"BlockNeighbourBreak\",user->nick.c_str(), x, y, z - 1, x, int8_t(y), z);\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && (blockcb->affectedBlock(status) || blockcb->affectedBlock(block)))\n        {\n          blockcb->onNeighbourBroken(user, status, x, y, z - 1, user->pos.map, BLOCK_EAST);\n        }\n      }\n\n    }\n\n    break;\n  }\n  case BLOCK_STATUS_DROP_ITEM_STACK:\n  case BLOCK_STATUS_DROP_ITEM:\n  {\n    //ToDo: handle\n    #define itemSlot (36+user->currentItemSlot())\n    if (user->inv[itemSlot].getType() > 0)\n    {\n      ServerInstance->map(user->pos.map)->createPickupSpawn(int(user->pos.x), int(user->pos.y), int(user->pos.z), int(user->inv[itemSlot].getType()), 1, int(user->inv[itemSlot].getHealth()), user);\n\n      user->inv[itemSlot].decCount();\n    }\n    break;\n    #undef itemSlot\n  }\n\n  }\n\n  return PACKET_OK;\n}\n\n\n\nint PacketHandler::player_block_placement(User* user)\n{\n  uint64_t position;\n  int16_t y = 0;\n  int8_t direction = 0;\n  int16_t newblock = 0;\n  int32_t x, z = 0;\n  /* replacement of block */\n  uint8_t oldblock = 0;\n  uint8_t metadata = 0;\n  /* neighbour blocks */\n  uint8_t block = 0;\n  uint8_t meta  = 0;\n  int8_t count  = 0;\n  int16_t health = 0;\n  BlockBasicPtr blockcb;\n  BlockDefault blockD;\n  int8_t nbt;\n  int8_t posx,posy,posz;\n  NBT_Value* nbtdata = nullptr;\n\n  user->buffer >> position >> direction >> newblock;\n\n  if(newblock != -1)\n  {\n    int8_t count;\n    int16_t damage;\n    user->buffer >> count >> damage;\n    user->buffer >> nbt;\n    if (nbt != 0)\n    {\n      int32_t nbtlen = user->packetLen - (user->buffer.m_readPos+2);  \n      if (nbtlen > 3)\n      {\n        uint8_t *buf = (uint8_t*)malloc(nbtlen-3);\n\n        std::copy(user->buffer.m_readBuffer.begin() + user->buffer.m_readPos+2, \n                  user->buffer.m_readBuffer.begin() + user->buffer.m_readPos-1 + nbtlen, buf);\n        nbtlen -= 3;\n        nbtdata = new NBT_Value(NBT_Value::eTAG_Type::TAG_COMPOUND, &buf,nbtlen);\n\n        #ifdef DEBUG\n        std::string data, name;\n        nbtdata->Dump(data);\n\n        std::cout << data << std::endl;\n        #endif\n        \n        delete[] buf;\n\n        // Hax, go forward length of the nbt data (-1 because we already read that before)\n        user->buffer.m_readPos += nbtlen-1;\n      }\n    }\n  }\n\n  // ToDo: use nbtdata, else just clean up\n  if (nbtdata) delete nbtdata;\n    \n  user->buffer >> posx >> posy >> posz;\n  \n  positionToXYZ(position, x, y, z);\n\n  ItemBasicPtr itemcb;\n  if (direction == -1 && x == -1 && y == 255 && z == -1)\n  {\n    // Right clicked without pointing at a tile\n    Item* item = &(user->inv[user->curItem + 36]);\n    runCallbackUntilFalse(\"ItemRightClickPre\",user->nick.c_str(), x, y, z, item->getType(), direction);\n    if (callbackReturnValue)\n    {\n      return PACKET_OK;\n    }\n\n\n    for (uint32_t i = 0 ; i < ServerInstance->plugin()->getItemCB().size(); i++)\n    {\n      itemcb = ServerInstance->plugin()->getItemCB()[i];\n      if (itemcb != NULL && itemcb->affectedItem(newblock))\n      {\n        itemcb->onRightClick(user, item);\n      }\n    }\n    return PACKET_OK;\n  }\n\n  if (!ServerInstance->map(user->pos.map)->getBlock(x, y, z, &oldblock, &metadata))\n  {\n    blockD.revertBlock(user, x, y, z, user->pos.map);\n    return PACKET_OK;\n  }\n\n  /* Protocol docs say this should be what interacting is. */\n  if (oldblock != BLOCK_AIR)\n  {\n    runAllCallback(\"PlayerBlockInteract\",user->nick.c_str(), x, y, z);\n    for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      blockcb = ServerInstance->plugin()->getBlockCB()[i];\n      if (blockcb != NULL && blockcb->affectedBlock(oldblock))\n      {\n        //This should actually make the boolean do something. Maybe.\n        if (blockcb->onInteract(user, x, y, z, user->pos.map))\n        {\n          blockD.revertBlock(user, x, y, z, user->pos.map);\n          return PACKET_OK;\n        }\n        else\n        {\n          break;\n        }\n      }\n    }\n  }\n  bool foundFromInventory = false;\n\n#define INV_TASKBAR_START 36\n  if (user->inv[INV_TASKBAR_START + user->currentItemSlot()].getType() == newblock && newblock != -1)\n  {\n    foundFromInventory = true;\n  }\n#undef INV_TASKBAR_START\n\n  // TODO: Handle processing of\n  if (direction == -1 || !foundFromInventory)\n  {\n    blockD.revertBlock(user, x, y, z, user->pos.map);\n    return PACKET_OK;\n  }\n\n  // Minecart testing!!\n  if (newblock == ITEM_MINECART && ServerInstance->map(user->pos.map)->getBlock(x, y, z, &oldblock, &metadata))\n  {\n    if (oldblock != BLOCK_MINECART_TRACKS)\n    {\n      return PACKET_OK;\n    }\n    \n    int32_t EID = Mineserver::generateEID();\n    // MINECART\n    user->sendAll(Protocol::spawnObject(EID,OBJECT_TYPE_MINECART,x,y,z,0));\n\n    ServerInstance->map(user->pos.map)->minecarts.push_back(MinecartData(EID,vec(x*32+16,y*32+16,z*32+16),vec(0,0,0),microTime()));\n    //ToDo: Store\n  }\n\n  if (newblock == -1 && newblock != ITEM_SIGN)\n  {\n#ifdef DEBUG\n    LOG(DEBUG, \"Packets\", \"ignoring: \" + dtos(newblock));\n#endif\n    return PACKET_OK;\n  }\n\n  if (y < 0)\n  {\n    return PACKET_OK;\n  }\n\n#ifdef DEBUG\n  LOG(DEBUG, \"Packets\", \"Block_placement: \" + dtos(newblock) + \" (\" + dtos(x) + \",\" + dtos((int)y) + \",\" + dtos(z) + \") dir: \" + dtos((int)direction));\n#endif\n\n  if (direction)\n  {\n    direction = 6 - direction;\n  }\n\n  //if (ServerInstance->map()->getBlock(x, y, z, &oldblock, &metadata))\n  {\n    uint8_t oldblocktop;\n    uint8_t metadatatop;\n    int16_t check_y = y;\n    int32_t check_x = x;\n    int32_t check_z = z;\n\n    /* client doesn't give us the correct block for lava and water, check block above */\n    switch (direction)\n    {\n    case BLOCK_BOTTOM:\n      check_y--;\n      break;\n    case BLOCK_TOP:\n      check_y++;\n      break;\n    case BLOCK_NORTH:\n      check_x++;\n      break;\n    case BLOCK_SOUTH:\n      check_x--;\n      break;\n    case BLOCK_EAST:\n      check_z++;\n      break;\n    case BLOCK_WEST:\n      check_z--;\n      break;\n    default:\n      break;\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(check_x, check_y, check_z, &oldblocktop, &metadatatop) &&\n        (oldblocktop == BLOCK_LAVA || oldblocktop == BLOCK_STATIONARY_LAVA ||\n         oldblocktop == BLOCK_WATER || oldblocktop == BLOCK_STATIONARY_WATER))\n    {\n      /* block above needs replacing rather then the block sent by the client */\n\n      // TODO: Does this require some form of recursion for multiple water/lava blocks?\n\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && blockcb->affectedBlock(newblock))\n        {\n          blockcb->onReplace(user, newblock, check_x, check_y, check_z, user->pos.map, direction);\n        }\n      }\n\n      runCallbackUntilFalse(\"BlockReplacePre\",user->nick.c_str(), check_x, check_y, check_z, oldblock, newblock);\n      if (callbackReturnValue)\n      {\n        blockD.revertBlock(user, x, y, z, user->pos.map);\n        return PACKET_OK;\n      }\n      runAllCallback(\"BlockReplacePost\",user->nick.c_str(), check_x, check_y, check_z, oldblock, newblock);\n    }\n    else\n    {\n      /*      for(int i =0 ; i<ServerInstance->plugin()->getBlockCB().size(); i++)\n            {\n              blockcb = ServerInstance->plugin()->getBlockCB()[i];\n              if(blockcb!=NULL && blockcb->affectedBlock(newblock))\n              {\n                blockcb->onReplace(user, newblock,check_x,check_y,check_z,user->pos.map,direction);\n              }\n            }*/\n\n      runCallbackUntilFalse(\"BlockReplacePre\",user->nick.c_str(), x, y, z, oldblock, newblock);\n      if (callbackReturnValue)\n      {\n        blockD.revertBlock(user, x, y, z, user->pos.map);\n        return PACKET_OK;\n      }\n      runAllCallback(\"BlockReplacePost\",user->nick.c_str(), x, y, z, oldblock, newblock);\n    }\n\n    runCallbackUntilFalse(\"BlockPlacePre\",user->nick.c_str(), x, y, z, newblock, direction);\n    if(callbackReturnValue)\n    {\n      blockD.revertBlock(user, x, y, z, user->pos.map);\n      return PACKET_OK;\n    }\n\n    /* We pass the newblock to the newblock's onPlace callback because\n    the callback doesn't know what type of block we're placing. Instead\n    the callback's job is to describe the behaviour when placing the\n    block down, not to place any specifically block itself. */\n    for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n    {\n      blockcb = ServerInstance->plugin()->getBlockCB()[i];\n      if (blockcb != NULL && blockcb->affectedBlock(newblock))\n      {\n        if (blockcb->onPlace(user, newblock, x, y, z, user->pos.map, direction))\n        {\n          return PACKET_OK;\n        }\n        else\n        {\n          break;\n        }\n      }\n    }\n    runAllCallback(\"BlockPlacePost\",user->nick.c_str(), x, y, z, newblock, direction);\n\n    /* notify neighbour blocks of the placed block */\n    if (ServerInstance->map(user->pos.map)->getBlock(x + 1, y, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && blockcb->affectedBlock(newblock))\n        {\n          blockcb->onNeighbourPlace(user, newblock, x + 1, y, z, user->pos.map, direction);\n        }\n      }\n\n      runAllCallback(\"BlockNeighbourPlace\",user->nick.c_str(), x + 1, y, z);\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x - 1, y, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && blockcb->affectedBlock(newblock))\n        {\n          blockcb->onNeighbourPlace(user, newblock, x - 1, y, z, user->pos.map, direction);\n        }\n      }\n      runAllCallback(\"BlockNeighbourPlace\",user->nick.c_str(), x - 1, y, z);\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y + 1, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && blockcb->affectedBlock(newblock))\n        {\n          blockcb->onNeighbourPlace(user, newblock, x, y + 1, z, user->pos.map, direction);\n        }\n      }\n      runAllCallback(\"BlockNeighbourPlace\",user->nick.c_str(), x, y + 1, z);\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y - 1, z, &block, &meta) && block != BLOCK_AIR)\n    {\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && blockcb->affectedBlock(newblock))\n        {\n          blockcb->onNeighbourPlace(user, newblock, x, y - 1, z, user->pos.map, direction);\n        }\n      }\n      runAllCallback(\"BlockNeighbourPlace\",user->nick.c_str(), x, y - 1, z);\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y, z + 1, &block, &meta) && block != BLOCK_AIR)\n    {\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && blockcb->affectedBlock(newblock))\n        {\n          blockcb->onNeighbourPlace(user, newblock, x, y, z + 1, user->pos.map, direction);\n        }\n      }\n      runAllCallback(\"BlockNeighbourPlace\",user->nick.c_str(), x, y, z + 1);\n    }\n\n    if (ServerInstance->map(user->pos.map)->getBlock(x, y, z - 1, &block, &meta) && block != BLOCK_AIR)\n    {\n      for (uint32_t i = 0 ; i < ServerInstance->plugin()->getBlockCB().size(); i++)\n      {\n        blockcb = ServerInstance->plugin()->getBlockCB()[i];\n        if (blockcb != NULL && blockcb->affectedBlock(newblock))\n        {\n          blockcb->onNeighbourPlace(user, newblock, x, y, z - 1, user->pos.map, direction);\n        }\n      }\n      runAllCallback(\"BlockNeighbourPlace\",user->nick.c_str(), x, y, z - 1);\n    }\n  }\n  // Now we're sure we're using it, lets remove from inventory!\n#define INV_TASKBAR_START 36\n  if (user->inv[INV_TASKBAR_START + user->currentItemSlot()].getType() == newblock && newblock != -1)\n  {\n    //if(newblock<256)\n    {\n      // It's a block\n      if(!user->creative)\n        user->inv[INV_TASKBAR_START + user->currentItemSlot()].decCount();\n    }\n  }\n#undef INV_TASKBAR_START\n\n\n\n  /* TODO: Should be removed from here. Only needed for liquid related blocks? */\n  ServerInstance->physics(user->pos.map)->checkSurrounding(vec(x, y, z));\n  return PACKET_OK;\n}\n\nint PacketHandler::held_item_change(User* user)\n{\n  int16_t itemSlot;\n  user->buffer >> itemSlot;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n  user->curItem = itemSlot;\n\n  //Send holding change to others\n  Packet pkt = Protocol::entityEquipment(user->UID, 0, user->inv[itemSlot + 36]);\n  user->sendOthers(pkt);\n\n  // Set current itemID to user\n  user->setCurrentItemSlot(itemSlot);\n  return PACKET_OK;\n}\n\nint PacketHandler::animation(User* user)\n{\n  Packet pkt = Protocol::animation(user->UID,0);\n  user->sendOthers(pkt);\n\n  runAllCallback(\"PlayerArmSwing\",user->nick.c_str());\n\n  return PACKET_OK;\n}\n\nint PacketHandler::pickup_spawn(User* user)\n{\n  //uint32_t curpos = 4; //warning: unused variable ‘curpos’\n  spawnedItem item;\n\n  item.health = 0;\n\n  int8_t yaw, pitch, roll;\n\n  user->buffer >> (int32_t&)item.EID;\n\n  user->buffer >> (int16_t&)item.item >> (int8_t&)item.count >> (int16_t&)item.health;\n  user->buffer >> (int32_t&)item.pos.x() >> (int32_t&)item.pos.y() >> (int32_t&)item.pos.z();\n  user->buffer >> yaw >> pitch >> roll;\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n\n\n  item.EID       = Mineserver::generateEID();\n\n  item.spawnedBy = user->UID;\n  item.spawnedAt = time(NULL);\n\n  // Modify the position of the dropped item so that it appears in front of user instead of under user\n  int distanceToThrow = 64;\n  float angle = float(DEGREES_TO_RADIANS(user->pos.yaw + 45));     // For some reason, yaw seems to be off to the left by 45 degrees from where you're actually looking?\n  int x = int(cos(angle) * distanceToThrow - sin(angle) * distanceToThrow);\n  int z = int(sin(angle) * distanceToThrow + cos(angle) * distanceToThrow);\n  item.pos += vec(x, 0, z);\n\n  ServerInstance->map(user->pos.map)->sendPickupSpawn(item);\n\n  return PACKET_OK;\n}\n\n\nint PacketHandler::use_entity(User* user)\n{\n  MS_VarInt target, type;\n  int8_t leftClick;\n  float x, y, z;\n\n\n  user->buffer >> target >> type;\n  \n  if ((int32_t)type == USE_ENTITY_INTERACT_AT)\n  {\n    user->buffer >> x >> y >> z;\n  }\n\n  if (!user->buffer)\n  {\n    return PACKET_NEED_MORE_DATA;\n  }\n\n\n\n  if ((int32_t)type == USE_ENTITY_INTERACT)\n  {\n    // right clicks: interaction, attaching, ...\n    for (size_t i = 0; i < ServerInstance->mobs()->getMobCount(); i++)\n    {\n      if (ServerInstance->mobs()->getMobByID(i)->UID == (uint32_t)target)\n      {\n        runAllCallback(\"interact\",user->nick.c_str(), (int32_t)ServerInstance->mobs()->getMobByTarget((uint32_t)target));\n        //make a callback\n        return PACKET_OK;\n      }\n    }\n\n    // No? Try to attach.\n    //Attach\n    if (user->attachedTo == 0)\n    {\n      user->sendAll(Protocol::attachEntity(user->UID,(int32_t)target));\n      user->attachedTo = (int32_t)target;\n      for (size_t i = 0; i < ServerInstance->map(user->pos.map)->minecarts.size(); i++)\n      {\n        if(ServerInstance->map(user->pos.map)->minecarts[i].EID == (uint32_t)target)\n        {\n          ServerInstance->map(user->pos.map)->minecarts[i].speed = vec(64,0,0);\n        }\n      }\n    }\n    //Detach\n    else\n    {\n      for (size_t i = 0; i < ServerInstance->map(user->pos.map)->minecarts.size(); i++)\n      {\n        if(ServerInstance->map(user->pos.map)->minecarts[i].EID == user->attachedTo)\n        {\n          ServerInstance->map(user->pos.map)->minecarts[i].speed = vec(0,0,0);\n        }\n      }\n      user->sendAll(Protocol::attachEntity(user->UID,-1));\n      user->attachedTo = 0;\n    }\n    return PACKET_OK;\n\n  }\n  else if ((int32_t)type == USE_ENTITY_ATTACK)\n  {\n    // left clicks: fighhht!\n    if (ServerInstance->m_pvp_enabled)\n    {\n      //This is used when punching users, mobs or other entities\n      for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n      {\n        if ((*it)->UID == (uint32_t)target)\n        {\n          (*it)->health--;\n          (*it)->sethealth((*it)->health);\n\n          if ((*it)->health <= 0)\n          {\n            (*it)->sendOthers(Protocol::entityStatus((int32_t)(*it)->UID, ENTITY_STATUS_DEAD));\n          }\n          break;\n        }\n      }\n    }\n    for (size_t i = 0; i < ServerInstance->mobs()->getMobCount(); i++)\n    {\n      if (ServerInstance->mobs()->getMobByID(i)->UID == (uint32_t)target)\n      {\n        //int h = ServerInstance->mobs()->getMobByID(i)->health - 1;\n        //ServerInstance->mobs()->getMobByID(i)->sethealth(h);\n        runAllCallback(\"gotAttacked\",user->nick.c_str(),(int32_t)ServerInstance->mobs()->getMobByTarget(target));\n        //make a callback\n        break;\n      }\n    }\n  }\n\n  return PACKET_OK;\n}\n\n\n// Serverlist ping (http://wiki.vg/Server_List_Ping)\nint PacketHandler::server_list_ping(User* user)\n{  \n  //Reply with server info\n  std::string line;\n  Packet pkt;\n\n  line = \"{ \\\"version\\\": {\\\"name\\\": \\\"\"+MINECRAFT_VERSION+\"\\\", \\\"protocol\\\": \"+my_itoa(PROTOCOL_VERSION)+\" },\\n\"+\n        \"\\\"players\\\": {\"+\n          \"\\\"max\\\": \"+my_itoa(ServerInstance->config()->iData(\"system.user_limit\"))+\",\"+\n          \"\\\"online\\\": \"+my_itoa(ServerInstance->getLoggedUsersCount())+\n        \" },\"+\n        \"\\\"description\\\": {\\\"text\\\": \\\"\"+ServerInstance->config()->sData(\"system.server_name\")+\"\\\" }\"+\n      \"}\";\n\n  LOG2(DEBUG, line);\n  pkt << (uint8_t)0 << line;\n\n  user->writePacket(pkt);\n\n  return PACKET_OK;\n}\n\nint PacketHandler::ping(User* user)\n{\n\n  uint64_t value;\n  user->buffer >> value; \n  \n  std::string line;\n  Packet pkt;\n\n  pkt << (uint8_t)1 << value;\n\n  user->writePacket(pkt);\n\n  return PACKET_OK;\n}\n\n//Sent when right clicking blocks without placing, interact?\nint PacketHandler::block_change(User* user)\n{\n  int32_t x,z;\n  int8_t y,type,meta;\n\n  user->buffer >> x >> y >> z >> type >> meta;\n  //printf(\"block change %d:%d:%d type %d meta %d\\r\\n\",x,y,z, type,meta);\n\n  return PACKET_OK;\n}\n\n\nPacket& Packet::operator<<(const std::string& str)\n{\n  writeString(str);\n  return *this;\n}\n\nPacket& Packet::operator>>(std::string& str)\n{\n  str = readString();\n  return *this;\n}\n\nPacket& Packet::operator<<(const MS_VarInt& varint)\n{\n  writeVarInt(static_cast<int64_t>(varint));\n  return *this;\n}\nPacket& Packet::operator>>(MS_VarInt& varint)\n{\n  varint.val = readVarInt();\n  return *this;\n}\n\nPacket& Packet::operator<<(const Packet& other)\n{\n  addToWrite(other);\n  return *this;\n}\n\n// writeString and readString provide the old, 8-bit string features.\n\nvoid Packet::writeString(const std::string& str)\n{\n  MS_VarInt len;\n  len.val = str.size();\n  *this << len;\n  addToWrite(reinterpret_cast<const uint8_t*>(str.data()), str.length());\n}\n\nstd::string Packet::readString()\n{\n  std::string str;\n\n  if (haveData(1))\n  {\n    MS_VarInt lenval;\n    *this >> lenval;\n    uint16_t len = (uint16_t)static_cast<int64_t>(lenval);\n\n    if (len && haveData(len))\n    {\n      for (size_t i = 0; i < uint16_t(len); ++i)\n        str += m_readBuffer[m_readPos++];\n    }\n  }\n\n  return str;\n}\n\nvoid Packet::writeVarInt(int64_t varint)\n{\n  uint8_t out[10]; // 64bit variables should fit in this\n  uint8_t cur_byte = 0;\n  while(varint > 127)\n  {\n    out[cur_byte++] = (varint & 0x7f) | 0x80;\n    varint >>= 7;\n  }\n  out[cur_byte++] = (uint8_t)varint;\n  write(out, cur_byte);\n}\n\nint64_t Packet::readVarInt()\n{\n  int64_t ret = 0;\n\n  int byte_idx = 0;\n\n  uint8_t byte;\n  do{\n    if (read(&byte, 1) != 1) {\n      // silent fail? not anymore\n      throw std::logic_error(\"readVarInt\");\n      return 0;\n    }\n    ret += (byte & 0x7F) << (7*byte_idx++);\n  }while(byte & 0x80);\n\n  return ret;\n}\n\n\nvoid Packet::writePacket(const Packet& p, uint16_t compression)\n  {\n    MS_VarInt datalen;\n    datalen.val = p.m_writeBuffer.end()-p.m_writeBuffer.begin();\n\n    if (compression)\n    {\n      if (datalen > compression) \n      {\n        uint8_t* tempBuf = new uint8_t[(uint32_t)datalen+16];\n        uint8_t* inBuf = new uint8_t[(uint32_t)datalen];\n\n        // Read the writebuffer to a continuous buffer\n        std::copy(p.m_writeBuffer.begin(), p.m_writeBuffer.end(), inBuf);\n\n        // Compress the buffer data\n        uLongf written = (uint32_t)datalen+16;\n        compress(tempBuf, &written, inBuf, (uint32_t)datalen);\n\n        // We have to get the length of the uncompressed data\n        Packet pkt_len;\n        pkt_len << datalen;\n        \n        // Compressed packet length is the uncompressed length varint len + compressed data len\n        MS_VarInt compressedLen;\n        compressedLen.val = pkt_len.m_writeBuffer.size() + written;\n\n        // Write the total packet length, uncompressed length and the compressed data\n        Packet packetOut;\n        packetOut << compressedLen << datalen;\n        packetOut.write(tempBuf, written);\n        addToWrite(packetOut);\n        delete[] tempBuf;\n        delete[] inBuf;\n      }\n      else\n      {\n        // If data is uncompressed, set uncompressed size to \"0\"\n        datalen.val ++;\n        *this << datalen;\n        *this << (uint8_t)0;\n        addToWrite(p);\n      }\n    }\n    else {\n      // Write without the compress field\n      MS_VarInt len;\n      len.val = p.m_writeBuffer.end()-p.m_writeBuffer.begin();\n      *this << len;\n      addToWrite(p);\n    }\n  }"
  },
  {
    "path": "src/packets.h",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _PACKETS_H\n#define _PACKETS_H\n\n#include <deque>\n#include <string>\n#include <cstring>\n#include <stdint.h>\n\n#include <stdio.h>\n\n/// endian functions... because windows htons are actually library functions\n\ninline uint16_t _htons(uint16_t x){\n#ifdef __GNUC__\n  /// return __builtin_bswap16(x); /// TODO: use when works, doesn't work in mingw64 4.7.1\n  return x<<8 | x>>8;\n#else\n  return x<<8 | x>>8;\n#endif\n}\n\ninline uint32_t _htonl(uint32_t x){\n#ifdef __GNUC__\n  return __builtin_bswap32(x);\n#else\n  uint16_t low  = x>>16;\n  uint16_t high = x;\n\n  return uint32_t(_htons(high))<<16 | _htons(low);\n#endif\n}\n\ninline uint64_t _htonll(uint64_t x){\n#ifdef __GNUC__\n  return __builtin_bswap64(x);\n#else\n  uint32_t low = uint32_t(x >> 32);\n  uint32_t high = uint32_t(x);\n\n  return uint64_t(_htonl(high))<<32 | _htonl(low);\n#endif\n}\n\n#ifndef __BIG_ENDIAN__\n#define htons(x)  _htons ((uint16_t)x)\n#define htonl(x)  _htonl ((uint32_t)x)\n#define htonll(x) _htonll((uint64_t)x)\n#else\n#define htons\n#define htonl\n#define htonll\n#endif\n/// bswap c++ endian flipper!\n\n#define bswap_def(TYPE, FLIPPER) \\\n  inline TYPE bswap(const TYPE& x){ return (TYPE)FLIPPER(x); }\n\nbswap_def(int8_t, )\nbswap_def(uint8_t, )\n\nbswap_def(int16_t, htons)\nbswap_def(uint16_t, htons)\n\nbswap_def(int32_t, htonl)\nbswap_def(uint32_t, htonl)\n\nbswap_def(int64_t, htonll)\nbswap_def(uint64_t, htonll)\n\n/// because float/double casting is fucking special in c++\n/// FIXME: find a way to cast float types the right way to data types of uint\ninline float bswap(const float& x){\n  uint32_t i = uint32_t(htonl(*(uint32_t*)&x));\n  return *(float*)&i;\n}\n\ninline double bswap(const double& x){\n  uint64_t i = htonll(*(uint64_t*)&x);\n  return *(double*)&i;\n}\n\n#undef bswap_def\n\n#undef htons\n#undef htonl\n#undef htonll\n\n#define PACKET_NEED_MORE_DATA -3\n#define PACKET_DOES_NOT_EXIST -2\n#define PACKET_VARIABLE_LEN   -1\n#define PACKET_OK             0\n\n#ifndef M_PI\n#define M_PI 3.141592653589793238462643\n#endif\n\nclass PacketHandler;\nclass User;\n\n// gameState names\nenum {\n  STATE_HANDSHAKE = 0,\n  STATE_STATUS    = 1,\n  STATE_LOGIN     = 2,\n  STATE_PLAY      = 3\n};\n\n//Packet names\nenum\n{\n  //Client to server\n\n  // State: Handshake\n  PACKET_IN_HANDSHAKE                 = 0x00,\n\n  // State: Status\n  PACKET_IN_SERVER_LIST_PING          = 0x00,\n  PACKET_IN_PING                      = 0x01,\n\n  // State: Login\n  PACKET_IN_LOGIN_REQUEST             = 0x00,\n  PACKET_IN_ENCRYPTION_RESPONSE       = 0x01,\n  \n  // State: Play\n  PACKET_IN_KEEP_ALIVE                = 0x00,\n  PACKET_IN_CHAT_MESSAGE              = 0x01,\n  PACKET_IN_USE_ENTITY                = 0x02,\n  PACKET_IN_PLAYER                    = 0x03,\n  PACKET_IN_PLAYER_POSITION           = 0x04,\n  PACKET_IN_PLAYER_LOOK               = 0x05,\n  PACKET_IN_PLAYER_POSITION_AND_LOOK  = 0x06,\n  PACKET_IN_PLAYER_DIGGING            = 0x07,\n  PACKET_IN_PLAYER_BLOCK_PLACEMENT    = 0x08,\n  PACKET_IN_HELD_ITEM_CHANGE          = 0x09,    \n  PACKET_IN_ANIMATION                 = 0x0a,\n  PACKET_IN_ENTITY_ACTION             = 0x0b,\n  PACKET_IN_CLOSE_WINDOW              = 0x0d,\n  PACKET_IN_CLICK_WINDOW              = 0x0e,\n  PACKET_IN_CONFIRM_TRANSACTION       = 0x0f,\n  PACKET_IN_CREATIVE_INVENTORY_ACTION = 0x10,\n  PACKET_IN_ENCHANT_ITEM              = 0x11,\n  PACKET_IN_UPDATE_SIGN               = 0x12,\n  PACKET_IN_PLAYER_ABILITIES          = 0x13,\n  PACKET_IN_TAB_COMPLETE              = 0x14,\n  PACKET_IN_CLIENT_SETTINGS           = 0x15,\n  PACKET_IN_CLIENT_STATUS             = 0x16,\n  PACKET_IN_PLUGIN_MESSAGE            = 0x17,\n\n\n  PACKET_IN_INVENTORY                 = 0x99,\n  PACKET_IN_BLOCK_CHANGE              = 0x99,\n\n\n  //Server to client\n\n  // State: Login  \n  PACKET_OUT_ENCRYPTION_REQUEST        = 0x01,\n  PACKET_OUT_LOGIN_SUCCESS             = 0x02,\n  PACKET_OUT_SET_COMPRESSION           = 0x03,\n\n  // State: play\n  PACKET_OUT_KEEP_ALIVE                = 0x00,\n  PACKET_OUT_JOIN_GAME                 = 0x01,\n  PACKET_OUT_CHAT_MESSAGE              = 0x02,\n  PACKET_OUT_TIME_UPDATE               = 0x03,\n  PACKET_OUT_ENTITY_EQUIPMENT          = 0x04,\n  PACKET_OUT_SPAWN_POSITION            = 0x05,\n  PACKET_OUT_UPDATE_HEALTH             = 0x06,\n  PACKET_OUT_RESPAWN                   = 0x07,\n  PACKET_OUT_PLAYER_POSITION_AND_LOOK  = 0x08,\n  PACKET_OUT_HELD_ITEM_CHANGE          = 0x09,\n  PACKET_OUT_USE_BED                   = 0x0a,\n  PACKET_OUT_ANIMATION                 = 0x0b,\n  PACKET_OUT_SPAWN_PLAYER              = 0x0c,\n  PACKET_OUT_COLLECT_ITEM              = 0x0d,\n  PACKET_OUT_SPAWN_OBJECT              = 0x0e,\n  PACKET_OUT_SPAWN_MOB                 = 0x0f,\n  PACKET_OUT_SPAWN_PAINTING            = 0x10,\n  PACKET_OUT_SPAWN_EXPERIENCE_ORB      = 0x11,\n  PACKET_OUT_ENTITY_VELOCITY           = 0x12,\n  PACKET_OUT_DESTROY_ENTITIES          = 0x13,\n  PACKET_OUT_ENTITY                    = 0x14,\n  PACKET_OUT_ENTITY_RELATIVE_MOVE      = 0x15,\n  PACKET_OUT_ENTITY_LOOK               = 0x16,\n  PACKET_OUT_ENTITY_LOOK_RELATIVE_MOVE = 0x17,\n  PACKET_OUT_ENTITY_TELEPORT           = 0x18,\n  PACKET_OUT_ENTITY_HEAD_LOOK          = 0x19,\n  PACKET_OUT_ENTITY_STATUS             = 0x1a,\n  PACKET_OUT_ATTACH_ENTITY             = 0x1b,\n  PACKET_OUT_ENTITY_METADATA           = 0x1c,\n  PACKET_OUT_ENTITY_EFFECT             = 0x1d,\n  PACKET_OUT_REMOVE_ENTITY_EFFECT      = 0x1e,\n  PACKET_OUT_SET_EXPERIENCE            = 0x1f,\n  PACKET_OUT_ENTITY_PROPERTIES         = 0x20,\n  PACKET_OUT_MAP_CHUNK                 = 0x21,\n  PACKET_OUT_MULTI_BLOCK_CHANGE        = 0x22,\n  PACKET_OUT_BLOCK_CHANGE              = 0x23,\n  PACKET_OUT_BLOCK_ACTION              = 0x24,\n  PACKET_OUT_BLOCK_BREAK_ANIMATION     = 0x25,\n  PACKET_OUT_MAP_CHUNK_BULK            = 0x26,\n  PACKET_OUT_EXPLOSION                 = 0x27,\n  PACKET_OUT_EFFECT                    = 0x28,\n  PACKET_OUT_SOUND_EFFECT              = 0x29,\n  PACKET_OUT_PARTICLE                  = 0x2a,\n  PACKET_OUT_CHANGE_GAME_STATE         = 0x2b,\n  PACKET_OUT_SPAWN_GLOBAL_ENTITY       = 0x2c,\n  PACKET_OUT_OPEN_WINDOW               = 0x2d,\n  PACKET_OUT_CLOSE_WINDOW              = 0x2e,\n  PACKET_OUT_SET_SLOT                  = 0x2f,\n  PACKET_OUT_WINDOW_ITEMS              = 0x30,\n  PACKET_OUT_WINDOW_PROPERTY           = 0x31,\n  PACKET_OUT_CONFIRM_TRANSACTION       = 0x32,\n  PACKET_OUT_UPDATE_SIGN               = 0x33,\n  PACKET_OUT_MAP                       = 0x34,\n  PACKET_OUT_UPDATE_BLOCK_ENTITY       = 0x35,\n  PACKET_OUT_OPEN_SIGN_EDITOR          = 0x36,\n  PACKET_OUT_STATISTICS                = 0x37,\n  PACKET_OUT_PLAYER_LIST_ITEM          = 0x38,\n  PACKET_OUT_PLAYER_ABILITIES          = 0x39,\n  PACKET_OUT_TAB_COMPLETE              = 0x3a,\n\n  PACKET_OUT_SCOREBOARD_OBJECTIVE      = 0x3b,\n  PACKET_OUT_UPDATE_SCORE              = 0x3c,\n  PACKET_OUT_DISPLAY_SCOREBOARD        = 0x3d,\n  PACKET_OUT_TEAMS                     = 0x3e,\n\n  PACKET_OUT_PLUGIN_MESSAGE            = 0x3f,\n  PACKET_OUT_DISCONNECT                = 0x40,\n  PACKET_OUT_SERVER_DIFFICULTY         = 0x41,\n  PACKET_OUT_COMBAT_EVENT              = 0x42,\n  PACKET_OUT_CAMERA                    = 0x43,\n  PACKET_OUT_WORLD_BORDER              = 0x44,\n  PACKET_OUT_TITLE                     = 0x45,\n  PACKET_OUT_PLAYERLIST_HEADER_FOOTER  = 0x47,\n  PACKET_OUT_RESOURCE_PACK_SEND        = 0x48,\n  PACKET_OUT_UPDATE_ENTITY_NBT         = 0x49  \n  \n\n};\n\ntypedef struct VarInt_internal {\n  VarInt_internal() {};\n  VarInt_internal(int64_t init_value) : val(init_value) {};\n  VarInt_internal(uint32_t init_value) : val((int64_t)init_value) {};\n  operator int64_t() const { return val; }\n  int64_t val;\n} MS_VarInt;\n\nclass Packet\n{\n  // A deque has random-access iterators, so we can track the read position in an integer.\n  typedef std::deque<uint8_t> BufferVector;\n\npublic:\n  BufferVector m_readBuffer;\n  BufferVector m_writeBuffer;\n  size_t m_readPos;\n  bool m_isValid;\n\npublic:\n  Packet()\n    :\n      m_readBuffer(),\n      m_writeBuffer(),\n      m_readPos(0),\n      m_isValid(true)\n  {\n  }\n\n  inline uint8_t firstwrite() const { return m_writeBuffer.front(); }\n\n  inline bool haveData(int requiredBytes)\n  {\n    return m_isValid = m_isValid && (m_readPos + requiredBytes <= m_readBuffer.size());\n  }\n\n  inline operator bool() const\n  {\n    return m_isValid;\n  }\n\n  inline void reset()\n  {\n    m_readPos = 0;\n    m_isValid = true;\n  }\n\n  inline void addToReadBegin(const uint8_t* const data, const size_t len)\n  {\n    m_readBuffer.insert(m_readBuffer.begin(), data, data + len);\n    m_isValid = true;\n  }\n\n  inline void addToRead(const uint8_t* const data, const size_t len)\n  {\n    m_readBuffer.insert(m_readBuffer.end(), data, data + len);\n    m_isValid = true;\n  }\n\n  void writePacket(const Packet& p, uint16_t compression);\n\n  inline void addToWrite(const Packet& p)\n  {\n    m_writeBuffer.insert(m_writeBuffer.end(), p.m_writeBuffer.begin(), p.m_writeBuffer.end());\n  }\n\n  inline void addToWrite(const uint8_t* const buffer, const size_t len)\n  {\n    m_writeBuffer.insert(m_writeBuffer.end(), buffer, buffer + len);\n  }\n\n  size_t read( void* buffer, size_t size){\n    if(haveData(size)){\n      for(size_t i=0;i<size;i++)\n        *((uint8_t*&)buffer)++ = m_readBuffer[m_readPos++];\n      return size;\n    }\n    else return 0;\n  }\n\n  void write( const void* data, size_t size){\n    addToWrite((uint8_t*)data,size);\n  }\n\n  inline void removePacket()\n  {\n    m_readBuffer.erase(m_readBuffer.begin(), m_readBuffer.begin() + m_readPos);\n    m_readPos = 0;\n  }\n  inline void removePacketLen(uint32_t len)\n  {\n    m_readBuffer.erase(m_readBuffer.begin(), m_readBuffer.begin() + len);\n    m_readPos = 0;\n  }\n\n  /// This was too much to write by hand... so I macro'ed - Exim\n  /// Oh wow! These macros are truly Majestic! I can hardly keep my breath. Astounding... - Everyone\n\n#define _rwop(T) \\\n  Packet& operator<<(const T& x){ \\\n  T y = bswap(x); \\\n  write(&y, sizeof(T)); \\\n  return *this; \\\n} \\\n  Packet& operator>>(T& x){ \\\n  if(read(&x,sizeof(T))) \\\n  x = bswap(x); \\\n  return *this; \\\n}\n\n  _rwop( int8_t )\n  _rwop(uint8_t )\n\n  _rwop( int16_t )\n  _rwop(uint16_t )\n\n  _rwop( int32_t )\n  _rwop(uint32_t )\n\n  _rwop( int64_t )\n  _rwop(uint64_t )\n\n  _rwop(float  )\n  _rwop(double )\n#undef _rwop\n\n\n  // convert to wstring and call that operator\n  Packet& operator<<(const std::string& str);\n  Packet& operator>>(std::string& str);\n\n  // Varint reading and writing\n  Packet& operator<<(const MS_VarInt& varint);\n  Packet& operator>>(MS_VarInt& varint);\n\n  void writeString(const std::string& str);\n  std::string readString();\n\n  void writeVarInt(int64_t varint);\n  int64_t readVarInt();\n\n  Packet& operator<<(const Packet& other);\n\n  inline void getData(uint8_t* buf, size_t count)\n  {\n    if (haveData(count))\n    {\n      std::copy(m_readBuffer.begin() + m_readPos, m_readBuffer.begin() + m_readPos + count, buf);\n      m_readPos += count;\n    }\n  }\n\n  inline bool getWriteEmpty() const\n  {\n    return m_writeBuffer.empty();\n  }\n\n  inline void getWriteData(std::vector<char>& buf) const\n  {\n    buf.clear();\n    buf.resize(m_writeBuffer.size(), 0);\n    std::copy(m_writeBuffer.begin(), m_writeBuffer.end(), buf.begin());\n  }\n\n  inline void clearWrite(size_t count)\n  {\n    BufferVector::iterator it = m_writeBuffer.begin();\n    std::advance(it, count);\n    m_writeBuffer.erase(m_writeBuffer.begin(), it);\n  }\n};\n\n\nstruct Packets\n{\n  typedef int (*handler_function)(User*);\n\n  int len;\n  handler_function function;\n\n  Packets(int newlen = PACKET_DOES_NOT_EXIST)\n    : len(newlen)\n  {\n  }\n\n  Packets(handler_function newfunction)\n    : len(PACKET_OK), function(newfunction)\n  {\n  }\n\n  Packets(const Packets & other)\n    : len(other.len), function(other.function)\n  {\n  }\n};\n\nstruct packet_login_request\n{\n  int version;\n  std::string Username;\n  std::string Password;\n  int64_t map_seed;\n  uint8_t dimension;\n};\n\nstruct packet_player_position\n{\n  double x;\n  double y;\n  double stance;\n  double z;\n  char onground;\n};\n\nstruct packet_player_look\n{\n  float yaw;\n  float pitch;\n  char onground;\n};\n\nstruct packet_player_position_and_look\n{\n  double x;\n  double y;\n  double stance;\n  double z;\n  float yaw;\n  float pitch;\n  char onground;\n};\n\nclass PacketHandler\n{\npublic:\n  void init();\n\n  // Information of all the packets\n  // around 4*2kB of memory\n  // 4 gamestates with max 256 packets each\n  Packets packets[4][256];\n\n  // The packet functions\n  static int keep_alive(User* user);\n  static int login_request(User* user);\n  static int handshake(User* user);\n  static int chat_message(User* user);\n  static int player(User* user);\n  static int player_position(User* user);\n  static int player_look(User* user);\n  static int player_position_and_look(User* user);\n  static int player_digging(User* user);\n  static int player_block_placement(User* user);\n  static int held_item_change(User* user);\n  static int animation(User* user);\n  static int pickup_spawn(User* user);\n  static int use_entity(User* user);\n  static int client_status(User* user);\n  static int update_sign(User* user);\n  static int confirm_transaction(User* user);\n  static int tab_complete(User* user);\n  static int encryption_response(User* user);\n  static int plugin_message(User* user);\n\n  static int client_settings(User* user);\n\n  static int creative_inventory(User* user);\n  static int player_abilities(User* user);\n\n  static int click_window(User* user);\n  static int close_window(User* user);\n  static int destroy_entity(User* user);\n\n  static int entity_action(User* user);\n\n  static int unhandledPacket(User* user);\n\n  static int ping(User* user);\n  static int server_list_ping(User* user);\n\n\n  static int block_change(User* user);\n\n};\n\n#endif\n"
  },
  {
    "path": "src/permissions.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _PERMISSIONS_H\n#define _PERMISSIONS_H\n\n\n// Bitmask definitions\n#define PERM_CUSTOM 1\n#define PERM_GUEST  (1 << 1)\n#define PERM_MEMBER (1 << 2)\n#define PERM_OP     (1 << 3)\n#define PERM_ADMIN  (1 << 4)\n\n// Permission check macros\n#define IS_CUSTOM(p) (p & PERM_GUEST)\n#define IS_GUEST(p)  (p & PERM_GUEST)\n#define IS_MEMBER(p) (p & PERM_MEMBER)\n#define IS_OP(p)     (p & PERM_OP)\n#define IS_ADMIN(p)  (p & PERM_ADMIN)\n\n// Setter macros for built-in permissions\n#define SET_GUEST(p)                            \\\n  p = (IS_CUSTOM(p) | PERM_MEMBER)\n\n#define SET_MEMBER(p)                           \\\n  p = (IS_CUSTOM(p) | PERM_GUEST | PERM_MEMBER)\n\n#define SET_OP(p)                                         \\\n  p = (IS_CUSTOM(p) | PERM_GUEST | PERM_MEMBER | PERM_OP)\n\n#define SET_ADMIN(p)                                                    \\\n  p = (IS_CUSTOM(p) | PERM_GUEST | PERM_MEMBER | PERM_OP | PERM_ADMIN)\n\n\n#endif /* _PERMISSIONS_H */\n"
  },
  {
    "path": "src/physics.cpp",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <math.h>\n\n#include \"physics.h\"\n#include \"logger.h\"\n#include \"constants.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"protocol.h\"\n#include \"vec.h\"\n\nnamespace\n{\n\ninline bool isWaterBlock(int id)\n{\n  return ((id == BLOCK_WATER) || (id == BLOCK_STATIONARY_WATER));\n}\n\ninline bool isLavaBlock(int id)\n{\n  return ((id == BLOCK_LAVA) || (id == BLOCK_STATIONARY_LAVA));\n}\n\ninline bool isLiquidBlock(int id)\n{\n  return ((id == BLOCK_LAVA) || (id == BLOCK_STATIONARY_LAVA) || (id == BLOCK_WATER) || (id == BLOCK_STATIONARY_WATER));\n}\n\ninline bool mayFallThrough(int id)\n{\n  return ((id == BLOCK_AIR) || (id == BLOCK_WATER) || (id == BLOCK_STATIONARY_WATER) || (id == BLOCK_SNOW));\n}\n\n}\n\nenum\n{\n  FLAT_NS = 0,\n  FLAT_EW,\n  ASCEND_W,\n  ASCEND_E,\n  ASCEND_S,\n  ASCEND_N,\n  CORNER_SE,\n  CORNER_SW,\n  CORNER_NW,\n  CORNER_NE\n};\n\n//Minecart physics loop\nbool Physics::updateMinecart()\n{\n  std::vector<MinecartData> &minecarts = map->minecarts;\n  uint32_t listSize = minecarts.size();\n\n  for (uint32_t simIt = 0; simIt < listSize; simIt++)\n  {\n    //Check if the cart is suppose to move\n    if(minecarts[simIt].speed.x() != 0 ||\n       minecarts[simIt].speed.y() != 0 ||\n       minecarts[simIt].speed.z() != 0)\n    {      \n      uint64_t timeNow = microTime();\n      double timeDiff = (timeNow-minecarts[simIt].timestamp*1.0)/1000000.0; //s\n      minecarts[simIt].timestamp = timeNow;\n\n      vec diff = vec(int8_t(float(minecarts[simIt].speed.x())*(timeDiff)),\n                     int8_t(float(minecarts[simIt].speed.y())*(timeDiff)),\n                     int8_t(float(minecarts[simIt].speed.z())*(timeDiff)) );\n      minecarts[simIt].pos = vec(minecarts[simIt].pos.x()+diff.x(),\n                                 minecarts[simIt].pos.y()+diff.y(),\n                                 minecarts[simIt].pos.z()+diff.z());\n\n\n\n      vec blockPos = vec((int)(minecarts[simIt].pos.x()/32),\n                          (int)(minecarts[simIt].pos.y()/32),\n                          (int)(minecarts[simIt].pos.z()/32)); \n      uint8_t block, meta;\n      map->getBlock(blockPos.x(),\n                                         blockPos.y(),\n                                         blockPos.z(),\n                                         &block, &meta);\n      bool changed = false;\n      if(block == BLOCK_AIR)\n      {\n        minecarts[simIt].pos.y() -= 32;\n        changed = true;\n      }\n      else if((minecarts[simIt].lastBlock.x() != blockPos.x() ||\n               minecarts[simIt].lastBlock.y() != blockPos.y() ||\n               minecarts[simIt].lastBlock.z() != blockPos.z()) &&\n              block == BLOCK_MINECART_TRACKS)\n      {\n        minecarts[simIt].lastBlock = blockPos;\n        if((meta == FLAT_NS && minecarts[simIt].speed.x() != 0)\n           || (meta == FLAT_EW && minecarts[simIt].speed.z() != 0))\n        {\n\n        }\n        else\n        {\n          //z = north\n          //-x = east\n\n          //Going west\n          if(minecarts[simIt].speed.x() > 0 && meta == CORNER_NW)\n          {\n            minecarts[simIt].speed.z() = -minecarts[simIt].speed.x();\n            minecarts[simIt].speed.x() = 0;\n            changed = true;\n          }\n          //Going west\n          else if(minecarts[simIt].speed.x() > 0 && meta == CORNER_SW)\n          {\n            minecarts[simIt].speed.z() = minecarts[simIt].speed.x();\n            minecarts[simIt].speed.x() = 0;\n            changed = true;\n          }\n          //Going east\n          else if(minecarts[simIt].speed.x() < 0 && meta == CORNER_NE)\n          {\n            minecarts[simIt].speed.z() = minecarts[simIt].speed.x();\n            minecarts[simIt].speed.x() = 0;\n            changed = true;\n          }\n          //Going east\n          else if(minecarts[simIt].speed.x() < 0 && meta == CORNER_SE)\n          {\n            minecarts[simIt].speed.z() = -minecarts[simIt].speed.x();\n            minecarts[simIt].speed.x() = 0;\n            changed = true;\n          }\n          //Going north\n          else if(minecarts[simIt].speed.z() > 0 && meta == CORNER_NW)\n          {\n            minecarts[simIt].speed.x() = -minecarts[simIt].speed.z();\n            minecarts[simIt].speed.z() = 0;\n            changed = true;\n          }\n          //Going north\n          else if(minecarts[simIt].speed.z() > 0 && meta == CORNER_NE)\n          {\n            minecarts[simIt].speed.x() = minecarts[simIt].speed.z();\n            minecarts[simIt].speed.z() = 0;\n            changed = true;            \n          }\n          //Going south\n          else if(minecarts[simIt].speed.z() < 0 && meta == CORNER_SE)\n          {\n            minecarts[simIt].speed.x() = -minecarts[simIt].speed.z();\n            minecarts[simIt].speed.z() = 0;\n            changed = true;            \n          }\n          //Going south\n          else if(minecarts[simIt].speed.z() < 0 && meta == CORNER_SW)\n          {\n            minecarts[simIt].speed.x() = minecarts[simIt].speed.z();\n            minecarts[simIt].speed.z() = 0;\n            changed = true;            \n          }\n        }\n      }\n      else\n      {\n        //minecarts[simIt].pos.y() += 32;\n        //changed = true;\n      }\n\n      //Signal clients about the new pos\n      Packet pkt;\n      if(changed)\n      {\n        minecarts[simIt].pos.x() = blockPos.x()*32;\n        minecarts[simIt].pos.y() = blockPos.y()*32;\n        minecarts[simIt].pos.z() = blockPos.z()*32;\n        pkt = Protocol::entityTeleport(minecarts[simIt].EID,\n                                       (minecarts[simIt].pos.x()+16.0)/32.0,\n                                       (minecarts[simIt].pos.y()+16.0)/32.0,\n                                       (minecarts[simIt].pos.z()+16.0)/32.0, 0, 0);\n      }\n      else\n      {\n        pkt = Protocol::entityRelativeMove(minecarts[simIt].EID,(int8_t)diff.x(),(int8_t)diff.y(),(int8_t)diff.z(), 1);\n\n      }\n      User::sendAll(pkt);\n    }\n  }\n  return true;\n}\n\n//Falling physics loop\nbool Physics::updateEntity()\n{\n\n  uint32_t listSize = entitySimList.size();\n  std::vector<uint32_t> toRem;\n  for (int32_t simIt = listSize-1; simIt >= 0; simIt--)\n  {\n    simulationEntity& f = entitySimList[simIt];\n\n    double timeInSec = (microTime()-f.startTime)/1000000.0;\n    double lasttimeInSec = (f.lastTime-f.startTime)/1000000.0;\n    f.lastTime = microTime();\n    f.ticks++;\n\n    const double gravity = -13.5;//9.81;\n\n    //Calculate offset when x and z velocity stays the same and y velocity has gravity to deal with\n    double offset_x = f.startPos.vel_x*timeInSec;\n    double offset_z = f.startPos.vel_z*timeInSec;\n    double offset_y = 0.5*gravity*timeInSec*timeInSec+f.startPos.vel_y*timeInSec;\n    entity_position newPos;\n    newPos.x = offset_x+f.startPos.x;\n    newPos.z = offset_z+f.startPos.z;\n    newPos.y = offset_y+f.startPos.y;\n    entity_position diffPos;\n    diffPos.x = newPos.x-f.pos.x;\n    diffPos.z = newPos.z-f.pos.z;\n    diffPos.y = newPos.y-f.pos.y;\n\n    //Loop all blocks between current point and last point. Just simple linear interpolation\n    for(double i = 0; i < 1.0; i+= 1.0/sqrt(diffPos.x*diffPos.x+diffPos.y*diffPos.y+diffPos.z*diffPos.z))\n    {\n      //Check for the block\n      uint8_t block,meta;\n      map->getBlock((int)(f.pos.x+diffPos.x*i-0.5),(int)(f.pos.y+diffPos.y*i),(int)(f.pos.z+diffPos.z*i-0.5),&block, &meta);\n\n      //When hitting _something_, turn it to glass and destroy the entity\n      if(block != BLOCK_AIR)\n      {\n        map->sendBlockChange((int)(f.pos.x+diffPos.x*i-0.5), (int)(f.pos.y+diffPos.y*i), (int)(f.pos.z+diffPos.z*i-0.5), BLOCK_GLASS, 0);\n        //Add to \"to-remove\" list\n        toRem.push_back(f.EID);\n        break;\n      }\n    }\n\n\n    f.pos.x = newPos.x;\n    f.pos.z = newPos.z;\n    f.pos.y = newPos.y;\n    f.pos.vel_y = gravity*timeInSec+f.startPos.vel_y;\n    /*\n    Packet pkt = Protocol::entityVelocity(f.EID,(int16_t)(f.pos.vel_x*8000.0/20),\n                                                (int16_t)(f.pos.vel_y*8000.0/20),\n                                                (int16_t)(f.pos.vel_z*8000.0/20));  \n    pkt << Protocol::entityTeleport(f.EID, f.pos.x, f.pos.y, f.pos.z,0,0);\n                                                \n    User::sendAll(pkt);\n    */\n  }\n  for(uint32_t i = 0; i < toRem.size(); i++)\n  {\n    for (uint32_t simIt = entitySimList.size()-1; simIt >= 0; simIt--)\n    {\n      if(entitySimList[simIt].EID == toRem[i])\n      {\n        Packet pkt = Protocol::destroyEntity(toRem[i]);  \n        User::sendAll(pkt);\n        entitySimList.erase(entitySimList.begin()+simIt);\n        break;\n      }\n    }\n  }\n  return true;\n}\n\n//Falling physics loop\nbool Physics::updateFall()\n{\n\n  uint32_t listSize = fallSimList.size();\n\n  for (int32_t simIt = listSize-1; simIt >= 0; simIt--)\n  {\n    Falling& f = fallSimList[simIt];\n\n    double timeInSec = (microTime()-f.startTime)/1000000.0;\n    f.ticks++;\n\n    const double gravity = 9.81;\n    double offset = 0.5*gravity*timeInSec*timeInSec;\n    int blockOffset = f.pos.y() - f.lastY;\n    if(blockOffset != (int)offset) ///  not necessary, doesn't optimize much\n    {\n      int yStart = f.pos.y();\n      int x = f.pos.x(); int z = f.pos.z();\n\n      int ypos = f.lastY;\n\n      f.lastY = yStart-(int)offset;\n      for(; ypos >= f.lastY;ypos--)\n      {\n        uint8_t block, meta;\n        map->getBlock(x,ypos,z, &block, &meta);\n        switch (block)\n        {\n        case BLOCK_AIR:\n        case BLOCK_WATER:\n        case BLOCK_STATIONARY_WATER:\n        case BLOCK_LAVA:\n        case BLOCK_STATIONARY_LAVA:\n        case BLOCK_SNOW:\n          break;\n          //If we hit ground\n        default:\n          {\n            map->setBlock(x, ++ypos, z, f.block, 0);\n            map->sendBlockChange(x, ypos, z, f.block, 0);\n            \n            //Despawn entity\n            Packet pkt = Protocol::destroyEntity(f.EID);\n            const int chunk_x = blockToChunk(x);\n            const int chunk_z = blockToChunk(z);\n            const ChunkMap::const_iterator it = map->chunks.find(Coords(chunk_x, chunk_z));\n            if (it != map->chunks.end())\n            {               \n              it->second->sendPacket(pkt);\n            }\n            //Erase from the simulation list\n            fallSimList.erase(fallSimList.begin()+simIt);\n            goto breakout;\n          }\n        }\n      }\n    }\nbreakout:\n    continue;\n  }\n  return true;\n}\n\n// Physics loop\nbool Physics::update()\n{\n  updateFall();\n  updateMinecart();\n  updateEntity();\n  if (!enabled)\n  {\n    return true;\n  }\n\n  // Check if needs to be updated\n  if (simList.empty())\n  {\n    return true;\n  }\n\n  std::vector<vec> toAdd;\n  std::vector<vec> toRem;\n  std::set<vec> changed;\n\n  clock_t starttime = clock();\n\n  LOG(INFO, \"Physics\", \"Simulating \" + dtos(simList.size()) + \" items!\");\n\n  uint32_t listSize = simList.size();\n\n  for (uint32_t simIt = 0; simIt < listSize; simIt++)\n  {\n    vec pos = simList[simIt].blocks[0].pos;\n    // Blocks\n    uint8_t block, meta;\n    map->getBlock(pos, &block, &meta);\n    simList[simIt].blocks[0].id   = block;\n    simList[simIt].blocks[0].meta = meta;\n\n    bool used = false;\n    for (int i = 0; i < 5; i++)\n    {\n      vec local(pos);\n      bool falling = false;\n      switch (i)\n      {\n      case 0:\n        local += vec(0, -1, 0); // First tries to go down\n        falling = true;\n        break;\n      case 1:\n        local += vec(1, 0, 0); // Might be bad to have the 4 cardinal dir'\n        // so predictable\n        break;\n      case 2:\n        local += vec(-1, 0, 0);\n        break;\n      case 3:\n        local += vec(0, 0, 1);\n        break;\n      case 4:\n        local += vec(0, 0, -1);\n        break;\n      case 5:\n        //        local += vec(0,1,0); // Going UP\n        break;\n      }\n      uint8_t newblock, newmeta;\n      map->getBlock(pos, &block, &meta);\n      map->getBlock(local, &newblock, &newmeta);\n      if (!isLiquidBlock(block))\n      {\n        toRem.push_back(pos);\n        break;\n      }\n      if ((isWaterBlock(newblock) && isWaterBlock(block)) // New or old block is water\n          || (isLavaBlock(newblock) && isLavaBlock(block)) // New or ols block is lava\n          || (isLiquidBlock(block) && mayFallThrough(newblock)))\n      {\n        // Falling non-liquid block\n        if (falling && !isLiquidBlock(newblock))\n        {\n          // Move block down one and replace old position with air\n          map->setBlock(local, block, meta);\n          changed.insert(local);\n          map->setBlock(pos, BLOCK_AIR, 0);\n\n          // For blockchange packet\n          changed.insert(pos);\n\n          // Remove old position from simulation\n          toRem.push_back(pos);\n          // Add new position of the block to the simulation\n          toAdd.push_back(local);\n          used = true;\n          continue;\n        }\n        if (falling && isLiquidBlock(newblock))\n        {\n          int top = 8 - meta;\n          int bot = 8 - newmeta;\n          int volume = top + bot;\n          if (volume > 8)\n          {\n            top = volume - 8;\n            bot = 8;\n          }\n          else\n          {\n            top = 0;\n            bot = volume;\n          }\n          int a_meta = 8 - top;\n          int a_newmeta = 8 - bot;\n          toAdd.push_back(local);\n          if (a_meta == meta && a_newmeta == newmeta)\n          {\n            toRem.push_back(pos);\n            toRem.push_back(local);\n            continue;\n          }\n          if ((isWaterBlock(block) && a_meta < 8) || (isLavaBlock(block) && a_meta < 4))\n          {\n            map->setBlock(pos, block, a_meta);\n\n            changed.insert(pos);\n          }\n          else\n          {\n            map->setBlock(pos, BLOCK_AIR, 0);\n            changed.insert(pos);\n          }\n          map->setBlock(local, block, a_newmeta);\n          used = true;\n          toAdd.push_back(local);\n          toAdd.push_back(pos);\n          changed.insert(pos);\n          continue;\n        }\n\n        // if the new block is not liquid\n        if (!isLiquidBlock(newblock))\n        {\n          // If we are not falling\n          if (!falling)\n          {\n            // At lowest liquid level, we cannot spread anymore\n            if ((isWaterBlock(block) && meta == 7) || (isLavaBlock(block) && meta >= 3))\n            {\n              toRem.push_back(pos);\n              break;\n            }\n          }\n          // We are spreading onto dry area.\n\n          // Reduce liquid level by one (0 = max level)\n          newmeta = ++meta;\n          map->setBlock(local, block, newmeta);\n          changed.insert(local);\n\n          // If we still have range to spread\n          if (meta < 8) {\n            // Add the new block back to the simulation for spreading\n            toAdd.push_back(local);\n          }\n          used = true;\n          continue;\n        }\n        if (meta < newmeta - 1 || (meta == newmeta && falling))\n        {\n          newmeta --;\n          map->setBlock(local, block, newmeta);\n          changed.insert(local);\n          meta ++;\n          if (meta < 8)\n          {\n            map->setBlock(pos, block, meta);\n            changed.insert(pos);\n          }\n          else\n          {\n            map->setBlock(pos, BLOCK_AIR, 0);\n            changed.insert(pos);\n            toRem.push_back(pos);\n          }\n          toAdd.push_back(local);\n          used = true;\n          continue;\n        }\n      }\n    }\n    if (!used)\n    {\n      toRem.push_back(pos);\n    }\n  }\n  for (int i = int(toRem.size()) - 1; i >= 0; i--)\n  {\n    removeSimulation(toRem[i]);\n  }\n  for (size_t i = 0; i < toAdd.size(); i++)\n  {\n    addSimulation(toAdd[i]);\n  }\n  map->sendMultiBlocks(changed);\n\n  //clock_t endtime = clock() - starttime;\n  //  LOG(INFO, \"Physics\", \"Exit simulation, took \" + dtos(endtime * 1000 / CLOCKS_PER_SEC) + \" ms, \" + dtos(simList.size()) + \" items left\");\n  return true;\n}\n\nbool Physics::addEntitySimulation(int16_t entity, entity_position pos, uint32_t EID, uint32_t UID)\n{\n  entitySimList.push_back(simulationEntity(entity,pos,EID,UID));\n  return true;\n}\n\nbool Physics::addFallSimulation(uint8_t block, vec pos, uint32_t EID)\n{\n  fallSimList.push_back(Falling(block,pos,EID));\n  return true;\n}\n\n// Add world simulation\nbool Physics::addSimulation(vec pos)\n{  \n  if (!enabled)\n  {\n    return true;\n  }\n\n  uint8_t block;\n  uint8_t meta;\n  map->getBlock(pos, &block, &meta);\n  SimBlock simulationBlock(block, pos, meta);\n\n  // Dont add duplicates\n  for (std::vector<Sim>::iterator simIt = simList.begin(); simIt != simList.end(); simIt++)\n  {\n    vec itpos = simIt->blocks[0].pos;\n    if (itpos.x() == pos.x() && itpos.y() == pos.y() && itpos.z() == pos.z())\n    {\n      return true;\n    }\n  }\n\n\n  // Simulating water\n  if (isWaterBlock(block))\n  {\n    simList.push_back(Sim(TYPE_WATER, simulationBlock));\n    return true;\n  }\n  // Simulating lava\n  else if (isLavaBlock(block))\n  {\n    simList.push_back(Sim(TYPE_LAVA, simulationBlock));\n    return true;\n  }\n\n  return false;\n}\n\nbool Physics::removeSimulation(vec pos)\n{\n  if (!enabled)\n  {\n    return true;\n  }\n\n  // Iterate each simulation\n  for (std::vector<Sim>::iterator simIt = simList.begin(); simIt != simList.end(); simIt++)\n  {\n    vec itpos = simIt->blocks[0].pos;\n    if (itpos.x() == pos.x() && itpos.y() == pos.y() && itpos.z() == pos.z())\n    {\n      simList.erase(simIt);\n      return true;\n    }\n  }\n  return false;\n}\n\n\nbool Physics::checkSurrounding(vec pos)\n{\n  if (!enabled)\n  {\n    return true;\n  }\n\n  uint8_t block;\n  uint8_t meta;\n\n  for (int i = 0; i < 6; i++)\n  {\n    vec local(pos);\n    switch (i)\n    {\n    case 0:\n      local += vec(0,  1,  0);\n      break;\n\n    case 1:\n      local += vec(1,  0,  0);\n      break;\n\n    case 2:\n      local += vec(-1,  0,  0);\n      break;\n\n    case 3:\n      local += vec(0,  0,  1);\n      break;\n\n    case 4:\n      local += vec(0,  0, -1);\n      break;\n\n    case 5:\n      local += vec(0, -1,  0);\n      break;\n    }\n\n    //Add liquid blocks to simulation if they are affected by breaking a block\n    if (map->getBlock(local, &block, &meta) &&\n        isLiquidBlock(block))\n    {\n      addSimulation(local);\n    }\n  }\n\n  return true;\n}\n"
  },
  {
    "path": "src/physics.h",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _PHYSICS_H\n#define _PHYSICS_H\n\n#include <stdint.h>\n#include <vector>\n#include \"vec.h\"\n#include \"tools.h\"\n\nstruct entity_position\n{\n  double x;\n  double y;\n  double z;\n  double vel_x;\n  double vel_y;\n  double vel_z;\n\n  entity_position() { x = y = z = vel_x = vel_y = vel_z = 0.0; };\n\n  entity_position(double _x, double _y, double _z)\n  {\n    x = _x; y = _y; z = _z;\n    vel_x = vel_y = vel_z = 0.0;\n  }\n\n  entity_position(double _x, double _y, double _z,double _vel_x, double _vel_y, double _vel_z)\n  {\n    x = _x; y = _y; z = _z;\n    vel_x = _vel_x;\n    vel_y = _vel_y;\n    vel_z = _vel_z;\n  }\n};\n\nclass Physics\n{\npublic:\n  Physics(Map* map)\n    :map(map) {}\n\n  bool enabled;\n  Map* map; // Which map are we affecting?\n\n  bool update();\n  bool updateFall();\n  bool updateEntity();\n  bool addSimulation(vec pos);\n  bool addFallSimulation(uint8_t block, vec pos, uint32_t EID);\n  bool addEntitySimulation(int16_t entity, entity_position pos, uint32_t EID, uint32_t UID);\n  bool removeSimulation(vec pos);\n  bool checkSurrounding(vec pos);\n  bool updateMinecart();\n\nprivate:\n  enum { TYPE_WATER, TYPE_LAVA } SimType;\n  enum { M0, M1, M2, M3, M4, M5, M6, M7, M_FALLING } SimState;\n\n  struct SimBlock\n  {\n    uint8_t id;\n    vec pos;\n    uint8_t meta;\n    SimBlock() {}\n    SimBlock(uint8_t id, vec pos, uint8_t meta)\n    {\n      this->id   = id;\n      this->pos  = pos;\n      this->meta = meta;\n    }\n  };\n\n  struct Sim\n  {\n    char type;\n    std::vector<SimBlock> blocks;\n    Sim(char stype, SimBlock initblock) : type(stype), blocks(1, initblock) {}\n  };\n\n  struct Falling\n  {\n    uint8_t block;\n    uint32_t EID;\n    vec pos;\n    int16_t lastY;\n    uint64_t startTime;\n    int ticks;\n    Falling() {};\n    Falling(uint8_t _block, vec _pos, uint32_t _EID)\n    {\n      block = _block;\n      pos = _pos;\n      lastY = pos.y();\n      EID = _EID;\n      ticks = 0;\n      startTime = microTime();\n    }\n  };\n\n  struct simulationEntity\n  {\n    int16_t entity;\n    uint32_t EID;\n    uint32_t UID;\n    entity_position startPos;\n    entity_position pos;\n    uint64_t startTime;\n    uint64_t lastTime;\n    int32_t ticks;\n    simulationEntity() {};\n    simulationEntity(int16_t _entity, entity_position _pos, uint32_t _EID, uint32_t _UID)\n    {\n      entity = _entity;\n      pos = _pos;\n      startPos = _pos;\n      EID = _EID;\n      UID = _UID;\n      ticks = 0;\n      startTime = microTime();\n      lastTime = startTime;\n    }\n  };\n\n  std::vector<Sim> simList;\n\n  std::vector<Falling> fallSimList;\n  std::vector<simulationEntity> entitySimList;\n};\n\n#endif\n"
  },
  {
    "path": "src/plugin.cpp",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"sys/stat.h\"\n\n#include \"mineserver.h\"\n\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <dlfcn.h>\n#endif\n\n#include \"constants.h\"\n#include \"logger.h\"\n\n#include \"plugin.h\"\n#include \"blocks/default.h\"\n#include \"blocks/falling.h\"\n#include \"blocks/torch.h\"\n#include \"blocks/plant.h\"\n#include \"blocks/snow.h\"\n#include \"blocks/liquid.h\"\n#include \"blocks/fire.h\"\n#include \"blocks/stair.h\"\n#include \"blocks/door.h\"\n#include \"blocks/sign.h\"\n#include \"blocks/tracks.h\"\n#include \"blocks/chest.h\"\n#include \"blocks/ladder.h\"\n#include \"blocks/leaves.h\"\n#include \"blocks/cake.h\"\n#include \"blocks/note.h\"\n#include \"blocks/blockfurnace.h\"\n#include \"blocks/workbench.h\"\n#include \"blocks/wood.h\"\n#include \"blocks/planks.h\"\n#include \"blocks/redstone.h\"\n#include \"blocks/redstoneutil.h\"\n#include \"blocks/pumpkin.h\"\n#include \"blocks/step.h\"\n#include \"blocks/tnt.h\"\n#include \"blocks/bed.h\"\n#include \"blocks/wool.h\"\n#include \"blocks/jackolantern.h\"\n#include \"blocks/ice.h\"\n#include \"blocks/blockbrewingstand.h\"\n\n#include \"items/food.h\"\n#include \"items/projectile.h\"\n\n#include \"inventory/inventoryPlayer.h\"\n#include \"inventory/inventoryWorkbench.h\"\n#include \"inventory/inventoryChest.h\"\n#include \"inventory/inventoryFurnace.h\"\n#include \"inventory/inventoryBrewingstand.h\"\n\nbool callbackReturnINTERNAL;\n// Create default hooks\nPlugin::Plugin()\n{\n  /*\n  setHook(\"Timer200\", new Hook0<bool>);\n  setHook(\"Timer1000\", new Hook0<bool>);\n  setHook(\"Timer10000\", new Hook0<bool>);\n  setHook(\"PlayerLoginPre\", new Hook2<bool, const char*, char***>);\n  setHook(\"PlayerLoginPost\", new Hook1<bool, const char*>);\n  setHook(\"PlayerNickPost\", new Hook2<bool, const char*, const char*>);\n  setHook(\"PlayerKickPost\", new Hook2<bool, const char*, const char*>);\n  setHook(\"PlayerQuitPost\", new Hook1<bool, const char*>);\n  setHook(\"PlayerChatPre\", new Hook3<bool, const char*, time_t, const char*>);\n  setHook(\"PlayerChatPost\", new Hook3<bool, const char*, time_t, const char*>);\n  setHook(\"PlayerArmSwing\", new Hook1<bool, const char*>);\n  setHook(\"PlayerDamagePre\", new Hook3<bool, const char*, const char*, int>);\n  setHook(\"PlayerDamagePost\", new Hook3<bool, const char*, const char*, int>);\n  setHook(\"PlayerDisconnect\", new Hook3<bool, const char*, uint32_t, uint16_t>);\n  setHook(\"PlayerDiggingStarted\", new Hook5<bool, const char*, int32_t, int16_t, int32_t, int8_t>);\n  setHook(\"PlayerDigging\", new Hook5<bool, const char*, int32_t, int16_t, int32_t, int8_t>);\n  setHook(\"PlayerDiggingStopped\", new Hook5<bool, const char*, int32_t, int16_t, int32_t, int8_t>);\n  setHook(\"PlayerBlockInteract\", new Hook4<bool, const char*, int32_t, int16_t, int32_t>);\n  setHook(\"BlockBreakPre\", new Hook4<bool, const char*, int32_t, int16_t, int32_t>);\n  setHook(\"BlockBreakPost\", new Hook4<bool, const char*, int32_t, int16_t, int32_t>);\n  setHook(\"BlockNeighbourBreak\", new Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>);\n  setHook(\"BlockPlacePre\", new Hook6<bool, const char*, int32_t, int16_t, int32_t, int16_t, int8_t>);\n  setHook(\"ItemRightClickPre\", new Hook6<bool, const char*, int32_t, int16_t, int32_t, int16_t, int8_t>);\n  setHook(\"BlockPlacePost\", new Hook6<bool, const char*, int32_t, int16_t, int32_t, int16_t, int8_t>);\n  setHook(\"BlockNeighbourPlace\", new Hook7<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t>);\n  setHook(\"BlockReplacePre\", new Hook6<bool, const char*, int32_t, int16_t, int32_t, int16_t, int16_t>);\n  setHook(\"BlockReplacePost\", new Hook6<bool, const char*, int32_t, int16_t, int32_t, int16_t, int16_t>);\n  setHook(\"BlockNeighbourReplace\", new Hook9<bool, const char*, int32_t, int16_t, int32_t, int32_t, int8_t, int32_t, int16_t, int16_t>);\n  setHook(\"LogPost\", new Hook3<bool, int, const char*, const char*>);\n  setHook(\"PlayerChatCommand\", new Hook4<bool, const char*, const char*, int, const char**>);\n  setHook(\"PlayerRespawn\", new Hook1<bool, const char*>);\n  setHook(\"gotAttacked\", new Hook2<bool, const char*, int32_t>);\n  setHook(\"interact\", new Hook2<bool, const char*, int32_t>);\n  */\n\n  init();\n}\n\n// Remove existing hooks\nPlugin::~Plugin()\n{\n  \n  for (HookMap::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it)\n  {\n    delete it->second;\n  }\n  \n  m_hooks.clear();\n}\n\nvoid Plugin::init()\n{\n  // Create Block objects\n  m_block_CBs.push_back(BlockBasicPtr(new BlockRedstone));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockRedstoneUtil));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockWood));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockPlanks));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockFalling));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockTorch));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockPlant));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockSnow));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockLiquid));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockFire));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockStair));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockChest));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockDoor));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockSign));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockTracks));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockLadder));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockLeaves));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockCake));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockNote));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockFurnace));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockWorkbench));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockPumpkin));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockStep));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockBed));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockWool));\n  m_block_CBs.push_back(BlockBasicPtr(new Blockjackolantern));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockIce));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockTNT));\n  m_block_CBs.push_back(BlockBasicPtr(new BlockBrewingStand));\n  // !! DEFAULT ALWAYS LAST, HANDLES EVERY BLOCK !!\n  m_block_CBs.push_back(BlockBasicPtr(new BlockDefault));\n\n  // ITEMS\n  m_item_CBs.push_back(ItemBasicPtr(new ItemFood));\n  m_item_CBs.push_back(ItemBasicPtr(new ItemProjectile));\n\n  // INVENTORIES\n  m_inventory_CBs.push_back(InventoryBasicPtr(new InventoryPlayer));\n  m_inventory_CBs.push_back(InventoryBasicPtr(new InventoryWorkbench));\n  m_inventory_CBs.push_back(InventoryBasicPtr(new InventoryChest));\n  m_inventory_CBs.push_back(InventoryBasicPtr(new InventoryFurnace));\n  m_inventory_CBs.push_back(InventoryBasicPtr(new InventoryBrewingstand));\n}\n\n\ntypedef void (*pfms)(mineserver_pointer_struct*);\ntypedef void (*pfv)();\n\nbool Plugin::loadPlugin(const std::string& name, const std::string& path, std::string alias)\n{\n  LIBRARY_HANDLE lhandle = NULL;\n  pfms fhandle = NULL;\n\n  if (name.empty()\n      || (name.find('/')  != std::string::npos)\n      || (name.find('\\\\') != std::string::npos))\n  {\n    LOG(INFO, \"Plugin\", \"Invalid name: \" + name);\n    return false;\n  }\n\n  if (alias.empty())\n  {\n    alias = name;\n  }\n\n  if (!path.empty())\n  {\n    std::string file;\n    file = path + '/' + name + LIBRARY_EXTENSION;\n\n    struct stat st;\n    int statr = stat(file.c_str(), &st);\n    if ((statr == 0) && !(st.st_mode & S_IFDIR))\n    {\n      LOG(INFO, \"Plugin\", \"Loading: \" + file);\n      lhandle = LIBRARY_LOAD(file.c_str());\n    }\n    else\n    {\n      LOG(INFO, \"Plugin\", \"Could not find: \" + file);\n      return false;\n    }\n  }\n  else\n  {\n    LOG(INFO, \"Plugin\", \"Loading built-in: \" + name);\n    lhandle = LIBRARY_SELF();\n  }\n\n  if (lhandle == NULL)\n  {\n    LOG(INFO, \"Plugin\", \"Could not load: \" + name);\n    LOG(INFO, \"Plugin\", LIBRARY_ERROR());\n    return false;\n  }\n\n  m_libraryHandles[alias] = lhandle;\n\n  *reinterpret_cast<void**>(&fhandle) = (void*)LIBRARY_SYMBOL(lhandle, (name + \"_init\").c_str());\n  if (fhandle == NULL)\n  {\n    LOG(INFO, \"Plugin\", \"Could not get init function handle!\");\n    unloadPlugin(alias);\n    return false;\n  }\n  fhandle(&plugin_api_pointers);\n\n  return true;\n}\n\nvoid Plugin::unloadPlugin(const std::string& name)\n{\n  LIBRARY_HANDLE lhandle = NULL;\n  pfv fhandle = NULL;\n\n  if (m_pluginVersions.find(name) != m_pluginVersions.end())\n  {\n    LOG(INFO, \"Plugin\", \"Unloading: \" + name);\n\n    if (m_libraryHandles[name] != NULL)\n    {\n      lhandle = m_libraryHandles[name];\n      m_libraryHandles.erase(name);\n    }\n    else\n    {\n      lhandle = LIBRARY_SELF();\n    }\n\n    *reinterpret_cast<void**>(&fhandle) = (void*)LIBRARY_SYMBOL(lhandle, (name + \"_shutdown\").c_str());\n    if (fhandle == NULL)\n    {\n      LOG(INFO, \"Plugin\", \"Could not get shutdown function handle!\");\n    }\n    else\n    {\n      LOG(INFO, \"Plugin\", \"Calling shutdown function for: \" + name);\n      fhandle();\n    }\n\n    LIBRARY_CLOSE(m_libraryHandles[name]);\n  }\n  else\n  {\n    LOG(WARNING, \"Plugin\", name + \" is not loaded!\");\n  }\n}\n"
  },
  {
    "path": "src/plugin.h",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _PLUGIN_H\n#define _PLUGIN_H\n\n#include <string>\n#include <vector>\n#include <ctime>\n#include <list>\n\n#include <memory>\n#include <unordered_map>\n\n//Fix Winsock2 error that occurs when Windows.h is included before it.\n#define _WINSOCKAPI_\n\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <dlfcn.h>\n#endif\n\n\n// A wild INCONSISTENCY appears!\n//\n//  --------------\n// | >FIGHT  PkMn |\n// |  ITEM   RUN  |\n//  --------------\n//\n// deoxxa uses MACRO ATTACK!\n//\n\n#ifdef WIN32\n#define LIBRARY_HANDLE HINSTANCE\n#define LIBRARY_LOAD(x) LoadLibraryA(x)\n#define LIBRARY_SELF() GetModuleHandle(NULL)\n#define LIBRARY_SYMBOL(x, y) GetProcAddress(x, y)\nstatic char *LIBRARY_ERROR(void)\n{\n  static char errbuf[513];\n  DWORD err = GetLastError();\n  if(!err)\n    return NULL;\n  FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, errbuf, 512, NULL);\n  SetLastError(0);\n  return errbuf;\n}\n#define LIBRARY_CLOSE(x) FreeLibrary(x)\n#define LIBRARY_EXTENSION \".dll\"\n#else\n#define LIBRARY_HANDLE void*\n#define LIBRARY_LOAD(x) dlopen(x, RTLD_LAZY)\n#define LIBRARY_SELF() dlopen(NULL, RTLD_LAZY)\n#define LIBRARY_SYMBOL(x, y) dlsym(x, y)\n#define LIBRARY_ERROR() dlerror()\n#define LIBRARY_CLOSE(x) dlclose(x)\n#define LIBRARY_EXTENSION \".so\"\n#endif\n\n#include \"blocks/basic.h\"\n#include \"items/itembasic.h\"\n#include \"inventory/inventorybasic.h\"\n\n//\n// It's SUPER EFFECTIVE!\n// Foe INCONSISTENCY fainted!\n// You got 374¥ for winning!\n\ntypedef std::shared_ptr<BlockBasic> BlockBasicPtr;\ntypedef std::shared_ptr<ItemBasic>  ItemBasicPtr;\ntypedef std::shared_ptr<InventoryBasic>  InventoryBasicPtr;\n\nextern bool callbackReturnINTERNAL;\ntypedef int(*funcPointer)(...);\n\n#define addCallback(name,func) if(ServerInstance->plugin()->getHook(name) == NULL) {ServerInstance->plugin()->setHook(name,new funcListType); } ServerInstance->plugin()->getHook(name)->push_back(func);\n#define runCallbackUntilTrue(name,...) { callbackReturnINTERNAL = false; funcListType *funcList = ServerInstance->plugin()->getHook(name);\\\n                                         if(funcList != NULL) for(funcListType::iterator i = funcList->begin(); i != funcList->end(); i++) { \\\n                                         if((*i)(__VA_ARGS__)) { callbackReturnINTERNAL = true; break; } } }\n#define runCallbackUntilFalse(name,...) { callbackReturnINTERNAL = false; funcListType *funcList = ServerInstance->plugin()->getHook(name);\\\n                                          if(funcList != NULL) for(funcListType::iterator i = funcList->begin(); i != funcList->end(); i++) { \\\n                                          if(!(*i)(__VA_ARGS__)) { callbackReturnINTERNAL = true; break; } } }\n#define runAllCallback(name,...)        {  funcListType *funcList = ServerInstance->plugin()->getHook(name);\\\n                                          if(funcList != NULL) for(funcListType::iterator i = funcList->begin(); i != funcList->end(); i++) { \\\n                                          (*i)(__VA_ARGS__); } }\n#define callbackReturnValue callbackReturnINTERNAL\n\ntypedef std::list<funcPointer> funcListType;\n\nclass Plugin\n{\npublic:\n  \n  typedef std::unordered_map<std::string, funcListType* > HookMap;\n  typedef std::unordered_map<std::string, LIBRARY_HANDLE> LibHandleMap;\n  typedef std::unordered_map<std::string, void*> PointerMap;\n  typedef std::unordered_map<std::string, float> VersionMap;\n\n  typedef std::vector<BlockBasicPtr> BlockCBs;\n  typedef std::vector<ItemBasicPtr>  ItemCBs;\n  typedef std::vector<InventoryBasicPtr>  InventoryCBs;\n\n   Plugin();\n  ~Plugin();\n\n  // Hook registry stuff\n  inline bool  hasHook(const HookMap::key_type& name) const { return m_hooks.count(name) > 0; }\n  inline HookMap::mapped_type getHook(const HookMap::key_type& name)\n  {\n    HookMap::iterator hook = m_hooks.find(name);\n    return (hook == m_hooks.end()) ? NULL : (hook->second);\n  }  \n  inline void  setHook(const HookMap::key_type& name, HookMap::mapped_type hook) { m_hooks[name] = hook; }\n  inline void  remHook(const HookMap::key_type& name) { m_hooks.erase(name); /* erases 0 or 1 elements */ }\n\n  // Load/Unload plugins\n  bool loadPlugin(const std::string& name, const std::string& path = \"\", std::string alias = \"\");\n  void unloadPlugin(const std::string& name);\n\n  // Plugin version registry\n  inline bool  hasPluginVersion(const VersionMap::key_type& name) const { return m_pluginVersions.find(name) != m_pluginVersions.end(); }\n  inline float getPluginVersion(const VersionMap::key_type& name) const\n  {\n    VersionMap::const_iterator pluginVersion = m_pluginVersions.find(name);\n    return pluginVersion == m_pluginVersions.end() ? 0 : pluginVersion->second;\n  }\n  inline void  setPluginVersion(const VersionMap::key_type& name, VersionMap::mapped_type version) { m_pluginVersions[name] = version; }\n  inline void  remPluginVersion(const VersionMap::key_type& name) { m_pluginVersions.erase(name); }\n\n  // Pointer registry stuff\n  inline bool  hasPointer(const PointerMap::key_type& name) const { return m_pointers.find(name) != m_pointers.end(); }\n  inline void* getPointer(const PointerMap::key_type& name) const\n  {\n    PointerMap::const_iterator pointer = m_pointers.find(name);\n    return pointer == m_pointers.end() ? NULL : pointer->second;\n  }\n  inline void  setPointer(const PointerMap::key_type& name, PointerMap::mapped_type pointer) {m_pointers[name] = pointer; }\n  inline void  remPointer(const PointerMap::key_type& name) { m_pointers.erase(name); }\n\n  void init();\n\n  inline const BlockCBs & getBlockCB() const { return m_block_CBs; }\n\n  inline const ItemCBs  & getItemCB()  const { return m_item_CBs; }\n\n  inline const InventoryCBs  & getInventoryCB()  const { return m_inventory_CBs; }\n\nprivate:\n  HookMap      m_hooks;\n  LibHandleMap m_libraryHandles;\n  PointerMap   m_pointers;\n  VersionMap   m_pluginVersions;\n\n  BlockCBs     m_block_CBs;\n  ItemCBs      m_item_CBs;\n  InventoryCBs m_inventory_CBs;\n};\n\n#endif\n"
  },
  {
    "path": "src/plugin_api.cpp",
    "content": "/*\n  Copyright (c) 2011, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"sys/stat.h\"\n\n#include \"mineserver.h\"\n#include \"logger.h\"\n#include \"chat.h\"\n#include \"permissions.h\"\n#include \"protocol.h\"\n\n#include \"plugin.h\"\n#include \"config.h\"\n#include \"map.h\"\n#include \"mob.h\"\n#include \"random.h\"\n#include \"blocks/default.h\"\n#include \"blocks/falling.h\"\n#include \"blocks/torch.h\"\n#include \"blocks/plant.h\"\n#include \"blocks/snow.h\"\n#include \"blocks/liquid.h\"\n#include \"blocks/fire.h\"\n#include \"blocks/stair.h\"\n#include \"blocks/door.h\"\n#include \"blocks/sign.h\"\n#include \"blocks/tracks.h\"\n#include \"blocks/chest.h\"\n#include \"blocks/note.h\"\n#define MINESERVER\n#include \"plugin_api.h\"\n\nmineserver_pointer_struct plugin_api_pointers;\n\n// HELPER FUNCTIONS\nUser* userFromName(std::string user)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    // Don't send to his user if he is DND and the message is a chat message\n    if (((*it)->fd && (*it)->logged && user == (*it)->nick))\n    {\n      return *it;\n    }\n  }\n  return NULL;\n}\nUser* anyUserFromName(std::string user)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    // Don't send to his user if he is DND and the message is a chat message\n    if ((user == (*it)->nick))\n    {\n      return *it;\n    }\n  }\n  return NULL;\n}\n\n// PLUGIN_API FUNCTIONS\n\nbool plugin_hasPluginVersion(const char* name)\n{\n  return ServerInstance->plugin()->hasPluginVersion(std::string(name));\n}\n\nfloat plugin_getPluginVersion(const char* name)\n{\n  return ServerInstance->plugin()->getPluginVersion(std::string(name));\n}\n\nvoid plugin_setPluginVersion(const char* name, float version)\n{\n  ServerInstance->plugin()->setPluginVersion(std::string(name), version);\n}\n\nvoid plugin_remPluginVersion(const char* name)\n{\n  ServerInstance->plugin()->remPluginVersion(std::string(name));\n}\n\nbool plugin_hasPointer(const char* name)\n{\n  return ServerInstance->plugin()->hasPointer(std::string(name));\n}\n\nvoid* plugin_getPointer(const char* name)\n{\n  return ServerInstance->plugin()->getPointer(std::string(name));\n}\n\nvoid plugin_setPointer(const char* name, void* pointer)\n{\n  ServerInstance->plugin()->setPointer(std::string(name), pointer);\n}\n\nvoid plugin_remPointer(const char* name)\n{\n  ServerInstance->plugin()->remPointer(std::string(name));\n}\n\nbool plugin_hasHook(const char* hookID)\n{\n  return ServerInstance->plugin()->hasHook(hookID);\n}\n\n/*\nHook* plugin_getHook(const char* hookID)\n{\n  return ServerInstance->plugin()->getHook(hookID);\n}\n\nvoid plugin_setHook(const char* hookID, void* hook)\n{\n  ServerInstance->plugin()->setHook(hookID, hook);\n}\n*/\n\nvoid plugin_remHook(const char* hookID)\n{\n  ServerInstance->plugin()->remHook(hookID);\n}\n\nbool hook_hasCallback(const char* hookID, voidF function)\n{\n  funcListType *funcList = ServerInstance->plugin()->getHook(hookID);\n  for(funcListType::iterator i = funcList->begin(); i != funcList->end(); i++)\n  {\n    if((*i) == (funcPointer)function)\n    {\n      return true;\n    }\n  }\n  return false;\n}\n\nvoid hook_addCallback(const char* hookID, voidF function)\n{\n  addCallback(std::string(hookID), (funcPointer)function);\n}\n\nvoid hook_addIdentifiedCallback(const char* hookID, void* identifier, voidF function)\n{\n  //ServerInstance->plugin()->getHook(hookID)->addIdentifiedCallback(identifier, function);\n}\n\nvoid hook_remCallback(const char* hookID, voidF function)\n{\n  funcListType *funcList = ServerInstance->plugin()->getHook(hookID);\n  for(funcListType::iterator i = funcList->begin(); i != funcList->end(); i++)\n  {\n    if((*i) == (funcPointer)function)\n    {\n      funcList->erase(i);\n      break;\n    }\n  }\n}\n\nbool hook_doUntilTrue(const char* hookID, ...)\n{\n  bool result = false;\n  va_list argList;\n  va_start(argList, hookID);\n  runCallbackUntilTrue(hookID,argList);\n  result = callbackReturnValue;\n  va_end(argList);\n  return result;\n}\n\nbool hook_doUntilFalse(const char* hookID, ...)\n{\n  bool result = false;\n  va_list argList;\n  va_start(argList, hookID);  \n  runCallbackUntilFalse(hookID,argList);\n  result = callbackReturnValue;\n  va_end(argList);\n  return result;\n}\n\nvoid hook_doAll(const char* hookID, ...)\n{\n  va_list argList;\n  va_start(argList, hookID);\n  runAllCallback(hookID,argList);\n  va_end(argList);\n}\n\n// LOGGER WRAPPER FUNCTIONS\nvoid logger_log(int type, const char* source, const char* message)\n{\n  ServerInstance->logger()->log((LogType::LogType)type, std::string(source), std::string(message));\n}\n\n// CHAT WRAPPER FUNCTIONS\nbool chat_sendmsgTo(const char* user, const char* msg)\n{\n  const std::string userStr(user);\n\n  if (userStr == \"[Server]\")\n  {\n    LOG(INFO, \"Chat\", msg);\n    return true;\n  }\n\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    // Don't send to his user if he is DND and the message is a chat message\n    if ((*it)->fd && (*it)->logged && userStr == (*it)->nick)\n    {\n      (*it)->writePacket(Protocol::chatMsg(\"{\\\"text\\\": \\\"\"+json_esc(msg)+\"\\\"}\"));\n      return true;\n    }\n  }\n\n  return false;\n}\n\nbool chat_sendmsg(const char* msg)\n{\n  const std::string msgStr(msg);\n\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    // Don't send to his user if he is DND and the message is a chat message\n    if ((*it)->fd && (*it)->logged && !(*it)->dnd)\n    {\n      (*it)->writePacket(Protocol::chatMsg(\"{\\\"text\\\": \\\"\"+ json_esc(msg) + \"\\\"}\"));\n    }\n  }\n\n  return true;\n}\n\nbool chat_sendUserlist(const char* user)\n{\n  const std::string userStr(user);\n\n  User* userPtr = userFromName(userStr);\n\n  if (userPtr != NULL)\n  {\n    ServerInstance->chat()->sendUserlist(userPtr);\n    return true;\n  }\n\n  return false;\n}\n\nbool chat_handleMessage(const char* username, const char* message)\n{\n  if (strcmp(username, \"[Server]\") == 0)\n  {\n    User serverUser(-1, SERVER_CONSOLE_UID);\n    serverUser.changeNick(\"[Server]\");\n\n    ServerInstance->chat()->handleMsg(&serverUser, message);\n  }\n  else\n  {\n    User* user = userFromName(std::string(username));\n    if (user != NULL)\n    {\n      ServerInstance->chat()->handleMsg(user, message);\n    }\n  }\n  return false;\n}\n\n// MAP WRAPPER FUNCTIONS\nbool map_setTime(int timeValue)\n{\n  ServerInstance->map(0)->mapTime = timeValue;\n  Packet pkt;\n  pkt << Protocol::timeUpdate(ServerInstance->map(0)->mapTime);\n\n  if (!User::all().empty())\n  {\n    (*User::all().begin())->sendAll(pkt);\n  }\n  return true;\n}\n\nint map_getTime()\n{\n  return int(ServerInstance->map(0)->mapTime);\n}\n\nvoid map_createPickupSpawn(int x, int y, int z, int type, int count, int health, const char* user)\n{\n  User* tempUser = NULL;\n  if (user != NULL)\n  {\n    tempUser = userFromName(std::string(user));\n    ServerInstance->map(tempUser->pos.map)->createPickupSpawn(x, y, z, type, count, health, tempUser);\n\n  }\n  else\n  {\n    ServerInstance->map(0)->createPickupSpawn(x, y, z, type, count, health, NULL);\n  }\n}\n\nvoid map_getSpawn(int* x, int* y, int* z)\n{\n  *x = ServerInstance->map(0)->spawnPos.x();\n  *y = ServerInstance->map(0)->spawnPos.y();\n  *z = ServerInstance->map(0)->spawnPos.z();\n}\n\nvoid map_setSpawn(int x, int y, int z)\n{\n  ServerInstance->map(0)->spawnPos.x() = x;\n  ServerInstance->map(0)->spawnPos.y() = y;\n  ServerInstance->map(0)->spawnPos.z() = z;\n}\n\nbool map_getBlock(int x, int y, int z, unsigned char* type, unsigned char* meta)\n{\n  return ServerInstance->map(0)->getBlock(x, y, z, type, meta);\n}\n\nbool map_setBlock(int x, int y, int z, unsigned char type, unsigned char meta)\n{\n  ServerInstance->map(0)->sendBlockChange(x, y, z, type, meta);\n  return ServerInstance->map(0)->setBlock(x, y, z, type, meta);\n}\n\nbool map_getBlockW(int x, int y, int z, int w, unsigned char* type, unsigned char* meta)\n{\n  return ServerInstance->map(w)->getBlock(x, y, z, type, meta);\n}\n\nbool map_setBlockW(int x, int y, int z, int w, unsigned char type, unsigned char meta)\n{\n  ServerInstance->map(w)->sendBlockChange(x, y, z, type, meta);\n  return ServerInstance->map(w)->setBlock(x, y, z, type, meta);\n}\n\n\nvoid map_saveWholeMap(void)\n{\n  ServerInstance->saveAll();\n}\n\nunsigned char* map_getMapData_block(int x, int z)\n{\n  sChunk* chunk = ServerInstance->map(0)->getMapData(x, z);\n  if (chunk != NULL)\n  {\n    return chunk->blocks;\n  }\n  return NULL;\n}\nunsigned char* map_getMapData_meta(int x, int z)\n{\n  sChunk* chunk = ServerInstance->map(0)->getMapData(x, z);\n  if (chunk != NULL)\n  {\n    return chunk->data;\n  }\n  return NULL;\n}\nunsigned char* map_getMapData_skylight(int x, int z)\n{\n  sChunk* chunk = ServerInstance->map(0)->getMapData(x, z);\n  if (chunk != NULL)\n  {\n    return chunk->skylight;\n  }\n  return NULL;\n}\nunsigned char* map_getMapData_blocklight(int x, int z)\n{\n  sChunk* chunk = ServerInstance->map(0)->getMapData(x, z);\n  if (chunk != NULL)\n  {\n    return chunk->blocklight;\n  }\n  return NULL;\n}\n\n// USER WRAPPER FUNCTIONS\nbool user_toggleDND(const char* user)\n{\n  const std::string username(user);\n\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged && username == (*it)->nick)\n    {\n      (*it)->toggleDND();\n      return true;\n    }\n  }\n\n  return false;\n}\n\nbool user_getPosition(const char* user, double* x, double* y, double* z, float* yaw, float* pitch, double* stance)\n{\n  const std::string userStr(user);\n\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    //Is this the user?\n    if ((*it)->fd && (*it)->logged && userStr == (*it)->nick)\n    {\n      //For safety, check for NULL pointers!\n      if (x != NULL)  *x = (*it)->pos.x;\n      if (y != NULL)  *y = (*it)->pos.y;\n      if (z != NULL)  *z = (*it)->pos.z;\n      if (yaw != NULL)    *yaw    = (*it)->pos.yaw;\n      if (pitch != NULL)  *pitch  = (*it)->pos.pitch;\n      if (stance != NULL) *stance = (*it)->pos.stance;\n\n      return true;\n    }\n  }\n\n  return false;\n}\n\nbool user_getPositionW(const char* user, double* x, double* y, double* z, int* w, float* yaw, float* pitch, double* stance)\n{\n  const std::string userStr(user);\n\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    //Is this the user?\n    if ((*it)->fd && (*it)->logged && userStr == (*it)->nick)\n    {\n      //For safety, check for NULL pointers!\n      if (x != NULL)      *x = (*it)->pos.x;\n      if (y != NULL)      *y = (*it)->pos.y;\n      if (z != NULL)      *z = (*it)->pos.z;\n      if (yaw != NULL)    *yaw = (*it)->pos.yaw;\n      if (pitch != NULL)  *pitch = (*it)->pos.pitch;\n      if (stance != NULL) *stance = (*it)->pos.stance;\n      if (w != NULL)      *w = (*it)->pos.map;\n\n      return true;\n    }\n  }\n  return false;\n}\n\nbool user_teleport(const char* user, double x, double y, double z)\n{\n  User* tempUser = userFromName(std::string(user));\n  if (tempUser != NULL)\n  {\n    tempUser->teleport(x, y, z);\n    return true;\n  }\n  return false;\n}\n\nbool user_teleportMap(const char* user, double x, double y, double z, size_t map)\n{\n  if (map >= ServerInstance->mapCount())\n  {\n    return false;\n  }\n  User* tempUser = userFromName(std::string(user));\n  if (tempUser != NULL && map != tempUser->pos.map)\n  {\n    tempUser->teleport(x, y, z, map);\n    return true;\n  }\n  return false;\n}\n\nbool user_sethealth(const char* user, int userHealth)\n{\n  User* tempUser = userFromName(std::string(user));\n  if (tempUser != NULL)\n  {\n    tempUser->sethealth(userHealth);\n    return true;\n  }\n  return false;\n}\n\nint user_gethealth(const char* user)\n{\n  User* tempUser = userFromName(std::string(user));\n  if (tempUser != NULL)\n  {\n    return tempUser->health;\n  }\n  return 0;\n}\n\nint user_getCount()\n{\n  return ServerInstance->users().size();\n}\n\nconst char* user_getUserNumbered(int c)\n{\n  std::set<User*>::const_iterator it = ServerInstance->users().begin();\n  std::advance(it, c);\n  return (*it)->nick.c_str();\n}\n\nbool user_getItemInHand(const char* user, int* type, int* meta, int* quant)\n{\n  User* tempUser = userFromName(std::string(user));\n  if (tempUser != NULL)\n  {\n    Item item = tempUser->inv[tempUser->curItem + 36];\n    if (type != NULL)\n    {\n      *type = item.getType();\n    }\n    if (meta != NULL)\n    {\n      *meta = item.getHealth();\n    }\n    if (quant != NULL)\n    {\n      *quant = item.getCount();\n    }\n    return true;\n  }\n  return false;\n}\n\nbool user_setItemInHand(const char* user, int type, int meta, int quant)\n{\n  if (quant > 64)\n  {\n    quant = 64;\n  }\n  if (quant < 0)\n  {\n    quant = 0;\n  }\n  User* tempUser = userFromName(std::string(user));\n  if (tempUser != NULL)\n  {\n    Item* item = &tempUser->inv[tempUser->curItem + 36];\n    item->setHealth(meta);\n    item->setCount(quant);\n    if (item->getType() != -1)\n    {\n      item->setType(type);\n    }\n    return true;\n  }\n  return false;\n}\n\nbool user_addItem(const char* user, int item, int count, int health)\n{\n  int total = count;\n  User* tempuser = userFromName(std::string(user));\n  if (tempuser != NULL)\n  {\n    bool checkingTaskbar = true;\n    for (uint8_t i = 36 - 9; i < 36 - 9 || checkingTaskbar; i++)\n    {\n      if (i == 36)\n      {\n        checkingTaskbar = false;\n        i = 0;\n      }\n      Item* slot = &tempuser->inv[i + 9];\n      if (item == slot->getType() && health == slot->getHealth())\n      {\n        if (slot->getCount() < 64)\n        {\n          int a = 64 - slot->getCount();\n          if (a < total)\n          {\n            total -= a;\n            slot->setCount(64);\n          }\n          else\n          {\n            slot->decCount(-total);\n            total = 0;\n          }\n        }\n      }\n      else if (slot->getType() == -1)\n      {\n        slot->setType(item);\n        slot->setHealth(health);\n        if (total < 65)\n        {\n          slot->setCount(total);\n          total = 0;\n        }\n        else\n        {\n          slot->setCount(64);\n          total -= 64;\n        }\n      }\n      if (total == 0)\n      {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nbool user_hasItem(const char* user, int item, int count, int health)\n{\n  User* tempuser = userFromName(std::string(user));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  bool checkingTaskbar = true;\n  int total = 0;\n\n  for (uint8_t i = 36 - 9; i < 36 - 9 || checkingTaskbar; i++)\n  {\n    //First, the \"task bar\"\n    if (i == 36)\n    {\n      checkingTaskbar = false;\n      i = 0;\n    }\n    Item* slot = &tempuser->inv[i + 9];\n    if (item == slot->getType() && (health == slot->getHealth() || health == -1))\n    {\n      total += slot->getCount();\n      if (total >= count)\n      {\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\nbool user_delItem(const char* user, int item, int count, int health)\n{\n  User* tempuser = userFromName(std::string(user));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  bool checkingTaskbar = true;\n  int total = count;\n\n  for (uint8_t i = 36 - 9; i < 36 - 9 || checkingTaskbar; i++)\n  {\n    //First, the \"task bar\"\n    if (i == 36)\n    {\n      checkingTaskbar = false;\n      i = 0;\n    }\n    Item* slot = &tempuser->inv[i + 9];\n    if (item == slot->getType() && (health == slot->getHealth() || health == -1))\n    {\n      if (slot->getCount() > total)\n      {\n        int a = slot->getCount();\n        slot->decCount(total);\n        total -= a;\n        return true;\n      }\n      else\n      {\n        total -= slot->getCount();\n        slot->setType(-1);\n      }\n    }\n  }\n  return false;\n}\n\nbool user_kick(const char* user)\n{\n  User* tempuser = userFromName(std::string(user));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  tempuser->kick(\"You have been kicked!\"); // Need to allow other languages.\n  return true;\n}\n\nbool user_getItemAt(const char* user, int slotn, int* type, int* meta, int* quant)\n{\n  User* tempuser = userFromName(std::string(user));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  Item* slot = &tempuser->inv[slotn];\n  if (type != NULL)\n  {\n    *type = slot->getType();\n  }\n  if (meta != NULL)\n  {\n    *meta = slot->getHealth();\n  }\n  if (quant != NULL)\n  {\n    *quant = slot->getCount();\n  }\n  return true;\n}\n\nbool user_setItemAt(const char* user, int slotn, int type, int meta, int quant)\n{\n  User* tempuser = userFromName(std::string(user));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  Item* slot = &tempuser->inv[slotn];\n  slot->setType(type);\n  if (slot->getType() != -1)\n  {\n    slot->setHealth(meta);\n    slot->setCount(quant);\n  }\n  return true;\n}\nbool user_setGameMode(const char* user, int gamemode)\n{\n    User* tempuser = userFromName(std::string(user));\n    if (tempuser == NULL)\n        return false;\n\n    if(gamemode != 0 && gamemode != 1)\n        return false;\n\n    return tempuser->setGameMode((User::GameMode)gamemode);\n}\n\n// CONFIG WRAPPER FUNCTIONS\nbool config_has(const char* name)\n{\n  return ServerInstance->config()->has(std::string(name));\n}\n\nint config_iData(const char* name)\n{\n  return ServerInstance->config()->iData(std::string(name));\n}\n\nint64_t config_lData(const char* name)\n{\n  return ServerInstance->config()->lData(std::string(name));\n}\n\nfloat config_fData(const char* name)\n{\n  return ServerInstance->config()->fData(std::string(name));\n}\n\ndouble config_dData(const char* name)\n{\n  return ServerInstance->config()->dData(std::string(name));\n}\n\nconst char* config_sData(const char* name)\n{\n  return ServerInstance->config()->sData(std::string(name)).c_str();\n}\n\nbool config_bData(const char* name)\n{\n  return ServerInstance->config()->bData(std::string(name));\n}\n\nint mob_createMob(int type)\n{\n  MobPtr m = ServerInstance->mobs()->createMob();\n  m->type = type;\n  return ServerInstance->mobs()->getAll().size() - 1;\n}\n\nint mob_createSpawnMob(int type)\n{\n  MobPtr m = ServerInstance->mobs()->createMob();\n  m->type = type;\n  m->spawnToAll();\n  m->teleportToAll();\n  return ServerInstance->mobs()->getAll().size() - 1;\n}\n\nvoid mob_spawnMob(int uid)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  m->spawnToAll();\n}\n\nvoid mob_despawnMob(int uid)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  m->deSpawnToAll();\n}\n\nvoid mob_moveMob(int uid, double x, double y, double z)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  m->moveTo(x, y, z, -1);\n}\n\nvoid mob_moveMobW(int uid, double x, double y, double z, int map)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  m->moveTo(x, y, z, map);\n}\n\nint mob_getMobID(int uid)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  return m->UID;\n}\n\nint mob_getHealth(int uid)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  return m->health;\n}\n\nvoid mob_setHealth(int uid, int mobHealth)\n{\n  ServerInstance->mobs()->getMobByID(uid)->sethealth(mobHealth);\n}\n\nvoid mob_moveAnimal(const char*, size_t mobID)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID((int)mobID);\n  m->moveAnimal();\n}\n\nvoid mob_animateMob(const char*, size_t mobID, int animID) \n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(mobID);\n  m->animateMob(animID);\n}\n\nvoid mob_animateDamage(const char*, size_t mobID, int animID) \n{\n MobPtr m = ServerInstance->mobs()->getMobByID(mobID);\n m->animateDamage(animID);\n}\n\nint mob_getType(size_t uid)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  return m->type;\n}\n\nbool mob_getLook(int uid, double* rot, double* pitch, double* head_yaw)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  if (m != NULL)\n  {\n    if (rot != NULL)\n    {\n      *rot = (double)((m->yaw * 1.0) * 360.0 / 256.0);\n    }\n    if (pitch != NULL)\n    {\n      *pitch = (double)((m->pitch * 1.0) * 360.0 / 256.0);\n    }\n    if (head_yaw != NULL)\n    {\n      *head_yaw = (double)((m->head_yaw * 1.0) * 360.0 / 256.0);\n    }\n    return true;\n  }\n  return false;\n}\n\nbool mob_setLook(int uid, double rot, double pitch, double head_yaw)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  if (m != NULL)\n  {\n    m->look((int16_t)rot, (int16_t)pitch);\n    m->headLook((int16_t)head_yaw);\n    return true;\n  }\n  return false;\n}\n\n\nbool mob_getMobPositionW(int uid, double* x, double* y, double* z, int* w)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  if (m != NULL)\n  {\n    if (w != NULL)\n    {\n      *w = m->map;\n    }\n    if (x != NULL)\n    {\n      *x = m->x;\n    }\n    if (y != NULL)\n    {\n      *y = m->y;\n    }\n    if (z != NULL)\n    {\n      *z = m->z;\n    }\n    return true;\n  }\n  return false;\n}\n\nbool mob_setByteMetadata(int uid, int8_t idx, int8_t val)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  if (!m) return false;\n  m->metadata.set(new MetaDataElemByte(idx, val));\n  return true;\n}\n\nbool mob_updateMetadata(int uid)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  if (!m) return false;\n  m->updateMetadata();\n  return true;\n}\n\nint8_t mob_getByteMetadata(int uid, int idx)\n{\n  MobPtr m = ServerInstance->mobs()->getMobByID(uid);\n  if (!m) return false;\n  MetaDataElemPtr x = m->metadata.get(idx);\n  MetaDataElemByte* data = dynamic_cast<MetaDataElemByte*>(x.get());\n  if (!data) return 0;\n  return data->val;\n}\n\nbool permission_setAdmin(const char* name)\n{\n  User* tempuser = anyUserFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  SET_ADMIN(tempuser->permissions);\n  return true;\n}\n\nbool permission_setOp(const char* name)\n{\n  User* tempuser = anyUserFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  tempuser->permissions = 0; // reset any previous permissions\n  SET_OP(tempuser->permissions);\n  return true;\n}\n\nbool permission_setMember(const char* name)\n{\n  User* tempuser = anyUserFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  tempuser->permissions = 0; // reset any previous permissions\n  SET_MEMBER(tempuser->permissions);\n  return true;\n}\n\nbool permission_setGuest(const char* name)\n{\n  User* tempuser = anyUserFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  tempuser->permissions = 0; // reset any previous permissions\n  SET_GUEST(tempuser->permissions);\n  return true;\n}\n\nbool permission_isAdmin(const char* name)\n{\n  User* tempuser = userFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  return (IS_ADMIN(tempuser->permissions) != 0);\n}\n\nbool permission_isOp(const char* name)\n{\n  User* tempuser = userFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  return (IS_OP(tempuser->permissions) != 0);\n}\n\nbool permission_isMember(const char* name)\n{\n  User* tempuser = userFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  return (IS_MEMBER(tempuser->permissions) != 0);\n}\n\nbool permission_isGuest(const char* name)\n{\n  User* tempuser = userFromName(std::string(name));\n  if (tempuser == NULL)\n  {\n    return false;\n  }\n  return (IS_GUEST(tempuser->permissions) != 0);\n}\n\nint tools_uniformInt(int a, int b)\n{\n  if (a < 0)\n  {\n    return uniformUINT(0, b - a) + a;\n  }\n  return uniformUINT(a, b);\n}\n\ndouble tools_uniform01()\n{\n  return uniform01();\n}\n\nbool tools_namedSoundEffect(const char* name, int x, int y, int z, float volume, char pitch)\n{\n  for (User* user : ServerInstance->users())\n  {\n    if (user->fd && user->logged)\n    {\n      float xx = user->pos.x-(float)x/32.0f;\n      float yy = user->pos.y-(float)y/32.0f;\n      float zz = user->pos.z-(float)z/32.0f;\n      int dist = sqrtf(xx*xx + yy*yy + zz*zz)/2.0f;\n      if (dist < 1.0f) dist = 1.0f;\n      user->writePacket(Protocol::namedSoundEffect(std::string(name), x, y, z, volume*(1.0f/dist), pitch));\n    }\n  }\n  return true;\n}\n\nvoid init_plugin_api(void)\n{\n  plugin_api_pointers.logger.log                   = &logger_log;\n\n  plugin_api_pointers.chat.sendmsg                 = &chat_sendmsg;\n  plugin_api_pointers.chat.sendmsgTo               = &chat_sendmsgTo;\n  plugin_api_pointers.chat.sendUserlist            = &chat_sendUserlist;\n  plugin_api_pointers.chat.handleMessage           = &chat_handleMessage;\n\n  plugin_api_pointers.plugin.hasPluginVersion      = &plugin_hasPluginVersion;\n  plugin_api_pointers.plugin.getPluginVersion      = &plugin_getPluginVersion;\n  plugin_api_pointers.plugin.setPluginVersion      = &plugin_setPluginVersion;\n  plugin_api_pointers.plugin.remPluginVersion      = &plugin_remPluginVersion;\n  plugin_api_pointers.plugin.hasPointer            = &plugin_hasPointer;\n  plugin_api_pointers.plugin.getPointer            = &plugin_getPointer;\n  plugin_api_pointers.plugin.setPointer            = &plugin_setPointer;\n  plugin_api_pointers.plugin.remPointer            = &plugin_remPointer;\n  plugin_api_pointers.plugin.hasHook               = &plugin_hasHook;\n  //plugin_api_pointers.plugin.getHook               = &plugin_getHook;\n  //plugin_api_pointers.plugin.setHook               = &plugin_setHook;\n  plugin_api_pointers.plugin.remHook               = &plugin_remHook;\n  plugin_api_pointers.plugin.hasCallback           = &hook_hasCallback;\n  plugin_api_pointers.plugin.addCallback           = &hook_addCallback;\n  plugin_api_pointers.plugin.addIdentifiedCallback = &hook_addIdentifiedCallback;\n  plugin_api_pointers.plugin.remCallback           = &hook_remCallback;\n  plugin_api_pointers.plugin.doUntilTrue           = &hook_doUntilTrue;\n  plugin_api_pointers.plugin.doUntilFalse          = &hook_doUntilFalse;\n  plugin_api_pointers.plugin.doAll                 = &hook_doAll;\n\n  plugin_api_pointers.map.setTime                  = &map_setTime;\n  plugin_api_pointers.map.getTime                  = &map_getTime;\n  plugin_api_pointers.map.createPickupSpawn        = &map_createPickupSpawn;\n  plugin_api_pointers.map.getSpawn                 = &map_getSpawn;\n  plugin_api_pointers.map.setSpawn                 = &map_setSpawn;\n  plugin_api_pointers.map.setBlock                 = &map_setBlock;\n  plugin_api_pointers.map.getBlock                 = &map_getBlock;\n  plugin_api_pointers.map.saveWholeMap             = &map_saveWholeMap;\n  plugin_api_pointers.map.getMapData_block         = &map_getMapData_block;\n  plugin_api_pointers.map.getMapData_meta          = &map_getMapData_meta;\n  plugin_api_pointers.map.getMapData_skylight      = &map_getMapData_skylight;\n  plugin_api_pointers.map.getMapData_blocklight    = &map_getMapData_blocklight;\n  plugin_api_pointers.map.setBlockW                = &map_setBlockW;\n  plugin_api_pointers.map.getBlockW                = &map_getBlockW;\n\n  plugin_api_pointers.user.getPosition             = &user_getPosition;\n  plugin_api_pointers.user.teleport                = &user_teleport;\n  plugin_api_pointers.user.sethealth               = &user_sethealth;\n  plugin_api_pointers.user.teleportMap             = &user_teleportMap;\n  plugin_api_pointers.user.getCount                = &user_getCount;\n  plugin_api_pointers.user.getUserNumbered         = &user_getUserNumbered;\n  plugin_api_pointers.user.getPositionW            = &user_getPositionW;\n  plugin_api_pointers.user.getItemInHand           = &user_getItemInHand;\n  plugin_api_pointers.user.setItemInHand           = &user_setItemInHand;\n  plugin_api_pointers.user.addItem                 = &user_addItem;\n  plugin_api_pointers.user.hasItem                 = &user_hasItem;\n  plugin_api_pointers.user.delItem                 = &user_delItem;\n  plugin_api_pointers.user.toggleDND               = &user_toggleDND;\n  plugin_api_pointers.user.gethealth               = &user_gethealth;\n  plugin_api_pointers.user.kick                    = &user_kick;\n  plugin_api_pointers.user.getItemAt               = &user_getItemAt;\n  plugin_api_pointers.user.setItemAt               = &user_setItemAt;\n  plugin_api_pointers.user.setGameMode             = &user_setGameMode;\n\n  plugin_api_pointers.config.has                   = &config_has;\n  plugin_api_pointers.config.iData                 = &config_iData;\n  plugin_api_pointers.config.lData                 = &config_lData;\n  plugin_api_pointers.config.fData                 = &config_fData;\n  plugin_api_pointers.config.dData                 = &config_dData;\n  plugin_api_pointers.config.sData                 = &config_sData;\n  plugin_api_pointers.config.bData                 = &config_bData;\n\n  plugin_api_pointers.mob.createMob                = &mob_createMob;\n  plugin_api_pointers.mob.createSpawnMob           = &mob_createSpawnMob;\n  plugin_api_pointers.mob.spawnMob                 = &mob_spawnMob;\n  plugin_api_pointers.mob.despawnMob               = &mob_despawnMob;\n  plugin_api_pointers.mob.moveMob                  = &mob_moveMob;\n  plugin_api_pointers.mob.moveMobW                 = &mob_moveMobW;\n  plugin_api_pointers.mob.getHealth                = &mob_getHealth;\n  plugin_api_pointers.mob.getMobID                 = &mob_getMobID;\n  plugin_api_pointers.mob.setHealth                = &mob_setHealth;\n  plugin_api_pointers.mob.moveAnimal               = &mob_moveAnimal;\n  plugin_api_pointers.mob.animateMob               = &mob_animateMob;\n  plugin_api_pointers.mob.animateDamage            = &mob_animateDamage;\n  plugin_api_pointers.mob.getType                  = &mob_getType;\n  plugin_api_pointers.mob.getMobPositionW          = &mob_getMobPositionW;\n  plugin_api_pointers.mob.getLook                  = &mob_getLook;\n  plugin_api_pointers.mob.setLook                  = &mob_setLook;\n  plugin_api_pointers.mob.setByteMetadata          = &mob_setByteMetadata;\n  plugin_api_pointers.mob.updateMetadata           = &mob_updateMetadata;\n  plugin_api_pointers.mob.getByteMetadata          = &mob_getByteMetadata;\n\n  plugin_api_pointers.permissions.setAdmin         = &permission_setAdmin;\n  plugin_api_pointers.permissions.setOp            = &permission_setOp;\n  plugin_api_pointers.permissions.setMember        = &permission_setMember;\n  plugin_api_pointers.permissions.setGuest         = &permission_setGuest;\n  plugin_api_pointers.permissions.isAdmin          = &permission_isAdmin;\n  plugin_api_pointers.permissions.isOp             = &permission_isOp;\n  plugin_api_pointers.permissions.isMember         = &permission_isMember;\n  plugin_api_pointers.permissions.isGuest          = &permission_isGuest;\n  \n  plugin_api_pointers.tools.uniformInt             = &tools_uniformInt;\n  plugin_api_pointers.tools.uniform01              = &tools_uniform01;\n  plugin_api_pointers.tools.namedSoundEffect       = &tools_namedSoundEffect;\n}\n"
  },
  {
    "path": "src/plugin_api.h",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _PLUGIN_API_H\n#define _PLUGIN_API_H\n\n#ifdef __cplusplus\n#ifndef MINESERVER_C_API\n#define USE_HOOKS\n#endif\n#else\n#include <stdbool.h>\n#endif\n\n#include <stdint.h>\n\n#include \"logtype.h\"\n#include \"configure.h\"\n\n#ifdef WIN32\n#define PLUGIN_API_EXPORT extern \"C\" __declspec(dllexport)\n#define CALLCONVENSION __cdecl\n#else\n#define PLUGIN_API_EXPORT extern \"C\"\n#define CALLCONVENSION\n#endif\n#define CALLCONVERSION CALLCONVENSION\n#include \"constants_num.h\"\n\ntypedef void (*voidF)(); // voidF is a \"void\"-like function pointer\n\nstruct plugin_pointer_struct\n{\n  bool (*hasPluginVersion)(const char* name);\n  float(*getPluginVersion)(const char* name);\n  void (*setPluginVersion)(const char* name, float version);\n  void (*remPluginVersion)(const char* name);\n\n  bool (*hasPointer)(const char* name);\n  void*(*getPointer)(const char* name);\n  void (*setPointer)(const char* name, void* pointer);\n  void (*remPointer)(const char* name);\n\n  bool (*hasHook)(const char* hookID);\n  /*\n#ifdef USE_HOOKS\n  Hook*(*getHook)(const char* hookID);\n  void (*setHook)(const char* hookID, Hook* hook);\n#else  \n  void*(*getHook)(const char* hookID);\n  void (*setHook)(const char* hookID, void* hook);\n#endif\n  */\n  void (*hookfiller)(void);\n  void (*hookfiller2)(void);\n\n  void (*remHook)(const char* hookID);\n\n  bool (*hasCallback)(const char* hookID, voidF function);\n  void (*addCallback)(const char* hookID, voidF function);\n  void (*addIdentifiedCallback)(const char* hookID, void* identifier, voidF function);\n  void (*remCallback)(const char* hookID, voidF function);\n  bool (*doUntilTrue)(const char* hookID, ...);\n  bool (*doUntilFalse)(const char* hookID, ...);\n  void (*doAll)(const char* hookID, ...);\n\n  void* temp[10];\n};\n\nstruct user_pointer_struct\n{\n  bool (*teleport)(const char* user, double x, double y, double z);\n  bool (*toggleDND)(const char* user);\n  bool (*getPosition)(const char* user, double* x, double* y, double* z, float* yaw, float* pitch, double* stance);\n  bool (*sethealth)(const char* user, int userHealth);\n  bool (*teleportMap)(const char* user, double x, double y, double z, size_t map);\n  int (*getCount)();\n  const char* (*getUserNumbered)(int c);\n  bool (*getPositionW)(const char* user, double* x, double* y, double* z, int* w, float* yaw, float* pitch, double* stance);\n  bool (*addItem)(const char* user, int item, int count, int health);\n  bool (*hasItem)(const char* user, int item, int count, int health);\n  bool (*delItem)(const char* user, int item, int count, int health);\n  int (*gethealth)(const char* user);\n  bool (*getItemInHand)(const char* user, int* type, int* meta, int* quant);\n  bool (*setItemInHand)(const char* user, int type, int meta, int quant);\n  bool (*kick)(const char* user);\n  bool (*getItemAt)(const char* user, int slot, int* type, int* meta, int* quant);\n  bool (*setItemAt)(const char* user, int slot, int type, int meta, int quant);\n\n  bool (*setGameMode)(const char* user, int gameMode);\n\n  void* temp[95];\n};\n\nstruct chat_pointer_struct\n{\n  bool (*sendmsgTo)(const char* user, const char* msg);\n  bool (*sendmsg)(const char* msg);\n  bool (*sendUserlist)(const char* user);\n  bool (*handleMessage)(const char* user, const char* msg);\n  void* temp[100];\n};\n\nstruct logger_pointer_struct\n{\n  void (*log)(int type, const char* source, const char* message);\n  void* temp[100];\n};\n\nstruct map_pointer_struct\n{\n  void (*createPickupSpawn)(int x, int y, int z, int type, int count, int health, const char* user);\n  bool (*setTime)(int timeValue);\n  int (*getTime)();\n  void (*getSpawn)(int* x, int* y, int* z);\n  void (*setSpawn)(int x, int y, int z);\n  bool (*getBlock)(int x, int y, int z, unsigned char* type, unsigned char* meta);\n  bool (*setBlock)(int x, int y, int z, unsigned char type, unsigned char meta);\n  void (*saveWholeMap)(void);\n  unsigned char*(*getMapData_block)(int x, int z);\n  unsigned char*(*getMapData_meta)(int x, int z);\n  unsigned char*(*getMapData_skylight)(int x, int z);\n  unsigned char*(*getMapData_blocklight)(int x, int z);\n  bool (*getBlockW)(int x, int y, int z, int w, unsigned char* type, unsigned char* meta);\n  bool (*setBlockW)(int x, int y, int z, int w, unsigned char type, unsigned char meta);\n  void* temp[100];\n};\n\nstruct config_pointer_struct\n{\n  bool (*has)(const char* name);\n  int (*iData)(const char* name);\n  int64_t (*lData)(const char* name);\n  float(*fData)(const char* name);\n  double(*dData)(const char* name);\n  const char*(*sData)(const char* name);\n  bool (*bData)(const char* name);\n  void* temp[100];\n};\n\nstruct mob_pointer_struct\n{\n  int (*createMob)(int type);\n  int (*createSpawnMob)(int type);\n  void (*spawnMob)(int uid);\n  void (*despawnMob)(int uid);\n  void (*moveMob)(int uid, double x, double y, double z);\n  void (*moveMobW)(int uid, double x, double y, double z, int map);\n  bool (*getMobPositionW)(int uid, double* x, double* y, double* z, int* w);\n  int (*getMobID)(int uid);\n  int (*getHealth)(int uid);\n  void (*setHealth)(int uid, int mobHealth);\n  int (*getType)(size_t uid);\n  bool (*getLook)(int uid, double* yaw, double* pitch, double *head_yaw);\n  bool (*setLook)(int uid, double yaw, double pitch, double head_yaw);\n  void (*moveAnimal)(const char* userIn, size_t mobID);\n  void (*animateMob)(const char* userIn, size_t mobID, int animID);\n  void (*animateDamage)(const char* userIn, size_t mobID, int animID);\n  bool (*setByteMetadata)(int uid, int8_t idx, int8_t byte);\n  bool (*updateMetadata)(int uid);\n  int8_t (*getByteMetadata)(int uid, int idx);\n  void* temp[97];\n\n};\n\nstruct permission_pointer_struct\n{\n  bool (*setAdmin)(const char* name);\n  bool (*setOp)(const char* name);\n  bool (*setMember)(const char* name);\n  bool (*setGuest)(const char* name);\n  bool (*isAdmin)(const char* name);\n  bool (*isOp)(const char* name);\n  bool (*isMember)(const char* name);\n  bool (*isGuest)(const char* name);\n  void* temp[100];\n\n};\n\nstruct tools_pointer_struct\n{\n  int (*uniformInt)(int a, int b);\n  double (*uniform01)();\n  bool (*namedSoundEffect)(const char* name, int x, int y, int z, float volume, char pitch);\n};\n\nstruct mineserver_pointer_struct\n{\n  struct map_pointer_struct map;\n  struct logger_pointer_struct logger;\n  struct chat_pointer_struct chat;\n  struct plugin_pointer_struct plugin;\n  struct user_pointer_struct user;\n  struct config_pointer_struct config;\n  struct mob_pointer_struct mob;\n  struct permission_pointer_struct permissions;\n  struct tools_pointer_struct tools;\n  void* temp[98];\n};\n\n// Ignore these, only used when compiling with Mineserver\n#ifdef MINESERVER\nvoid init_plugin_api(void);\nextern mineserver_pointer_struct plugin_api_pointers;\n#endif\n\n#endif\n"
  },
  {
    "path": "src/plugins/PyScript/.gitignore",
    "content": "complete\nMineServer_wr*\nMineServer.py*\n"
  },
  {
    "path": "src/plugins/PyScript/MineServer.i",
    "content": "%module MineServer\n%ignore getMineServer();\n%feature(\"autodoc\", \"1\");\n%include \"std_string.i\"\nusing namespace std;\ntypedef std::string String;\n%{\n#include \"python_plugin_api.h\"\n\n%}\n%include \"python_plugin_api.h\"\n%pythoncode %{\ndef setUpMSPointer(ms):\n    get_MS().setMineServer(ms)\n%}\n"
  },
  {
    "path": "src/plugins/PyScript/PyScript.cpp",
    "content": "#define PVERSION 1.1\n\n#include <Python.h>\n#include <iostream>\n#include <sstream>\n#include <stdlib.h>\n#include <math.h>\n#include <vector>\n#include <string>\n#include <errno.h>\n#include <iostream>\n#include <dirent.h>\n#include <sys/types.h>\n\n#include \"plugin_api.h\"\n#include \"python_plugin_api.h\"\n#include \"PyScript.h\"\n#include \"MineServer_wrap.cxx\"\n\nusing namespace std;\n\nmineserver_pointer_struct* safe;\nmineserver_pointer_struct* ms;\nPyObject* mod;\n\n\nScript* the_script;\n\nvoid checkPyErr()\n{\n  if (PyErr_Occurred())\n  {\n    PyErr_Print();\n  }\n}\n\n\n//PyScript* mainPS;\n\n//void PyScript::callbackLogin(bool temp, User* user, bool* kick, std::string* reason){\n//    callAllFunc(\"player_login\");\n//}\n\nScript::Script(mineserver_pointer_struct* mine, string name): m_mineserver(mine)\n{\n  load(name);\n}\n\n//Script::Script(const Script &last){\n//    mod = last.mod;\n//}\n\nvoid Script::load(string ModName)\n{\n  modname = ModName;\n  PyObject* pName, *Args, *Arg;\n  pName = PyString_FromString(ModName.c_str());\n  ::mod = PyImport_Import(pName);\n  checkPyErr();\n  Py_DECREF(pName);\n\n  Arg = SWIG_NewPointerObj((void*)m_mineserver, SWIGTYPE_p_mineserver_pointer_struct, 1);\n  Args = Py_BuildValue(\"(O)\", Arg);\n\n  callPyFunc(\"setUpMSPointer\", Args);\n  Py_XDECREF(Args);\n  checkPyErr();\n  PyObject* Args2;\n  Args2 = PyTuple_New(0);\n  callPyFunc(\"init\", Args2);\n}\n\nScript::~Script()\n{\n\n}\n\n//int PyScript::getdir (string dir, vector<string> &files)\n//{\n//    DIR *dp;\n//    struct dirent *dirp;\n//    if((dp  = opendir(dir.c_str())) == NULL) {\n//        return errno;\n//    }\n//\n//    while ((dirp = readdir(dp)) != NULL) {\n//        files.push_back(string(dirp->d_name));\n//    }\n//    closedir(dp);\n//    return 0;\n//}\n\nPyObject* Script::callPyFunc(const char* name, PyObject* Args)\n{\n  PyObject*  pValue, *pFunc;\n  if (::mod != NULL)\n  {\n    pFunc = PyObject_GetAttrString(::mod, name);\n    if (pFunc && PyCallable_Check(pFunc))\n    {\n      pValue = PyObject_CallObject(pFunc, Args);\n      if (pValue != NULL)\n      {\n        Py_XDECREF(pFunc);\n        return pValue;\n      }\n      Py_XDECREF(pValue);\n    }\n    else\n    {\n      checkPyErr();\n    }\n    Py_XDECREF(pFunc);\n  }\n  else\n  {\n    string str1 = \"Module \", str2 = \" is null\";\n    m_mineserver->logger.log(6, \"Plugin\", (str1 + modname + str2).c_str());\n  }\n  return NULL;\n}\n\n//PyScript::PyScript(mineserver_pointer_struct* mineserver) : m_mineserver(mineserver)\n//{\n////    mineserver->plugin()->hookLogin.addCallback(&PyScript::callbackLogin);\n//    string dir = string(\"python\");\n//    string filename;\n//    size_t found,found2,found3;\n//    vector<string> files = vector<string>();\n//    getdir(dir, files);\n//    scripts = vector<Script*>();\n//    Py_Initialize();\n//    //init_MineServer();\n//    PyRun_SimpleString(\"import sys; sys.path.insert(0,\\\"python\\\"); sys.path.insert(0,\\\".\\\");\");\n//    PyRun_SimpleString(\"import MineServer\");\n\n//    for (unsigned int i = 0; i < files.size(); i++){\n//        found = files[i].rfind(string(\".py\"));\n//        found2 = files[i].rfind(string(\".pyc\"));\n//        found3 = files[i].find(string(\".\"));\n//        if(found!=string::npos && found2==string::npos && found3!=0){\n//            m_mineserver->logger.log(6,\"Plugin\",(\"Loading : \"+files[i]).c_str());\n//            filename = files[i].substr(0,found);\n//            Script thescript = Script(mineserver,filename);\n//            scripts.push_back(&thescript);\n//        }\n//    }\n//}\n\n//PyObject* PyScript::callAllFunc(const char* func, PyObject* Args){\n//    unsigned int i;\n//    for(i = 0; i<scripts.size(); i++){\n//        Script *sc = scripts.at(i);\n//        sc->callPyFunc(func,Args);\n//    }\n//    return NULL;\n//}\n\n//PyScript::~PyScript(){\n//    PyObject* Args;\n//    Args=PyTuple_New(0);\n//    callAllFunc(\"deinit\",Args);\n//    Py_DECREF(Args);\n//    Py_Finalize();\n//}\n\nmineserver_pointer_struct* getMineServer()\n{\n  if ((int)::ms == 0)\n  {\n    cout << \"Passing zero pointer as MineServer struct! SEGFAULT COMMING\" << endl;\n  }\n  return ::ms;\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION PyScript_init(mineserver_pointer_struct* mineserver)\n{\n  ::safe  = mineserver;\n  //    getMS()->setMineServer(mineserver);\n  // Timers\n  mineserver->plugin.addCallback(\"Timer200\", (void*)timer200Function);\n  mineserver->plugin.addCallback(\"Timer1000\", (void*)timer1000Function);\n  mineserver->plugin.addCallback(\"Timer10000\", (void*)timer10000Function);\n\n  // Chat\n  mineserver->plugin.addCallback(\"PlayerChatPre\", (void*)chatPreFunction);\n\n  // Map callbacks\n  mineserver->plugin.addCallback(\"BlockPlacePre\", (void*)blockPlaceFunction);\n  mineserver->plugin.addCallback(\"BlockBreakPre\", (void*)blockBreakFunction);\n\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION set_name(const char* name)\n{\n  std::string script_name = std::string(name);\n  size_t pos = script_name.rfind(\"\\\\\");\n  while (pos != string::npos)\n  {\n    script_name.replace(pos, 1, \"/\"); // Silently ignore backslashes\n    pos = script_name.find(\"\\\\\");\n  }\n  //    PyImport_AppendInittab(\"MineServer\",init_MineServer);\n  Py_Initialize();\n  SWIG_init();\n  init_MineServer();\n  ::ms =::safe;\n  PyRun_SimpleString(\"import sys;\");\n  PyRun_SimpleString(\"sys.path.insert(0,\\\".\\\");\");\n  string f_slash(\"/\");\n  string path_to = script_name.substr(\n                     0,\n                     script_name.rfind(f_slash));\n  string c1(\"sys.path.insert(0,\\\"\");\n  string c2(\"\\\");\");\n  string command(c1 + path_to + c2);\n  PyRun_SimpleString(command.c_str());\n  size_t start = script_name.rfind(\"/\") + 1;\n  size_t len = script_name.rfind(\".\") - start;\n  string filename = script_name.substr(start, len);\n  PyRun_SimpleString(\"import MineServer\");\n\n  Script newScript = Script(::ms, filename);\n\n  the_script = &newScript;\n  ::ms =::safe;\n}\n\nPLUGIN_API_EXPORT void CALLCONVERSION PyScript_shutdown(void)\n{\n}\n\n\n\nbool chatPreFunction(const char* userIn, time_t timestamp, const char* msgIn)\n{\n  PyObject* ret, *param;\n  param = Py_BuildValue(\"ss\", userIn, msgIn);\n  ret = the_script->callPyFunc(\"cb_chat\", param);\n  checkPyErr();\n  Py_XDECREF(param);\n  if (PyBool_Check(ret))\n  {\n    Py_XDECREF(ret);\n    return ret == Py_True;\n  }\n  Py_XDECREF(ret);\n\n  return true;\n}\n\nbool timer200Function()\n{\n  PyObject* param;\n  param = PyTuple_New(0);\n  the_script->callPyFunc(\"cb_timer200\", param);\n  checkPyErr();\n  Py_XDECREF(param);\n}\n\nbool timer1000Function()\n{\n  PyObject* param;\n  param = PyTuple_New(0);\n  the_script->callPyFunc(\"cb_timer1000\", param);\n  checkPyErr();\n  Py_XDECREF(param);\n}\n\nbool timer10000Function()\n{\n  PyObject* param;\n  param = PyTuple_New(0);\n  the_script->callPyFunc(\"cb_timer10000\", param);\n  checkPyErr();\n  Py_XDECREF(param);\n}\n\nbool blockPlaceFunction(const char* name, int32_t x, int8_t y, int32_t z,\n                        int16_t id, int8_t dir)\n{\n  PyObject* param, *Arg, *ret;\n  PyBlock* block = get_MS()->map.get_block((int)x, (int)y, (int)z);\n  Arg = SWIG_NewPointerObj((void*)block, SWIGTYPE_p_PyBlock, 1);\n  param = Py_BuildValue(\"(sO)\", name, Arg);\n  ret = the_script->callPyFunc(\"cb_block_place\", param);\n  checkPyErr();\n  Py_XDECREF(Arg);\n  Py_XDECREF(param);\n  if (ret && PyBool_Check(ret))\n  {\n    Py_XDECREF(ret);\n    return ret == Py_True;\n  }\n  Py_XDECREF(ret);\n  return true;\n}\n\nbool blockBreakFunction(const char* name, int x, int y, int z)\n{\n  PyObject* param, *Arg, *ret;\n  PyBlock* block = get_MS()->map.get_block((int)x, (int)y, (int)z);\n  Arg = SWIG_NewPointerObj((void*)block, SWIGTYPE_p_PyBlock, 1);\n  param = Py_BuildValue(\"(sO)\", name, Arg);\n  ret = the_script->callPyFunc(\"cb_block_break\", param);\n  checkPyErr();\n  Py_XDECREF(Arg);\n  Py_XDECREF(param);\n  if (ret && PyBool_Check(ret))\n  {\n    Py_XDECREF(ret);\n    return ret == Py_True;\n  }\n  Py_XDECREF(ret);\n  return true;\n}\n\n\n\n\n"
  },
  {
    "path": "src/plugins/PyScript/PyScript.h",
    "content": "#define PVERSION 1.1\n\n#include <Python.h>\n#include <iostream>\n#include <stdlib.h>\n#include <math.h>\n#include <vector>\n#include <string>\n#include <errno.h>\n#include <iostream>\n#include <dirent.h>\n#include <sys/types.h>\n\n//##ifndef PyScript\n//##define PyScript\n#include \"plugin_api.h\"\n\n\nusing namespace std;\n\nvoid checkPyErr();\n\nclass Script\n{\npublic:\n  Script(mineserver_pointer_struct* mineserver, string name);\n  Script(const Script& last);\n  ~Script();\n  PyObject* callPyFunc(const char* name, PyObject* Args);\n  void load(string ModName);\nprivate:\n  mineserver_pointer_struct* m_mineserver;\n  //        PyObject* mod;\n  string modname;\n};\n\n// Stuff only to be used in C++ plugin, not in python wrapper\n#ifndef SWIG\nextern mineserver_pointer_struct* ms;\nmineserver_pointer_struct* getMineServer();\n\n// Call Back defs\nbool chatPreFunction(const char* userIn, time_t timestamp, const char* msgIn);\nbool timer200Function();\nbool timer500Function();\nbool timer1000Function();\nbool timer10000Function();\nbool blockPlaceFunction(const char* name, int32_t x, int8_t y, int32_t z,\n                        int16_t id, int8_t dir);\nbool blockBreakFunction(const char* name, int x, int y, int z);\n\n\n\n\n#endif\n\n//class PyScript\n//{\n//    public:\n//        PyScript(mineserver_pointer_struct* mineserver);\n//        ~PyScript();\n//        int getdir(string dir, vector<string> &files);\n//        PyObject* callAllFunc(const char* func, PyObject *args);\n//        static PyObject* MineServer_get_version(PyObject *self, PyObject *args);\n//    private:\n//        mineserver_pointer_struct* m_mineserver;\n//        vector<Script*> scripts;\n//};\n\n//##endif\n"
  },
  {
    "path": "src/plugins/PyScript/makefile",
    "content": "# Makefile for PyScript\nall: complete\nSHELL = /bin/sh\n\nCFLAGS = $(shell python-config --cflags) -fPIC -O0 -g\nLDFLAGS = $(shell python-config --ldflags) -shared -Xlinker -export-dynamic\n\nifeq ($(DEBIAN), 1)\n  CFLAGS  += -DDEBIAN\nendif\n\nCOMP = g++\nifeq ($(CLANG), YES)\n  COMP = clang\nendif\n\nOBJS = PyScript.o python_plugin_api.o\n\ncomplete: PyScript.so _MineServer.so MineServer.py\n\tcp PyScript.so ../../../bin\n\tcp _MineServer.so MineServer.py ../../../bin\n\tcp -r python ../../../bin/\n\ttouch complete\n\nPyScript.so : python/TriggTest.py _MineServer.so $(OBJS)\n\t$(COMP) $(LDFLAGS) -g -rdynamic -Wl,-soname,PyScript.so -o PyScript.so -lc $(OBJS)\n\nPyScript.o : PyScript.cpp MineServer_wrap.cxx PyScript.h\n\t$(COMP) $(CFLAGS) -c PyScript.cpp\n\npython_plugin_api.o: python_plugin_api.cpp python_plugin_api.h ../../plugin_api.cpp ../../plugin_api.h\n\t$(COMP) $(CFLAGS) -c python_plugin_api.cpp\n\nMineServer_wrap.cxx: MineServer.i ../../plugin_api.cpp ../../plugin_api.h python_plugin_api.cpp python_plugin_api.h\n\tswig -c++ -python MineServer.i\n\nMineServer_wrap.o: MineServer_wrap.cxx MineServer.py\n\t$(COMP) $(CFLAGS) -c MineServer_wrap.cxx\n\n_MineServer.so: $(OBJS)\n\t$(COMP) $(LDFLAGS) $(OBJS) -Wl,-soname,_MineServer.so -o _MineServer.so \n\nclean:\n\trm *.o\n\trm *.so\n\trm *.py*\n\trm MineServer_w*\n\trm complete\n"
  },
  {
    "path": "src/plugins/PyScript/python/TriggTest.py",
    "content": "# Plugin 1 for PyScript\nfrom MineServer import *;\nimport math;\nglobal M, lastblock,ltype\n\ndef init():\n    global M,lastblock, ltype\n    M= get_MS()\n    M.screen.log(\"Loaded TriggTest\")\n    lastblock = M.map.get_block(0,0,0)\n    ltype=7\n\n\ndef cb_timer200():\n    global lastblock, ltype\n    user = M.get_user(\"trigg\");\n    if not user==None:\n        print user.location.x, user.location.y, user.location.z\n        block = M.map.get_block(int(math.floor(user.location.x)),int(math.floor(user.location.y-1)),int(math.floor(user.location.z)));\n        b=block;lb=lastblock\n        if((not b.x==lb.x) or (not b.y==lb.y) or (not b.z==lb.z)):\n            ntype= block.get_type()\n            block.set_type(41)\n            lastblock.set_type(ltype)\n            lastblock=block\n            ltype=ntype\n\n    # Called at BEST every 200 milliseconds, might be later if under\n    # strain\n    pass\n\ndef cb_timer1000():\n    M.map.set_time(0)\n    pass\n\ndef cb_timer10000():\n    pass\n\ndef cb_block_place(name,block):\n    return False\n    pass\n\n\n\ndef cb_chat(name, msg):\n    print name,msg\n    return True\n\n"
  },
  {
    "path": "src/plugins/PyScript/python_plugin_api.cpp",
    "content": "/*\n  Copyright (c) 2010, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <iostream>\n#include <sstream>\n#include <stdlib.h>\n#include <math.h>\n#include <vector>\n#include <string>\n#include <errno.h>\n#include <iostream>\n#include <dirent.h>\n#include <sys/types.h>\n#include \"PyScript.h\"\n#include \"python_plugin_api.h\"\n\nPyMineserver* pymines = new PyMineserver();\n\nPyMineserver* get_MS()\n{\n  return pymines;\n}\n\nint PyBlock::get_type()\n{\n  return type;\n}\n\nvoid PyBlock::set_type(int new_type)\n{\n  getMineServer()->map.setBlock(x, y, z, new_type, meta);\n}\n\nint PyBlock::get_meta()\n{\n  return meta;\n}\n\nvoid PyBlock::set_meta(int new_meta)\n{\n  getMineServer()->map.setBlock(x, y, z, type, new_meta);\n}\n\nvoid PyUser::teleport(PyLoc new_location)\n{\n  getMineServer()->user.teleport(name, new_location.x, new_location.y, new_location.z);\n}\n\nvoid PyUser::set_health(int health)\n{\n  getMineServer()->user.sethealth(name, health);\n}\n\nvoid PyChat::send_message_to(const char* user, const char* message)\n{\n  getMineServer()->chat.sendmsgTo(user, message);\n}\n\nvoid PyChat::send_message(const char* message)\n{\n  getMineServer()->chat.sendmsg(message);\n}\n\nvoid PymyMap::create_item(int x, int y, int z, int type, int count, int health, std::string user)\n{\n  getMineServer()->map.createPickupSpawn(x, y, z, type, count, health, user.c_str());\n}\nmineserver_pointer_struct* magical()\n{\n  return getMineServer();\n}\nbool PymyMap::set_time(int timeValue)\n{\n  return ::ms->map.setTime(timeValue);\n}\nPyLoc* PymyMap::get_spawn()\n{\n  PyLoc* L = new PyLoc();\n  int* x, *y, *z;\n  double dx, dy, dz;\n  getMineServer()->map.getSpawn(x, y, z);\n  dx = (double) * x;\n  dy = (double) * y;\n  dz = (double) * z;\n  L->x = dx;\n  L->y = dy;\n  L->z = dz;\n  return L;\n}\nvoid PymyMap::save()\n{\n  getMineServer()->map.saveWholeMap();\n}\nPyBlock* PymyMap::get_block(int x, int y, int z)\n{\n  unsigned char type, meta;\n  getMineServer()->map.getBlock(x, y, z, &type, &meta);\n  PyBlock* block = new PyBlock();\n  block->x = x;\n  block->y = y;\n  block->z = z;\n  block->type = (int)type;\n  block->meta = (int)meta;\n  return block;\n}\n\nvoid PyScreen::log(const char* message)\n{\n  std::string m2(message);\n  getMineServer()->logger.log(6, \"Plugin\", m2.c_str());\n}\n\nPyUser* PyMineserver::get_user(const char* player_name)\n{\n  PyLoc* loc = new PyLoc();\n  double stance;\n  if (getMineServer()->user.getPosition(\n        player_name, &loc->x, &loc->y, &loc->z,\n        (float*)&loc->rot, (float*)&loc->pit, &stance))\n  {\n    PyUser* user = new PyUser();\n    user->location = loc;\n    user->name = player_name;\n    return user;\n  }\n  return NULL;\n}\n\nvoid PyMineserver::setMineServer(mineserver_pointer_struct* MS)\n{\n  ::ms = MS;\n}\n"
  },
  {
    "path": "src/plugins/PyScript/python_plugin_api.h",
    "content": "/*\n  Copyright (c) 2010, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n\n#include <iostream>\n#include <stdlib.h>\n#include <math.h>\n#include <vector>\n#include <string>\n#include <errno.h>\n#include <iostream>\n#include <dirent.h>\n#include <sys/types.h>\n\n#ifndef PyWrapper\n#define PyWrapper\n\n#include \"plugin_api.h\"\n\nclass PyLoc\n{\npublic:\n  double x, y, z, rot, pit;\n};\n\nclass PyBlock\n{\npublic:\n  int x, y, z, type, meta;\n  int get_type();\n  void set_type(int new_type);\n  int get_meta();\n  void set_meta(int new_meta);\n};\n\nclass PyUser\n{\npublic:\n  const char* name;\n  PyLoc* location;\n  void teleport(PyLoc new_location);\n  void set_health(int health);\n};\n\nclass PyChat\n{\npublic:\n  void send_message_to(const char* user, const char* message);\n  void send_message(const char* message);\n};\n\nclass PymyMap\n{\npublic:\n  void save();\n  void create_item(int x, int y, int z, int type, int count, int health, std::string user);\n  bool set_time(int timeValue);\n  PyLoc* get_spawn();\n  PyBlock* get_block(int x, int y, int z);\n};\n\nclass PyScreen\n{\npublic:\n  void log(const char* message);\n};\n\nclass PyMineserver\n{\npublic:\n  PymyMap map;\n  PyScreen screen;\n  PyChat chat;\n  void setMineServer(mineserver_pointer_struct* MS);\n  PyUser* get_user(const char* player_name);\n};\n\nmineserver_pointer_struct* magical();\n\n\n\nPyMineserver* get_MS();\n#ifndef SWIG\n#endif\n\n#endif\n"
  },
  {
    "path": "src/plugins/banlist/banlist.cpp.unused",
    "content": "/**\n * Compile this with the following command if you're using linux (and gcc):\n * $ g++ -shared -o banlist.so banlist.cpp\n * (add -DDEBIAN if you're not on Debian)\n *\n * On Windows under MSVS you'll have to link the DLL with the .lib from the\n * mineserver binary. With MingW I'm not sure how to make it work...\n *\n * Then put it in the same directory as your mineserver binary and issue the\n * command `/load banlist ./banlist.so`. Of course replace .so with .dll if\n * you're running Windows.\n *\n * Right now it doesn't do much, but it does demonstrate all the basics needed\n * to write your own plugins. Make sure you check out banlist.h as well.\n */\n\n#include <string>\n#include <vector>\n\n#include \"../../mineserver.h\"\n#include \"../../plugin.h\"\n#include \"../../screen.h\"\n#include \"../../user.h\"\n\n#include \"banlist.h\"\n\nextern \"C\" void banlist_init(Mineserver* mineserver)\n{\n  if (mineserver->plugin()->getPluginVersion(\"banlist\") >= 0)\n  {\n    LOG(WARNING,\"plugin.banlist\", \"banlist is already loaded!\");\n    return;\n  }\n\n  mineserver->plugin()->setPluginVersion(\"banlist\", PLUGIN_BANLIST_VERSION);\n  mineserver->plugin()->setPointer(\"banlist\", new P_Banlist(mineserver));\n}\n\nextern \"C\" void banlist_shutdown(Mineserver* mineserver)\n{\n  if (mineserver->plugin()->getPluginVersion(\"banlist\") < 0)\n  {\n    LOG(WARNING, \"plugin.banlist\", \"banlist is not loaded!\");\n    return;\n  }\n\n  if (mineserver->plugin()->hasPointer(\"banlist\"))\n  {\n    P_Banlist* banlist = static_cast<P_Banlist*>(mineserver->plugin()->getPointer(\"banlist\"));\n    mineserver->plugin()->remPointer(\"banlist\");\n    delete banlist;\n  }\n\n  mineserver->plugin()->remPluginVersion(\"banlist\");\n}\n\nP_Banlist::P_Banlist(Mineserver* mineserver) : m_mineserver(mineserver)\n{\n  if (m_mineserver->plugin()->hasHook(\"LoginPre\"))\n  {\n    (static_cast<Hook2<bool,User*,std::string*>*>(m_mineserver->plugin()->getHook(\"LoginPre\")))->addCallback(&P_Banlist::callbackLoginPre);\n  }\n  else\n  {\n    LOG(WARNING, \"plugin.banlist\", \"Banlist: Can't find the LoginPre hook, banlist will not be operational.\");\n  }\n}\n\nP_Banlist::~P_Banlist()\n{\n  if (m_mineserver->plugin()->hasHook(\"LoginPre\"))\n  {\n    (static_cast<Hook2<bool,User*,std::string*>*>(m_mineserver->plugin()->getHook(\"LoginPre\")))->remCallback(&P_Banlist::callbackLoginPre);\n  }\n}\n\nbool P_Banlist::getBan(const std::string user)\n{\n  std::vector<std::string>::iterator it_a = m_banlist.begin();\n  std::vector<std::string>::iterator it_b = m_banlist.end();\n  for (;it_a!=it_b;++it_a)\n  {\n    if (*it_a == user)\n    {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nvoid P_Banlist::setBan(const std::string user, bool banned)\n{\n  std::vector<std::string>::iterator it_a = m_banlist.begin();\n  std::vector<std::string>::iterator it_b = m_banlist.end();\n  for (;it_a!=it_b;++it_a)\n  {\n    if (*it_a == user)\n    {\n      if (banned)\n      {\n        return;\n      }\n      else\n      {\n        m_banlist.erase(it_a);\n        return;\n      }\n    }\n  }\n\n  if (banned)\n  {\n    m_banlist.push_back(user);\n  }\n}\n\nbool P_Banlist::callbackLoginPre(User* user, std::string* reason)\n{\n  P_Banlist* banlist = static_cast<P_Banlist*>(ServerInstance->plugin()->getPointer(\"banlist\"));\n  LOG(INFO, \"plugin.banlist\", \"Banlist: Checking if user \"+user->nick+\" is banned\");\n  if (banlist->getBan(user->nick))\n  {\n    LOG(INFO, \"plugin.banlist\", \"Banlist: They are!\");\n    reason->assign(\"You've been banned!\");\n    return false;\n  }\n  else\n  {\n    LOG(INFO, \"plugin.banlist\", \"Banlist: They are not!\");\n    return true;\n  }\n}\n"
  },
  {
    "path": "src/plugins/banlist/banlist.h",
    "content": "#include <string>\n#include <vector>\n\n#include \"mineserver.h\"\n#include \"user.h\"\n\n#ifndef _PLUGIN_BANLIST_H\n#define _PLUGIN_BANLIST_H\n\n#define PLUGIN_BANLIST_VERSION 0.1\n\nclass P_Banlist\n{\npublic:\n  P_Banlist(Mineserver* mineserver);\n  ~P_Banlist();\n  bool getBan(const std::string user);\n  void setBan(const std::string user, bool banned);\n  static bool callbackLoginPre(User* user, std::string* reason);\nprivate:\n  Mineserver* m_mineserver;\n  std::vector<std::string> m_banlist;\n};\n\n#endif\n"
  },
  {
    "path": "src/plugins/command/command.cpp.unused",
    "content": "#include <string>\n#include <deque>\n#include <ctime>\n\n#include \"../../mineserver.h\"\n#include \"../../user.h\"\n\n#include \"command.h\"\n\nextern \"C\" void command_init(Mineserver* mineserver)\n{\n  if (mineserver->plugin()->getPluginVersion(\"command\") >= 0)\n  {\n    mineserver->screen()->log(\"command is already loaded!\");\n    return;\n  }\n\n  mineserver->plugin()->setPluginVersion(\"command\", PLUGIN_COMMAND_VERSION);\n  mineserver->plugin()->setPointer(\"command\", new P_Command(mineserver));\n}\n\nextern \"C\" void command_shutdown(Mineserver* mineserver)\n{\n  if (mineserver->plugin()->getPluginVersion(\"command\") < 0)\n  {\n    mineserver->screen()->log(\"command is not loaded!\");\n    return;\n  }\n\n  if (mineserver->plugin()->hasPointer(\"command\"))\n  {\n    P_Command* command = (P_Command*)mineserver->plugin()->getPointer(\"command\");\n    mineserver->plugin()->remPointer(\"command\");\n    delete command;\n  }\n\n  mineserver->plugin()->remPluginVersion(\"command\");\n}\n\nP_Command::P_Command(Mineserver* mineserver) : m_mineserver(mineserver)\n{\n  if (m_mineserver->plugin()->hasHook(\"ChatPre\"))\n  {\n    (static_cast<Hook3<bool,User*,time_t,std::string>*>(m_mineserver->plugin()->getHook(\"ChatPre\")))->addCallback(&P_Command::callbackChatPre);\n    m_mineserver->plugin()->setHook(\"CommandPre\", new Hook4<bool,User*,time_t,std::string*,std::deque<std::string*>*>);\n    m_mineserver->plugin()->setHook(\"CommandPost\", new Hook4<void,User*,time_t,std::string*,std::deque<std::string*>*>);\n  }\n  else\n  {\n    m_mineserver->screen()->log(\"Command: Can't find the ChatPre hook, commands will not be operational.\");\n  }\n}\n\nP_Command::~P_Command()\n{\n  if (m_mineserver->plugin()->hasHook(\"ChatPre\"))\n  {\n    (static_cast<Hook3<bool,User*,time_t,std::string>*>(m_mineserver->plugin()->getHook(\"ChatPre\")))->remCallback(&P_Command::callbackChatPre);\n  }\n\n  if (m_mineserver->plugin()->hasHook(\"CommandPre\") && (static_cast<Hook4<bool,User*,time_t,std::string*,std::deque<std::string*>*>*>(m_mineserver->plugin()->getHook(\"CommandPre\"))->numCallbacks() < 1))\n  {\n    m_mineserver->plugin()->remHook(\"CommandPre\");\n  }\n\n  if (m_mineserver->plugin()->hasHook(\"CommandPost\") && (static_cast<Hook4<void,User*,time_t,std::string*,std::deque<std::string*>*>*>(m_mineserver->plugin()->getHook(\"CommandPost\"))->numCallbacks() < 1))\n  {\n    m_mineserver->plugin()->remHook(\"CommandPost\");\n  }\n}\n\nbool P_Command::callbackChatPre(User* user, time_t time, std::string data)\n{\n  if ((data.substr(0, 1) == \"/\") && (data.length() > 1))\n  {\n    std::string* command_name = NULL;\n    std::deque<std::string*>* command_args = new std::deque<std::string*>;\n\n    int pos = 1;\n    while (pos < data.length())\n    {\n      // Skip whitespace\n      while (data.substr(pos, 1) == \" \")\n      {\n        pos++;\n      }\n\n      std::string* token = new std::string();\n      // We've got a quoted string\n      if (data.substr(pos, 1) == \"\\\"\")\n      {\n        // Skip first quote\n        pos++;\n\n        while ((data.substr(pos, 1) != \"\\\"\") && (pos < data.length()))\n        {\n          // Escape character is '\\'. We only want to act on it if we have space for both it and whatever it's escaping.\n          if ((data.substr(pos, 1) == \"\\\\\") && (pos < data.length()-1))\n          {\n            pos++;\n          }\n\n          token->append(data.substr(pos, 1));\n          pos++;\n        }\n\n        // Skip closing quote if necessary\n        // This will only be false if we hit the end of the string before finding the closing quote\n        if (data.substr(pos, 1) == \"\\\"\")\n        {\n          pos++;\n        }\n      }\n      // We've got some bare data\n      else\n      {\n        while ((data.substr(pos, 1) != \" \") && (pos < data.length()))\n        {\n          token->append(data.substr(pos, 1));\n          pos++;\n        }\n      }\n\n      // If we don't have a command name yet, this is the first token\n      if (command_name == NULL)\n      {\n        command_name = token;\n      }\n      // Otherwise this is an argument\n      else\n      {\n        command_args->push_back(token);\n      }\n    }\n\n    ServerInstance->screen()->log(\"Command (\"+user->nick+\"): \"+*command_name);\n\n    if (!static_cast<Hook4<bool,User*,time_t,std::string*,std::deque<std::string*>*>*>(ServerInstance->plugin()->getHook(\"CommandPre\"))->doUntilFalse(user, time, command_name, command_args))\n    {\n      static_cast<Hook4<void,User*,time_t,std::string*,std::deque<std::string*>*>*>(ServerInstance->plugin()->getHook(\"CommandPost\"))->doAll(user, time, command_name, command_args);\n    }\n\n    delete command_name;\n    while (command_args->size())\n    {\n      delete command_args->back();\n      command_args->pop_back();\n    }\n    delete command_args;\n\n    return false;\n  }\n  else\n  {\n    return true;\n  }\n}\n"
  },
  {
    "path": "src/plugins/command/command.h",
    "content": "#include <string>\n\n#include \"mineserver.h\"\n#include \"user.h\"\n\n#ifndef _PLUGIN_COMMAND_H\n#define _PLUGIN_COMMAND_H\n\n#define PLUGIN_COMMAND_VERSION 0.1\n\nclass P_Command\n{\npublic:\n  P_Command(Mineserver* mineserver);\n  ~P_Command();\n  static bool callbackChatPre(User* user, time_t time, std::string data);\nprivate:\n  Mineserver* m_mineserver;\n};\n\n#endif\n"
  },
  {
    "path": "src/protocol.cpp",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n\n#include \"extern.h\"\n#include \"config.h\"\n#include \"constants.h\"\n#include \"mob.h\"\n#include \"tools.h\"\n#include \"utf8.h\"\n#include \"inventory.h\"\n#include \"mineserver.h\"\n#include \"logger.h\"\n#include \"protocol.h\"\n\n#ifdef PROTOCOL_ENCRYPTION\nPacket Protocol::encryptionRequest()\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ENCRYPTION_REQUEST) << ServerInstance->serverID \n  << MS_VarInt((int64_t)ServerInstance->publicKey.size());\n  ret.addToWrite((uint8_t*)ServerInstance->publicKey.c_str(),ServerInstance->publicKey.size());\n  ret << MS_VarInt((int64_t)ServerInstance->encryptionBytes.size());\n  ret.addToWrite((uint8_t*)ServerInstance->encryptionBytes.c_str(),ServerInstance->encryptionBytes.size());\n  return ret;\n}\n#endif\n\nPacket Protocol::openWindow(uint8_t windowId, std::string windowType, std::string title_json, int8_t numberOfSlots, int32_t EID)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_OPEN_WINDOW) << windowId << windowType << title_json << numberOfSlots;\n  if (windowType == INVENTORYTYPE_HORSE)\n    ret << EID;\n  return ret;\n}\n\nPacket Protocol::windowProperty(uint8_t windowId, int16_t property, int16_t value)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_WINDOW_PROPERTY) << windowId << property << value;\n  return ret;\n}\n\nPacket Protocol::confirmTransaction(uint8_t windowId, int16_t action_number, int8_t accepted)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_CONFIRM_TRANSACTION) << windowId << action_number << accepted;\n  return ret;\n}\n\nPacket Protocol::animation(int eid, int aid)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ANIMATION) << MS_VarInt((uint32_t)eid) << (int8_t)aid;\n  return ret;\n}\n\nPacket Protocol::updateSign(int32_t x, int32_t y, int32_t z, \n                          std::string line1, std::string line2, std::string line3, std::string line4)\n{\n  Packet ret;      \n  ret << MS_VarInt((uint32_t)PACKET_OUT_UPDATE_SIGN) \n    << (uint64_t)((((uint64_t)x & 0x3FFFFFF) << 38) | (((uint64_t)y & 0xFFF) << 26) | ((uint64_t)z & 0x3FFFFFF))\n    << line1 << line2 << line3 << line4;\n  return ret;\n}\n\nPacket Protocol::openSignEditor(int32_t x, int32_t y, int32_t z)\n{\n  Packet ret;      \n  ret << MS_VarInt((uint32_t)PACKET_OUT_OPEN_SIGN_EDITOR) \n    << (uint64_t)((((uint64_t)x & 0x3FFFFFF) << 38) | (((uint64_t)y & 0xFFF) << 26) | ((uint64_t)z & 0x3FFFFFF));\n  return ret;\n}\n\nPacket Protocol::entityStatus(int eid, int aid)\n{\n  Packet ret;\n  ret << (int8_t)PACKET_OUT_ENTITY_STATUS << (int32_t)eid << (int8_t)aid;\n  return ret;\n}\n\nPacket Protocol::entityMetadata(int eid, MetaData& metadata)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ENTITY_METADATA) << MS_VarInt((uint32_t)eid) << metadata;\n  return ret;\n}\n\nPacket Protocol::entityVelocity(int eid, int16_t vel_x, int16_t vel_y,int16_t vel_z)\n{\n  Packet ret;\n  ret << (int8_t)PACKET_OUT_ENTITY_VELOCITY << (int32_t)eid << vel_x << vel_y << vel_z;\n  return ret;\n}\n\nPacket Protocol::slot(const Item &item)\n{\n  Packet ret;\n  ret << (int16_t)item.getType();\n  if(item.getType() != -1) {\n    ret << (int8_t)item.getCount() << (int16_t)item.getHealth();\n    // ToDo: item extra data\n    /*\n    if(item_data != NULL) {\n      ret << item_data_size;\n      ret.addToWrite(item_data, item_data_size);\n    } else {\n      ret << (int16_t)0;\n    }\n    */\n    ret << (int8_t)0;\n  }\n  return ret;\n}\n\nPacket Protocol::setSlot(int8_t window_id, int16_t slotId, Item& item)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_SET_SLOT) << window_id << slotId;\n  ret << Protocol::slot(item);\n  return ret;\n}\n\nPacket Protocol::entityEquipment(int32_t eid, int16_t slot, Item& item)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ENTITY_EQUIPMENT) << MS_VarInt((uint32_t)eid) << (int16_t)slot\n      << Protocol::slot(item);\n  return ret;\n}\n\nPacket Protocol::mobSpawn(int eid, int8_t type, double x, double y, double z, int yaw, int pitch, int head_yaw, MetaData& metadata)\n{\n  // Warning! This converts absolute double coordinates to absolute integer coordinates!\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_SPAWN_MOB) << MS_VarInt((uint32_t)eid) << (int8_t)type\n      << (int32_t)(x * 32) << (int32_t)(y * 32) << (int32_t)(z * 32)\n      << (int8_t)yaw << (int8_t)pitch << (int8_t)head_yaw << (int16_t)0 \n      << (int16_t)0 << (int16_t)0 << (int8_t)0 << (int8_t)0 << metadata;\n  return ret;\n}\n\nPacket Protocol::mobSpawn(Mob& mob)\n{\n  return Protocol::mobSpawn(mob.UID, mob.type, mob.x, mob.y, mob.z, mob.yaw, mob.pitch, mob.head_yaw, mob.metadata);\n}\n\nPacket Protocol::destroyEntity(uint32_t eid)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_DESTROY_ENTITIES) << MS_VarInt((uint32_t)1) << MS_VarInt((uint32_t)eid);\n  return ret;\n}\n\nPacket Protocol::entityTeleport(uint32_t eid, double x, double y, double z, float yaw, float pitch)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ENTITY_TELEPORT) << MS_VarInt((uint32_t)eid)\n      << (int32_t)(x * 32) << (int32_t)(y * 32) << (int32_t)(z * 32)\n      << (int8_t)angleToByte(yaw) << (int8_t)angleToByte(pitch) << (int8_t)1;\n  return ret;\n}\nPacket Protocol::entityRelativeMove(uint32_t eid, int8_t x, int8_t y, int8_t z, int8_t onGround)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ENTITY_RELATIVE_MOVE) << MS_VarInt((uint32_t)eid) << x << y << z << onGround;\n  return ret;\n}\n\nPacket Protocol::entityTeleport(uint32_t eid, const position& pos)\n{\n  return Protocol::entityTeleport(eid, pos.x, pos.y, pos.z, pos.yaw, pos.pitch);\n}\n\nPacket Protocol::namedSoundEffect(std::string name, int32_t x, int32_t y, int32_t z, float volume, int8_t pitch)\n{\n  Packet ret;\n  ret << (int8_t)PACKET_OUT_SOUND_EFFECT << name << x << y << z << volume << pitch;\n  return ret;\n}\n\nPacket Protocol::entityHeadLook(int eid, int head_yaw)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ENTITY_HEAD_LOOK) << MS_VarInt((uint32_t)eid) << (int8_t)head_yaw;\n  return ret;\n}\n\nPacket Protocol::attachEntity(int32_t entity, int32_t vehicle, bool leash)\n{\n  Packet ret;\n  ret << (int8_t)PACKET_OUT_ATTACH_ENTITY << (int32_t)entity << (int32_t)vehicle << (int8_t)leash;\n  return ret;\n}\n\nPacket Protocol::entityLook(int eid, int yaw, int pitch)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_ENTITY_LOOK) << MS_VarInt((uint32_t)eid) << (int8_t)yaw << (int8_t)pitch << (int8_t)1;\n  return ret;\n}\n\nPacket Protocol::entityLook(int eid, float yaw, float pitch)\n{\n  return entityLook(eid, angleToByte(yaw), angleToByte(pitch));\n}\n\nPacket Protocol::entityRelativeMove(uint32_t eid, double dx, double dy, double dz, int8_t onGround)\n{\n  return Protocol::entityRelativeMove(eid, (int8_t)(dx * 32), (int8_t)(dy * 32), (int8_t)(dz * 32), onGround);\n}\n    \nPacket Protocol::entityLookRelativeMove(int eid, double dx, double dy, double dz, int yaw, int pitch)\n{\n  Packet ret;\n  ret << (int8_t)PACKET_OUT_ENTITY_LOOK_RELATIVE_MOVE << (int32_t)eid\n      << (int8_t)(dx * 32) << (int8_t)(dy * 32) << (int8_t)(dz * 32)\n      << (int8_t)yaw << (int8_t)pitch;\n  return ret;\n}\n\nPacket Protocol::setCompression(int threshold)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_SET_COMPRESSION) << MS_VarInt((uint32_t)threshold);\n  return ret;\n}\n\nPacket Protocol::loginSuccess(std::string uuid, std::string username)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_LOGIN_SUCCESS) << uuid\n      << username;\n  return ret;\n}\n\n//ToDo: remember gamemode for players\nPacket Protocol::joinGame(int eid, int8_t gamemode)\n{\n\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_JOIN_GAME) << (int32_t)eid\n      << (int8_t)gamemode << (int8_t)0 /* dimension */\n      << (int8_t)2 /*difficulty */ << (int8_t)ServerInstance->config()->iData(\"system.user_limit\")\n      << std::string(\"default\") << (int8_t)0; /* reduced debug info */\n  return ret;\n}\n\nPacket Protocol::playerAbilities(uint8_t flags, float flying_speed, float walking_speed)\n{\n\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_PLAYER_ABILITIES) << flags\n      << flying_speed << walking_speed;\n  return ret;\n}\n\nPacket Protocol::spawnPosition(int x, int y, int z)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_SPAWN_POSITION) << \n  (uint64_t)((((uint64_t)x & 0x3FFFFFF) << 38) | (((uint64_t)y & 0xFFF) << 26) | ((uint64_t)z & 0x3FFFFFF));\n  return ret;\n}\n\n//ToDo: use age of the world field somewhere\nPacket Protocol::timeUpdate(int64_t time, int64_t  ageOfTheWorld)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_TIME_UPDATE) << (int64_t)ageOfTheWorld << (int64_t)time;\n  return ret;\n}\n\nPacket Protocol::disconnect(std::string msg)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_DISCONNECT) << msg;\n  return ret;\n}\n\nPacket Protocol::spawnPlayer(int eid, uint8_t *uuid, std::string &nick, float health, double x, double y, double z, float yaw, float pitch, int16_t item)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_SPAWN_PLAYER) << MS_VarInt((uint32_t)eid);\n  for (int i = 0; i < 16; i++) ret << uuid[i];\n  ret << (int32_t)(x*32)<<(int32_t)(y * 32) << (int32_t)(z * 32)\n      << (int8_t)angleToByte(yaw) << (int8_t)angleToByte(pitch)\n      << (int16_t)item\n      << (uint8_t)((4<<5) | 2) // Metadata, type 4 = string, index 6 = name tag\n      << nick\n      << (uint8_t)((3<<5) | 6) // Metadata, type 3 = float, index 6 = health\n      << health\n      << (int8_t)127;\n  return ret;\n}\n\nPacket Protocol::spawnPlayer(int eid, uint8_t *uuid, std::string &nick, float health, position& pos, int16_t item){\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_SPAWN_PLAYER) << MS_VarInt((uint32_t)eid);\n  for (int i = 0; i < 16; i++) ret << uuid[i];\n  ret << (int32_t)(pos.x*32)<<(int32_t)(pos.y * 32) << (int32_t)(pos.z * 32)\n      << (int8_t)angleToByte(pos.yaw) << (int8_t)angleToByte(pos.pitch)\n      << (int16_t)item\n      << (uint8_t)((4<<5) | 2) // Metadata, type 4 = string, index 6 = name tag\n      << nick\n      << (uint8_t)((3<<5) | 6) // Metadata, type 3 = float, index 6 = health\n      << health\n      << (int8_t)127;\n  return ret;\n}\n\nPacket Protocol::PlayerListItemAddSingle(uint8_t *uuid, std::string &nick, int8_t gamemode, int ping, std::vector<UserProperty> &properties){\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_PLAYER_LIST_ITEM) \n      << MS_VarInt((uint32_t)0) // Action: Add\n      << MS_VarInt((uint32_t)1); // Number of Players\n  for (int i = 0; i < 16; i++) ret << uuid[i];\n  ret << nick\n      << MS_VarInt((uint32_t)properties.size()); // Number Of Properties\n  for (UserProperty prop : properties)\n  {\n    ret << prop.name << prop.value << (uint8_t)(prop.signature != \"\")?1:0;\n    if (prop.signature != \"\")\n    {\n      ret << prop.signature;\n    }\n  }\n  ret << MS_VarInt((uint32_t)gamemode)\n      << MS_VarInt((uint32_t)ping)\n      << (uint8_t)0; // Has Display Name\n  return ret;\n}\n\nPacket Protocol::PlayerListItemRemoveSingle(uint8_t *uuid){\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_PLAYER_LIST_ITEM) \n      << MS_VarInt((uint32_t)4) // Action: Remove\n      << MS_VarInt((uint32_t)1); // Number of Players\n  for (int i = 0; i < 16; i++) ret << uuid[i];\n  return ret;\n}\n\nPacket Protocol::spawnObject(int eid, int8_t object_type, int32_t x, int32_t y, int32_t z, int objectData, int16_t speed_x, int16_t speed_y,int16_t speed_z, float yaw, float pitch)\n{\n  Packet  pkt; \n  pkt << MS_VarInt((uint32_t)PACKET_OUT_SPAWN_OBJECT) << MS_VarInt((uint32_t)eid)\n      << (int8_t)object_type\n      << x << y << z \n      << angleToByte(yaw) << angleToByte(pitch)\n      << (int32_t)objectData;\n      if(objectData)\n      {\n        pkt << (int16_t)speed_x << (int16_t)speed_y << (int16_t)speed_z;\n      }\n  return pkt;\n}\n\nPacket Protocol::entity(int eid)\n{\n  Packet  pkt; \n  pkt << MS_VarInt((uint32_t)PACKET_OUT_ENTITY) << MS_VarInt((uint32_t)eid);\n  return pkt;\n}\n\nPacket Protocol::collectItem(int itemEid, int eid)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_COLLECT_ITEM) << MS_VarInt((uint32_t)itemEid) << MS_VarInt((uint32_t)eid);\n  return ret;\n}\n\nPacket Protocol::blockAction(int32_t x, int16_t y, int32_t z, int8_t byte1, int8_t byte2, int16_t blockid)\n{\n  Packet ret;\n  ret << (int8_t)PACKET_OUT_BLOCK_ACTION \n  << (uint64_t)((((uint64_t)x & 0x3FFFFFF) << 38) | (((uint64_t)y & 0xFFF) << 26) | ((uint64_t)z & 0x3FFFFFF)) \n  << byte1 << byte2 << MS_VarInt((uint32_t)blockid);\n  return ret;\n}\n\nPacket Protocol::playerPositionAndLook(double x, double y, double z, float yaw, float pitch, uint8_t flags)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_PLAYER_POSITION_AND_LOOK) << x << y << z << yaw << pitch << flags;\n  return ret;\n}\n\nPacket Protocol::respawn(int32_t dimension, int8_t difficulty,int8_t game_mode, std::string level_type)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_RESPAWN) << dimension << difficulty << game_mode << level_type;\n  return ret;\n}\n\nPacket Protocol::updateHealth(int health, int food)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_UPDATE_HEALTH) << (float)health << MS_VarInt((uint32_t)food) << (float)5.0;\n  return ret;\n}\n\nPacket Protocol::keepalive(int32_t time)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_KEEP_ALIVE) << MS_VarInt((uint32_t)time);\n  return ret;\n}\n\nPacket Protocol::playerlist()\n{\n  Packet ret;\n\n  //ToDo: Add admin/moderator coloring\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  { \n    if((*it)->nick.length() > 0)\n    {\n      ret << (int8_t)PACKET_OUT_PLAYER_LIST_ITEM << (*it)->nick << (int8_t)1 << (int16_t)0;\n    }\n  }      \n  return ret;\n}\nPacket Protocol::gameMode(int8_t reason, float value){\n  Packet ret;\n  ret<< MS_VarInt((uint32_t)PACKET_OUT_CHANGE_GAME_STATE) << reason << value;\n  return ret;\n}\n\nPacket Protocol::chatMsg(const std::string& msg)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_CHAT_MESSAGE) << msg << (uint8_t)0;\n  return ret;\n}\n\nPacket Protocol::blockChange(int32_t x, int32_t y, int32_t z, int16_t blocktype, int8_t meta)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_BLOCK_CHANGE)\n  << (uint64_t)((((uint64_t)x & 0x3FFFFFF) << 38) | (((uint64_t)y & 0xFFF) << 26) | ((uint64_t)z & 0x3FFFFFF)) \n  << MS_VarInt((uint32_t)(blocktype << 4) | meta);\n  return ret;\n}\n\nPacket Protocol::tabComplete(const std::vector<std::string> &msgs)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_TAB_COMPLETE) << MS_VarInt((uint32_t)msgs.size());\n  for(std::string const& msg : msgs)\n  {\n    ret << msg;\n  }\n  return ret;\n}\n\nPacket Protocol::explosion(float x, float y, float z, float radius, std::vector<vec>& record, float velocity_x, float velocity_y, float velocity_z)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_EXPLOSION) << x << y << z << radius;\n  ret << (int32_t)record.size();\n  for(vec const& pos : record)\n  {\n    ret << (int8_t)pos.x() << (int8_t)pos.y() <<(int8_t)pos.z();\n  }\n  ret << velocity_x << velocity_y << velocity_z;\n  return ret;\n}\n\n Packet Protocol::windowItems(uint8_t windowID, std::vector<Item>& slots)\n{\n  Packet ret;\n  ret << MS_VarInt((uint32_t)PACKET_OUT_WINDOW_ITEMS) << windowID;\n  ret << (int16_t)slots.size();\n  for(Item const& slot : slots)\n  {\n    ret << Protocol::slot(slot);\n  }\n  return ret;\n}\n\n Packet Protocol::chunkDataUnload(int32_t chunk_x, int32_t chunk_z)\n {\n  Packet ret;  \n  ret << MS_VarInt((uint32_t)PACKET_OUT_MAP_CHUNK) << chunk_x << chunk_z;\n  ret << (uint8_t)1 << (int16_t)0 << MS_VarInt((uint32_t)0);\n  return ret;\n }\n"
  },
  {
    "path": "src/protocol.h",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _PROTOCOL_H\n#define _PROTOCOL_H\n\n#include \"extern.h\"\n#include \"config.h\"\n#include \"constants.h\"\n#include \"mob.h\"\n#include \"tools.h\"\n#include \"utf8.h\"\n#include \"inventory.h\"\n#include \"mineserver.h\"\n#include \"logger.h\"\n\n/* This file introduces a basic abstraction over raw protocol packets format.\n * This is needed for varuios protocol updates - we need to change the raw format\n * only in one place. \n * The implementation is totally in header to be inlined and optimized out.\n *\n * Maybe we need to add a lot of asserts there?\n */\n\nclass Protocol\n{\n  public:\n\n    #ifdef PROTOCOL_ENCRYPTION\n    static Packet encryptionRequest();\n    #endif\n\n    static Packet openWindow(uint8_t windowId, std::string windowType, std::string title_json, int8_t numberOfSlots, int32_t EID = 0);\n\n    static Packet windowProperty(uint8_t windowId, int16_t property, int16_t value);\n\n    static Packet confirmTransaction(uint8_t windowId, int16_t action_number, int8_t accepted);\n\n    static Packet animation(int eid, int aid);\n\n    static Packet updateSign(int32_t x, int32_t y, int32_t z, \n                             std::string line1, std::string line2, std::string line3, std::string line4);\n\n    static Packet openSignEditor(int32_t x, int32_t y, int32_t z);\n\n    static Packet entityStatus(int eid, int aid);\n\n    static Packet entityMetadata(int eid, MetaData& metadata);\n\n    static Packet entityVelocity(int eid, int16_t vel_x, int16_t vel_y,int16_t vel_z);\n    static Packet slot(const Item &item);\n\n    static Packet setSlot(int8_t window_id, int16_t slotId, Item& item);\n\n    static Packet entityEquipment(int32_t eid, int16_t slot, Item& item);\n\n    static Packet mobSpawn(int eid, int8_t type, double x, double y, double z, int yaw, int pitch, int head_yaw, MetaData& metadata);\n\n    static Packet mobSpawn(Mob& mob);\n\n    static Packet destroyEntity(uint32_t eid);\n\n    static Packet entityTeleport(uint32_t eid, double x, double y, double z, float yaw, float pitch);\n    static Packet entityRelativeMove(uint32_t eid, int8_t x, int8_t y, int8_t z, int8_t onGround);\n\n    static Packet entityTeleport(uint32_t eid, const position& pos);\n\n    static Packet namedSoundEffect(std::string name, int32_t x, int32_t y, int32_t z, float volume, int8_t pitch);\n\n    static Packet entityHeadLook(int eid, int head_yaw);\n\n    static Packet attachEntity(int32_t entity, int32_t vehicle, bool leash = 0);\n\n    static Packet entityLook(int eid, int yaw, int pitch);\n\n    static Packet entityLook(int eid, float yaw, float pitch);\n\n    static Packet entityRelativeMove(uint32_t eid, double dx, double dy, double dz, int8_t onGround);\n    \n    static Packet entityLookRelativeMove(int eid, double dx, double dy, double dz, int yaw, int pitch);\n\n    static Packet setCompression(int threshold);\n\n    static Packet loginSuccess(std::string uuid, std::string username);\n\n    //ToDo: remember gamemode for players\n    static Packet joinGame(int eid, int8_t gamemode = 0);\n\n    static Packet playerAbilities(uint8_t flags, float flying_speed, float walking_speed);\n\n    static Packet spawnPosition(int x, int y, int z);\n\n    //ToDo: use age of the world field somewhere\n    static Packet timeUpdate(int64_t time, int64_t  ageOfTheWorld = 0);\n    static Packet disconnect(std::string msg);\n\n    static Packet spawnPlayer(int eid, uint8_t *uuid, std::string &nick, float health, double x, double y, double z, float yaw, float pitch, int16_t item);\n\n    static Packet spawnPlayer(int eid, uint8_t *uuid, std::string &nick, float health, position& pos, int16_t item);\n\n    static Packet PlayerListItemAddSingle(uint8_t *uuid, std::string &nick, int8_t gamemode, int ping, std::vector<UserProperty> &properties);\n\n    static Packet PlayerListItemRemoveSingle(uint8_t *uuid);\n\n    static Packet spawnObject(int eid, int8_t object_type, int32_t x, int32_t y, int32_t z, int objectData, int16_t speed_x = 0, int16_t speed_y = 0,int16_t speed_z = 0, float yaw = 0.0, float pitch = 0.0);\n\n    static Packet entity(int eid);\n\n    static Packet collectItem(int itemEid, int eid);\n\n    static Packet blockAction(int32_t x, int16_t y, int32_t z, int8_t byte1, int8_t byte2, int16_t blockid);\n\n    static Packet playerPositionAndLook(double x, double y, double z, float yaw, float pitch, uint8_t flags);\n\n    static Packet respawn(int32_t dimension = 0, int8_t difficulty=1,int8_t game_mode=0, std::string level_type=\"default\");\n\n    static Packet updateHealth(int health, int food=15);\n\n    static Packet keepalive(int32_t time);\n\n    static Packet playerlist();\n    static Packet gameMode(int8_t reason, float value);\n\n    static Packet chatMsg(const std::string& msg);\n\n    static Packet blockChange(int32_t x, int32_t y, int32_t z, int16_t blocktype, int8_t meta);\n\n    static Packet tabComplete(const std::vector<std::string> &msgs);\n\n    static Packet explosion(float x, float y, float z, float radius, std::vector<vec>& record, float velocity_x, float velocity_y, float velocity_z);\n\n    static Packet windowItems(uint8_t windowID, std::vector<Item>& slots);\n\n    static Packet chunkDataUnload(int32_t chunk_x, int32_t chunk_z);\n};\n#endif\n"
  },
  {
    "path": "src/random.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n//#include <iostream>\n//#include <iomanip>\n#include <limits>\n#include <ctime>\n#ifdef WIN32\n#define _WINSOCKAPI_\n#define NOMINMAX\n#include <windows.h>\n#include <wincrypt.h>\n#else\n#include <fstream>\n#endif\n#include \"mineserver.h\"\n#include \"random.h\"\n\nseed_type prng_seed = 0;\n\nMyRNG prng;\n\nMyUniform m_uniformUINT(0, std::numeric_limits<MyUniform::result_type>::max());\n\nvoid initPRNG()\n{\n  bool seedsuccess = false;\n\n#ifdef WIN32\n  HCRYPTPROV hCryptProv;\n  BYTE* pbData = reinterpret_cast<BYTE*>(&prng_seed);\n\n  if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0))\n  {\n    if (CryptGenRandom(hCryptProv, sizeof(prng_seed), pbData))\n    {\n      seedsuccess = true;\n    }\n    CryptReleaseContext(hCryptProv, 0);\n  }\n#else\n  std::ifstream urandom(\"/dev/urandom\");\n  if (urandom)\n  {\n    urandom.read(reinterpret_cast<char*>(&prng_seed), sizeof(prng_seed));\n    seedsuccess = true;\n  }\n#endif\n\n  if (!seedsuccess)\n  {\n    prng_seed = static_cast<seed_type>(std::time(NULL));\n  }\n\n  //std::cout << \"Seeding the PRNG with: 0x\" << std::hex << std::uppercase << std::setfill('0')\n  //          << std::setw(2 * sizeof(MyRNG::result_type)) << prng_seed << std::endl;\n\n  prng.seed(prng_seed);\n}\n\ndouble uniform01()\n{\n  return double(m_uniformUINT(prng)) / double(std::numeric_limits<MyUniform::result_type>::max());\n}\n"
  },
  {
    "path": "src/random.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef MY_RANDOM_H\n#define MY_RANDOM_H\n\n/// <Eximius> @MY_RANDOM_H : There seemed to be a conflict with another define of unknown origin\n///          (don't use names starting with underscores... compilers are stl libraries like that too)\n\n\n#include <random>\n\n// This is our core PRNG engine. The Mersenne Twister is both fast and good.\n\ntypedef std::mt19937 MyRNG;\n/**\n#if (defined(__GNUC__))\n * GCC TR1 implementation has a bug, which doesn't produce a correct\n * distribution on 64bit-machines when using mt19937 and uniform_int for 64bit\n * integers together. Because GCC TR1 implementation is frozen, this bug won't\n * be fixed and we need to limit uniform_int to 32bit integer\ntypedef std::uniform_int<uint32_t> MyUniform;\n#else\ntypedef std::uniform_int<MyRNG::result_type> MyUniform;\n#endif\n*/ /// not sure! but my right brain says to wing it\n\ntypedef std::uniform_int_distribution<MyRNG::result_type> MyUniform;\n\n// Ideally we would have \"typedef MyRNG::result_type seed_type\", but mt19937 is broken.\n// Set this to whatever MyRNG::seed(seed_type) needs to be.\n\ntypedef unsigned long int seed_type;\n\n\n/// Global objects: The PRNG, its seed value, and a 32-bit uniform distribution.\n/// Other distribution objects are instantiated locally as needed.\n\nextern MyRNG prng;\nextern seed_type prng_seed;\nextern MyUniform m_uniformUINT;\n\n\n/// A function to initialize the PRNG.\n\nvoid initPRNG();\n\n\n/// Some global accessor functions for useful distributions.\n\ninline MyRNG::result_type uniformUINT()\n{\n  return m_uniformUINT(prng);\n}\n\ninline MyRNG::result_type uniformUINT(MyUniform::result_type min, MyUniform::result_type max)\n{\n  MyUniform uni(min, max);\n  return uni(prng);\n}\n\ninline uint8_t uniformUINT8(uint8_t min, uint8_t max)\n{\n  std::uniform_int_distribution<uint16_t> uni(min, max);\n  return uint8_t(uni(prng));\n}\n\ndouble uniform01();\n\n#define MAKE_UNIFORM_DIST(A,B) static inline unsigned int uniform_ ## A ## _ ## B()\\\n{\\\n  MyUniform uni(A, B);\\\n  return uni(prng);\\\n}\\\n\n#endif\n"
  },
  {
    "path": "src/redstoneSimulation.cpp",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n#include \"redstoneSimulation.h\"\n#include \"logger.h\"\n#include \"constants.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"protocol.h\"\n\n// Main loop\nbool RedstoneSimulation::update()\n{\n  if (!enabled)\n  {\n    return true;\n  }\n\n  uint32_t listSize = simList.size();\n\n  std::vector<uint32_t> toRemove;\n\n  for (uint32_t simIt = 0; simIt < listSize; simIt++)\n  {\n    uint8_t curBlock = simList[simIt].id;\n    uint8_t curPower = simList[simIt].power;\n    uint8_t newPower = curPower;\n    vec pos = simList[simIt].pos;\n    //ToDo: handle removed\n\n    for (int i = 0; i <= 5; i++)\n    {\n      if(simList[simIt].direction == i) continue;\n      vec local(pos);\n      uint8_t disableDir = -1;\n      switch (i)\n      {\n      case 0:\n        local += vec(0, -1, 0);\n        disableDir = 5;\n        break;\n      case 1:\n        local += vec(1, 0, 0);\n        disableDir = 2;\n        break;\n      case 2:\n        local += vec(-1, 0, 0);\n        disableDir = 1;\n        break;\n      case 3:\n        local += vec(0, 0, 1);\n        disableDir = 4;\n        break;\n      case 4:\n        local += vec(0, 0, -1);\n        disableDir = 3;\n        break;\n      case 5:\n        local += vec(0,1,0);\n        disableDir = 0;\n        break;\n      default:\n        break;\n      }\n\n      uint8_t block, meta;\n      ServerInstance->map(map)->getBlock(local, &block, &meta);\n      //Skip air blocks\n      if(block != BLOCK_AIR)\n      {\n        if(curBlock == BLOCK_REDSTONE_WIRE)\n        {\n          if(block == BLOCK_REDSTONE_TORCH_ON)\n          {\n            newPower = 15;\n          }\n          if(block == BLOCK_REDSTONE_WIRE)\n          {\n            if(meta-1 > newPower)\n            {\n              newPower = meta-1;\n            }\n          }\n        }\n\n        if(block == BLOCK_REDSTONE_WIRE)\n        {\n          if(meta < curPower-1)\n          {\n            simList.push_back(RedstoneSim(BLOCK_REDSTONE_WIRE,local,curPower-1, disableDir));\n            listSize++;\n            ServerInstance->map(map)->setBlock(local, block, curPower-1);\n            ServerInstance->map(map)->sendBlockChange(local, block, curPower-1);\n          }\n        }\n        else if(curBlock == BLOCK_REDSTONE_WIRE || curBlock == BLOCK_REDSTONE_TORCH_ON)\n        {\n          simList.push_back(RedstoneSim(block,local,curPower-1, disableDir));\n          listSize++;\n        }\n\n      }\n\n      //We got power from neighbouring blocks\n      if(newPower > curPower && curBlock == BLOCK_REDSTONE_WIRE)\n      {\n          simList.push_back(RedstoneSim(curBlock,pos,newPower, i));\n          listSize++;\n          ServerInstance->map(map)->setBlock(pos, curBlock, newPower);\n          ServerInstance->map(map)->sendBlockChange(pos, curBlock, newPower);\n      }\n      \n    }\n    //Add queue to be removed\n    toRemove.push_back(simIt);\n\n  }\n\n  //Remove from the simulation\n  listSize = toRemove.size();\n  for (int32_t simIt = listSize-1; simIt >= 0; simIt--)\n  {\n    simList.erase(simList.begin()+toRemove[simIt]);\n  }\n\n\n  return true;\n}\n\n\n// Add world simulation\nbool RedstoneSimulation::addSimulation(vec pos)\n{  \n  if (!enabled)\n  {\n    return false;\n  }\n\n  uint8_t block;\n  uint8_t meta;\n  ServerInstance->map(map)->getBlock(pos, &block, &meta);\n\n  //Removed torch/wire/etc\n  if(block == BLOCK_AIR)\n  {\n\n  }\n\n  uint8_t power = 0;\n\n\n  switch(block)\n  {\n    case BLOCK_REDSTONE_TORCH_ON:\n      power = 16;\n      break;\n    default:\n      break;\n  }\n  RedstoneSim simulationBlock(block, pos, power);\n\n  // Dont add duplicates\n  for (std::vector<RedstoneSim>::iterator simIt = simList.begin(); simIt != simList.end(); simIt++)\n  {\n    vec itpos = simIt->pos;\n    if (itpos.x() == pos.x() && itpos.y() == pos.y() && itpos.z() == pos.z())\n    {\n      return false;\n    }\n  }\n\n  simList.push_back(simulationBlock);\n\n\n  return true;\n}\n\nRedstoneSimulation::Power RedstoneSimulation::getPower(int32_t x, int16_t y, int32_t z)\n{\n  uint8_t block;\n  uint8_t meta = 0;\n\n  // Check block type\n  if (!ServerInstance->map(map)->getBlock(x + 1, y, z, &block, &meta))\n  {\n    return POWER_NONE;\n  }\n  if (!isBlockSolid(block))\n  {\n    return POWER_NONE;\n  }\n\n  //\n  // Check for switches or wires on sides\n  //\n\n  // North\n  if (!ServerInstance->map(map)->getBlock(x + 1, y, z, &block, &meta))\n  {\n    return POWER_NONE;\n  }\n\n  if ((block == BLOCK_STONE_BUTTON || block == BLOCK_LEVER) && (meta & 0x4) == 0x4 && (meta & 0x8) == 0x8)\n  {\n    return POWER_NORMAL;\n  }\n  else if (block == BLOCK_REDSTONE_WIRE && meta != 0)\n  {\n    // TODO: Check if wire ends here\n    return POWER_WEAK;\n  }\n\n  // South\n  if (!ServerInstance->map(map)->getBlock(x - 1, y, z, &block, &meta))\n  {\n    return POWER_NONE;\n  }\n\n  if ((block == BLOCK_STONE_BUTTON || block == BLOCK_LEVER) && (meta & 0x3) == 0x3 && (meta & 0x8) == 0x8)\n  {\n    return POWER_NORMAL;\n  }\n  else if (block == BLOCK_REDSTONE_WIRE && meta != 0)\n  {\n    return POWER_WEAK;\n  }\n\n  // East\n  if (!ServerInstance->map(map)->getBlock(x, y, z + 1, &block, &meta))\n  {\n    return POWER_NONE;\n  }\n\n  if ((block == BLOCK_STONE_BUTTON || block == BLOCK_LEVER) && (meta & 0x1) == 0x1 && (meta & 0x8) == 0x8)\n  {\n    return POWER_NORMAL;\n  }\n  else if (block == BLOCK_REDSTONE_WIRE && meta != 0)\n  {\n    return POWER_WEAK;\n  }\n\n  // West\n  if (!ServerInstance->map(map)->getBlock(x, y, z - 1, &block, &meta))\n  {\n    return POWER_NONE;\n  }\n\n  if ((block == BLOCK_STONE_BUTTON || block == BLOCK_LEVER) && (meta & 0x2) == 0x2 && (meta & 0x8) == 0x8)\n  {\n    return POWER_NORMAL;\n  }\n  else if (block == BLOCK_REDSTONE_WIRE && meta != 0)\n  {\n    return POWER_WEAK;\n  }\n\n  \n  if (!ServerInstance->map(map)->getBlock(x, y + 1, z, &block, &meta))\n  {\n    return POWER_NONE;\n  }\n\n  // Switch or pressure plate on top of the block\n  if ((block == BLOCK_WOODEN_PRESSURE_PLATE || block == BLOCK_STONE_PRESSURE_PLATE) && (meta & 0x1) == 0x1)\n  {\n    return POWER_NORMAL;\n  }\n  else if (block == BLOCK_LEVER && (meta & 0x8) == 0x8)\n  {\n    return POWER_NORMAL;\n  }\n\n  // Wire on top of the block\n  else if (block == BLOCK_REDSTONE_WIRE && meta != 0)\n  {\n    return POWER_WEAK;\n  }\n\n  // Torch beneath the block\n  if (!ServerInstance->map(map)->getBlock(x, y - 1, z, &block, &meta))\n  {\n    return POWER_NONE;\n  }\n  if (block == BLOCK_REDSTONE_TORCH_ON)\n  {\n    return POWER_NORMAL;\n  }\n\n  // No power\n  return POWER_NONE;\n}\n\nbool RedstoneSimulation::isBlockSolid(const uint8_t block) {\n  switch (block)\n  {\n  case BLOCK_AIR:\n  case BLOCK_STONE_BUTTON:\n  case BLOCK_WATER:\n  case BLOCK_LAVA:\n  case BLOCK_STATIONARY_WATER:\n  case BLOCK_STATIONARY_LAVA:\n  case BLOCK_FIRE:\n  case BLOCK_LEVER:\n  case BLOCK_PORTAL:\n  case BLOCK_REDSTONE_WIRE:\n  case BLOCK_REDSTONE_TORCH_OFF:\n  case BLOCK_REDSTONE_TORCH_ON:\n  case BLOCK_SAPLING:\n  case BLOCK_SIGN_POST:\n  case BLOCK_GRASS:\n  case BLOCK_YELLOW_FLOWER:\n  case BLOCK_RED_ROSE:\n  case BLOCK_RED_MUSHROOM:\n  case BLOCK_BROWN_MUSHROOM:\n  case BLOCK_CROPS:\n  case BLOCK_TORCH:\n  case BLOCK_WOODEN_DOOR:\n  case BLOCK_FENCE_OAK:\n  case BLOCK_FENCE_BIRCH:\n  case BLOCK_FENCE_JUNGLE:\n  case BLOCK_FENCE_DARK_OAK:\n  case BLOCK_FENCE_ACACIA:\n  case BLOCK_WALL_SIGN:\n  case BLOCK_DOUBLE_STEP:\n  case BLOCK_IRON_DOOR:\n  case BLOCK_LADDER:\n  case BLOCK_SNOW:\n  case BLOCK_STEP:\n  case BLOCK_WOODEN_STAIRS:\n  case BLOCK_COBBLESTONE_STAIRS:\n    return false;\n    break;\n  default:\n    break;\n  }\n\n  return true;\n}"
  },
  {
    "path": "src/redstoneSimulation.h",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _REDSTONESIMULATION_H\n#define _REDSTONESIMULATION_H\n\n#include <stdint.h>\n#include <vector>\n#include \"vec.h\"\n#include \"tools.h\"\n\nclass RedstoneSimulation\n{\npublic:\n  enum Power { POWER_NONE, POWER_WEAK, POWER_NORMAL };\n\n  bool enabled;\n  int map;\n  bool addSimulation(vec pos);  \n  bool update();\n  Power getPower(int32_t x, int16_t y, int32_t z);\n\nprivate:\n  bool isBlockSolid(const uint8_t block);\n\n  enum { TYPE_WIRE, TYPE_TORCH, TYPE_BLOCK } SimType;\n  \n\n  struct RedstoneSim\n  {\n    uint8_t id;\n    vec pos;    \n    uint8_t power;\n    uint8_t direction;\n    Power charge;\n    RedstoneSim() {}\n    RedstoneSim(uint8_t id, vec pos, uint8_t power, uint8_t direction = -1, Power charge = POWER_NONE)\n    {\n      this->id    = id;\n      this->pos   = pos;\n      this->power = power;\n      this->direction = direction;\n      this->charge = charge;\n    }\n  };\n\n  std::vector<RedstoneSim> simList;\n\n};\n\n#endif\n"
  },
  {
    "path": "src/screenBase.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"screenBase.h\"\n#include <ctime>\n\nScreen::~Screen() {}\n\nstd::string Screen::currentTimestamp(bool seconds)\n{\n  time_t currentTime = time(NULL);\n  struct tm* Tm  = localtime(&currentTime);\n  std::string timeStamp(asctime(Tm));\n  timeStamp = timeStamp.substr(11, seconds ? 8 : 5);\n\n  return timeStamp;\n}"
  },
  {
    "path": "src/screenBase.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _SCREENBASE_H\n#define _SCREENBASE_H\n\n#include <string>\n#include <vector>\n#include \"logtype.h\"\n#include \"user.h\"\n\nclass Screen\n{\npublic:\n  virtual ~Screen(void) = 0;\n  virtual void init(std::string version) = 0;\n  virtual void log(LogType::LogType type, const std::string& source, const std::string& message) = 0;\n  virtual void updatePlayerList(std::vector<User*> users) = 0;\n  virtual void end() = 0;\n  virtual bool hasCommand() = 0;\n  virtual std::string getCommand() = 0;\n\nprotected:\n  std::string currentTimestamp(bool seconds);\n};\n\n#endif //_SCREENBASE_H\n"
  },
  {
    "path": "src/signalhandler.cpp",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"signalhandler.h\"\n#include \"mineserver.h\"\n#include \"constants.h\"\n#include \"logger.h\"\n#include <cstdio>\n#include <sstream>\n#include <iostream>\n#include <errno.h>\n#include <cstring>\n#include <cstdlib>\n#include <ctime>\n#include <signal.h>\n\n#ifndef SIGBREAK\n# define SIGBREAK 0 // Define this for unix systems\n#endif\nchar segv_location[255];\n\nvoid SignalHandler(int);\n\nvoid InitSignals()\n{\n  signal(SIGTERM, SignalHandler); // Justasic: Terminate signal sent by kill\n  #ifndef WIN32\n  signal(SIGKILL, SignalHandler); // Justasic: Kill signal sent by kill or kernel i think\n  signal(SIGHUP, SignalHandler);  // Justasic: Signal Hangup, typically used as a Config Rehash\n  #endif\n  signal(SIGINT, SignalHandler);  // Justasic: Signal Interrupt, usually a CTRL+C at console\n  signal(SIGBREAK, SignalHandler); // Justasic: ?? is this like sigterm?\n  #ifdef HAVE_BACKTRACE\n  signal(SIGSEGV, SignalHandler); // Justasic: Segmentation Fault signal, used for generating segfault reports\n  #endif\n}\n\nvoid HandleSegfault()\n{\n  // Justasic: We only use this statement if we have the capability of outputting a backtrace >.<\n  // Justasic: import some crap from another project i did this to.\n  #ifdef HAVE_BACKTRACE\n  void *array[10];\n  char **strings;\n  char tbuf[256];\n  size_t size;\n  time_t now = time(NULL);\n  size = backtrace(array, 10);\n  \n  #ifdef HAVE_SYS_UTSNAME_H\n  struct utsname uts;\n  if(uname(&uts) < 0)\n    std::cerr << \"uname() error: \" << strerror(errno) << std::endl;\n  #endif\n\n  strftime(tbuf, sizeof(tbuf), \"[%b %d %H:%M:%S %Y]\", localtime(&now));\n  std::stringstream slog;\n  slog << \"====================== Segmentation Fault ======================\" << std::endl;\n  slog << \"Please note that the Mineserver developers may ask you to re-run this under gdb!\" << std::endl;\n  slog << \"Time of crash: \" << tbuf << std::endl;\n  slog << \"Mineserver version: \" << VERSION_COMPLETE << std::endl;\n  #ifdef HAVE_SYS_UTSNAME_H\n  slog << \"System info: \" << uts.sysname << \" \" << uts.nodename << \" \" <<  uts.release << \" \" << uts.machine << std::endl;\n  slog << \"System version: \" << uts.version << std::endl;\n  #endif\n  slog << \"C++ Version: \" << __VERSION__ << std::endl; // GCC only? hmmnn\n  //slog << \"Socket Buffer: \" << LastBuf << std::endl; // Use this for the last thing sent/received by the socket.\n  slog << \"Location: \" << segv_location << std::endl;\n  strings = backtrace_symbols(array, size);\n\n  for(unsigned i=1; i < size; i++)\n    slog << \"BackTrace(\" << (i - 1) << \"): \" << strings[i] << std::endl;\n\n  free(strings);\n  slog << \"======================== END OF REPORT ==========================\" << std::endl;\n\n  // FIXME: Maybe log to a file somewhere instead of crashing?\n  std::cout << slog.str(); //Write to terminal.\n  std::cout.flush(); //Clear output\n  #endif // HAVE_BACKTRACE\n  \n  ServerInstance->stop();\n  exit(SIGSEGV); // Exit so we're not still running\n}\n\n// TODO: On signal event: close active connections, save world, etc.\nvoid SignalHandler(int sig)\n{\n  switch(sig)\n  {\n\n#ifdef HAVE_BACKTRACE\n    case SIGSEGV:\n      // Justasic: You can stop SIGSEGV's but I HIGHLY recommend against it unless you have good reason to.\n      // Justasic: as that can cause stack corruption and all kinds of bad things. if you do, use setjmp >.>\n      HandleSegfault();\n      break;\n#endif\n    #ifndef WIN32\n    case SIGHUP:\n      signal(sig, SIG_IGN);\n      /* TODO: Rehash a config? hmmnn */\n      LOG2(INFO, \"Received SIGHUP, rehashing..\");\n      break;\n    case SIGPIPE:\n      // Justasic: Ignore sigpipe since it just gets in the way.\n      signal(sig, SIG_IGN);\n      break;\n    case SIGKILL:\n    #endif\n    case SIGINT:    \n    case SIGBREAK:\n    case SIGTERM:\n      signal(sig, SIG_IGN);\n      #ifndef WIN32\n      signal(SIGHUP, SIG_IGN);\n      #endif\n      LOG2(INFO, \"Received SIGTERM, Exiting..\");\n      ServerInstance->stop();\n      break;\n    default:\n      static_cast<void>(0); // TODO: fix this to do something useful?\n  }\n}"
  },
  {
    "path": "src/signalhandler.h",
    "content": "/*\n  Copyright (c) 2012, The Mineserver Project\n  All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef SIGNAL_H\n#define SIGNAL_H\n\n// Segfault buffer\nextern char segv_location[255];\n\n// Initialize our signals.\nextern void InitSignals();\n\n// Use this macro for segfault specific locations\n#define SET_SEGV_LOCATION() snprintf(segv_location, sizeof(segv_location), \"%s %d %s\", __FILE__, __LINE__, __PRETTY_FUNCTION__);\n\n// Use this one to clear it\n#define CLEAR_SEGV_LOCATION() segv_location[0]='\\0';\n\n#endif"
  },
  {
    "path": "src/sockets.cpp",
    "content": "/*\n   Copyright (c) 2013, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifdef _WIN32\n#include <cstdlib>\n#include <winsock2.h>\ntypedef int socklen_t;\n#else\n#include <netdb.h>   // for gethostbyname()\n#include <netinet/tcp.h> // for TCP constants\n#endif\n\n#include <string>\n\n#include <sys/stat.h>\n#include <fstream>\n\n#include <cerrno>\n#include <sstream>\n#include <algorithm>\n\n\n#include <array>\n\n#include \"sockets.h\"\n#include \"tools.h\"\n#include \"logger.h\"\n#include \"constants.h\"\n#include \"user.h\"\n#include \"map.h\"\n#include \"chat.h\"\n#include \"nbt.h\"\n#include \"mineserver.h\"\n#include \"packets.h\"\n#include \"config.h\"\n#include \"extern.h\"\n\n\nextern int setnonblock(int fd);\n\n#ifndef WIN32\n#define SOCKET_ERROR -1\n#endif\n\nstatic const size_t BUFSIZE = 2048;\nstatic std::array<uint8_t, BUFSIZE> BUF;\nstatic std::array<uint8_t, BUFSIZE> BUFCRYPT;\nstatic char* const cpBUF = reinterpret_cast<char*>(BUF.data());\nstatic uint8_t* const upBUF = BUF.data();\n\nstatic char* cpBUFCRYPT = reinterpret_cast<char*>(BUFCRYPT.data());\n\n\nbool client_write(User *user)\n{\n  if (user->deleting) return false;\n  //If there is data in the output buffer, crypt it before writing\n  if (!user->buffer.getWriteEmpty())\n  {\n    std::vector<char> buf;\n    \n    user->buffer.getWriteData(buf);\n    \n    //More glue - Fador\n    if(user->crypted)\n    {\n      //We might have to write some data uncrypted ToDo: fix\n      if(user->uncryptedLeft)\n      {\n        user->bufferCrypted.addToWrite((uint8_t *)buf.data(),user->uncryptedLeft);\n      }\n      int p_len = buf.size()-user->uncryptedLeft, f_len = 0;\n      if(p_len)\n      {\n        uint8_t *buffer = (uint8_t *)malloc(p_len+1);\n        EVP_EncryptUpdate(user->en, (uint8_t *)buffer, &p_len, (const uint8_t *)buf.data()+user->uncryptedLeft, buf.size()-user->uncryptedLeft);\n        int written = p_len + f_len;\n        user->bufferCrypted.addToWrite((uint8_t *)buffer,written);\n        free(buffer);\n      }\n      user->uncryptedLeft = 0;\n    }\n    else\n    {\n      user->bufferCrypted.addToWrite((uint8_t *)buf.data(),buf.size());\n      user->uncryptedLeft = 0;\n    }\n\n    //free(outBuf);\n    user->buffer.clearWrite(buf.size());\n  }\n\n  //We have crypted data ready to be written\n  if(!user->bufferCrypted.getWriteEmpty())\n  {\n    std::vector<char> buf;\n    user->bufferCrypted.getWriteData(buf);\n\n    //Try to write the whole buffer\n    const int written = send(user->fd, buf.data(), buf.size(), 0);\n\n    //Handle errors\n    if (written == SOCKET_ERROR)\n    {\n    #ifdef WIN32\n    #define ERROR_NUMBER WSAGetLastError()\n      if ((ERROR_NUMBER != WSATRY_AGAIN && ERROR_NUMBER != WSAEINTR && ERROR_NUMBER != WSAEWOULDBLOCK))\n    #else\n    #define ERROR_NUMBER errno\n      if ((errno != EAGAIN && errno != EINTR))\n    #endif\n      {\n        LOG2(ERROR, \"Error writing to client, tried to write \" + dtos(buf.size()) + \" bytes, code: \" + dtos(ERROR_NUMBER));        \n        user->deleting = true;\n        ServerInstance->usersToRemove().insert(user);\n        return false;\n      }\n    }\n    else\n    {\n      //Remove written amount from the buffer\n      user->bufferCrypted.clearWrite(written);\n    }\n\n    //If we couldn't write everything at once, add EV_WRITE event calling this function again..\n    if (!user->bufferCrypted.getWriteEmpty())\n    {\n      event_add(user->getWriteEvent(), NULL);\n      return false;\n    }\n  }\n  return true;\n}\n\nextern \"C\" void client_callback(int fd, short ev, void* arg)\n{\n  User* user = reinterpret_cast<User*>(arg);\n  if (user->deleting) return;\n\n  if (ev & EV_READ)\n  {\n    int read = 1;\n\n    //Data must be decrypted if we are in crypted mode\n    if(user->crypted)\n    {\n      read = recv(fd, cpBUFCRYPT, BUFSIZE, 0);\n      int p_len = read, f_len = 0;  \n      EVP_DecryptUpdate(user->de, upBUF, &p_len, (const uint8_t *)cpBUFCRYPT, read);\n      read = p_len + f_len;\n    }\n    else\n    {\n      read = recv(fd, cpBUF, BUFSIZE, 0);\n    }\n\n    if (read == 0)\n    {\n      if(user->nick.size())\n      {\n        LOG2(INFO, \"User \"+ user->nick + \" disconnected by closing socket\");\n      }\n      else\n      {\n        LOG2(INFO, \"Socket closed\");\n      }\n      user->deleting = true;\n      ServerInstance->usersToRemove().insert(user);\n      return;\n    }\n\n    if (read == SOCKET_ERROR)\n    {\n      LOG2(INFO, \"Socket error\");\n      user->deleting = true;\n      ServerInstance->usersToRemove().insert(user);\n      return;\n    }\n\n    //Keep track on incoming data, can timeout inactive users\n    user->lastData = std::time(NULL);\n\n    user->buffer.addToRead(upBUF, read);\n    user->buffer.reset();\n    MS_VarInt packetLen;\n    uint32_t varint_len;\n    uint32_t buffer_pos = 0;\n\n    // Handle exceptions caused by varint reading\n    try\n    {\n      while (user->buffer >> (MS_VarInt&)packetLen)\n      {  \n        varint_len = user->buffer.m_readPos-buffer_pos;      \n\n        // Check if we have the data in buffer\n        if (!user->buffer.haveData(static_cast<int64_t>(packetLen)))\n        {\n          user->waitForData = true;\n          event_add(user->getReadEvent(), NULL);\n          return;\n        }\n        // Packet data has been received, call the function\n        else\n        {\n          // Store packetlen to be used in the parsing functions (replaced later if compression used..)\n          user->packetLen = (int32_t)packetLen;\n          // Handle compressed incoming data\n          if (user->compression)\n          {\n            MS_VarInt uncompressed_size;\n            int32_t cur_pos = user->buffer.m_readPos;\n            user->buffer >> (MS_VarInt&)uncompressed_size;\n\n            // Hopefully a rare occasion when the packet size exceeds the compression threshold\n            if (uncompressed_size != 0)\n            {\n              uLongf written = uncompressed_size;\n              uLong sourceLen = (int)packetLen.val-(user->buffer.m_readPos-cur_pos);\n              uint8_t* inbuffer = new uint8_t[sourceLen];\n              uint8_t* buffer = new uint8_t[uncompressed_size+1];\n\n              user->buffer.getData(inbuffer,sourceLen);           \n\n              user->buffer.removePacketLen((uint32_t)packetLen+varint_len);\n              int ret = uncompress(buffer, &written, inbuffer, sourceLen);\n              if (ret < Z_OK || written != uncompressed_size) {\n                LOG2(DEBUG, \"Uncompress error\");              \n                buffer_pos = user->buffer.m_readPos;\n                continue;\n              }\n\n              user->buffer.addToReadBegin(buffer, written);\n              packetLen.val = written;\n              varint_len = 0;\n              delete[] inbuffer;\n              delete[] buffer;\n\n              // Replace the current packet length\n              user->packetLen = (int32_t)uncompressed_size;\n            }\n          }\n          MS_VarInt action;\n          user->buffer >> (MS_VarInt&)action;\n          user->action = (uint8_t)static_cast<int64_t>(action);\n\n          if (ServerInstance->packetHandler()->packets[user->gameState][user->action].len == PACKET_DOES_NOT_EXIST) {\n            std::ostringstream str;\n            str << \"Unknown packet: 0x\" << std::hex << (unsigned int)(user->action);\n            LOG2(DEBUG, str.str());\n            user->buffer.removePacketLen((uint32_t)packetLen+varint_len);\n\n            buffer_pos = user->buffer.m_readPos;\n            continue;\n          }\n          user->packetsPerSecond++;\n  #ifdef DEBUG\n          printf(\"Packet from %s, state = 0x%hx, id = 0x%hx \\n\", user->nick.c_str(), user->gameState, user->action);\n  #endif\n\n          //Call specific function\n          ServerInstance->packetHandler()->packets[user->gameState][user->action].function(user);\n\n          const bool disconnecting = user->action == 0xFF;\n\n          if (disconnecting) // disconnect -- player gone\n          {\n            if (user->nick.size()) {\n              LOG2(INFO, \"User \" + user->nick + \" disconnected normally\");\n            }\n            user->deleting = true;\n            ServerInstance->usersToRemove().insert(user);\n            return;\n          }   \n        }\n        user->buffer.removePacketLen((uint32_t)packetLen+varint_len);\n        buffer_pos = user->buffer.m_readPos;\n      } // while(user->buffer)\n    } catch (std::logic_error &e)\n    {\n      user->waitForData = true;\n      event_add(user->getReadEvent(), NULL);\n    }\n  } //End reading\n\n  //Write data to user socket\n  if(!client_write(user))\n  {\n    return;\n  }  \n\n  //Add EV_READ event again\n  event_add(user->getReadEvent(), NULL);\n}\n\nextern \"C\" void accept_callback(int fd, short ev, void* arg)\n{\n  sockaddr_in client_addr;\n  socklen_t client_len = sizeof(client_addr);\n\n  const int client_fd = accept(fd, reinterpret_cast<sockaddr*>(&client_addr), &client_len);\n\n  if (client_fd < 0)\n  {\n    LOGLF(\"Client: accept() failed\");\n    return;\n  }\n\n  User* const client = new User(client_fd, Mineserver::generateEID());\n  setnonblock(client_fd);\n\n  //Keep delay minimum: more (smaller) packets -> less lag\n  int one = 1;\n  setsockopt(client_fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&one, sizeof(int));\n\n  client->setReadEvent(event_new(ServerInstance->getEventBase(), client_fd, EV_READ, client_callback, client));\n  client->setWriteEvent(event_new(ServerInstance->getEventBase(), client_fd, EV_WRITE, client_callback, client));\n  event_add(client->getReadEvent(), NULL);\n}\n\n//Opens a socket and connects to the host/port\nint socket_connect(char* host, int port)\n{\n  struct hostent* hp;\n  struct sockaddr_in addr;\n  int on = 1, sock;\n\n  if ((hp = gethostbyname(host)) == NULL)\n  {\n    return 0;\n  }\n\n  memmove(&addr.sin_addr, hp->h_addr, hp->h_length);\n  addr.sin_port = htons(port);\n  addr.sin_family = AF_INET;\n  sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);\n\n  //Set 5s timeout\n  struct timeval tv;\n  tv.tv_sec = 5;\n  setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(struct timeval));\n  setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(struct timeval));\n  setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&on, sizeof(int));\n\n  if (sock == -1 || connect(sock, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) == -1)\n  {\n    return 0;\n  }\n\n  return sock;\n}\n"
  },
  {
    "path": "src/sockets.h",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n/*\n  We declare functions that serve as C callbacks explicitly as 'extern \"C\"'\n  to avoid any potential ABI incompatibilities.\n*/\nclass User;\n\nextern \"C\" void accept_callback(int fd, short ev, void* arg);\nextern \"C\" void client_callback(int fd, short ev, void* arg);\nextern \"C\" void *user_validation_thread(void *arg);\nbool client_write(User *user);\n"
  },
  {
    "path": "src/stdtime.h",
    "content": "#ifndef _STDTIME_H\n#define _STDTIME_H\n\n#include <ctime>\n#include <stdint.h>\n#include <cassert>\n#include <string>\n#include <iostream>\n#include <sstream>\n#include <cmath>\n\n#include <chrono>\n\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef __unix__\n#include <sys/time.h>\n#include <unistd.h>\n#endif\n\nclass Time {\npublic:\n  Time() {}\n\n  explicit Time(int64_t usec):m_usec(usec){}\n  explicit Time(int32_t sec,int32_t usec):m_usec(sec*1000000 + usec){}\n\n  Time(const Time& rhs)\n    :m_usec(rhs.m_usec) {}\n\n  /// Math Operations\n  Time operator+(const Time& t) const {\n    return Time(m_usec + t.m_usec);\n  }\n  Time operator-(const Time& t) const {\n    return Time(m_usec - t.m_usec);\n  }\n  Time operator*(const Time& t) const {\n    return Time(m_usec * t.m_usec);\n  }\n  Time operator/(const Time& t) const {\n    return Time(m_usec / t.m_usec);\n  }\n\n  Time& operator+=(const Time& rhs)\n  {\n    return (*this) = (*this) + rhs;\n  }\n  Time& operator-=(const Time& rhs)\n  {\n    return (*this) = (*this) - rhs;\n  }\n  Time& operator*=(const Time& rhs)\n  {\n    return (*this) = (*this) * rhs;\n  }\n  Time& operator/=(const Time& rhs)\n  {\n    return (*this) = (*this) / rhs;\n  }\n\n  /// Comparison\n  bool operator<(const Time& t) const {\n    return m_usec < t.m_usec;\n  }\n  bool operator>(const Time& t) const {\n    return m_usec > t.m_usec;\n  }\n\n  /// SLEEP\n  static void sleep(const Time& t){\n#ifdef WIN32\n    Sleep((DWORD)t.total_usec());\n#elif defined(__unix__)\n    usleep(t.total_usec());\n#endif\n  }\n\n  static void sleep_until(const Time& until){\n    Time tnow = now();\n    assert(until > tnow);\n    sleep(until - tnow);\n  }\n\n  static void context_switch(){\n    Time::sleep(Time(0,0));\n  }\n\n  static Time now(){\n#ifdef WIN32\n    LARGE_INTEGER temp;\n    QueryPerformanceCounter(&temp);\n\n    LARGE_INTEGER freq;\n    QueryPerformanceFrequency(&freq);\n\n    extern Time systemboot;\n\n    return Time( temp.QuadPart / freq.QuadPart,\n                 ( double(temp.QuadPart % freq.QuadPart)\n                   / double(freq.QuadPart)) * 1000000) + systemboot;\n#endif\n#ifdef __unix__\n    timeval tv;\n    gettimeofday( &tv, 0);\n\n    return Time( tv.tv_sec, tv.tv_usec);\n#endif\n\n    /*\n        int64_t temp = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();\n        return Time(temp/1000000,temp%1000000);\n        */\n  }\n\n#define _out(X,Y); if(X) s<<X<<Y;\n  operator std::string() const{\n    std::stringstream s;\n\n    struct tm* ptm;\n    time_t t = total_sec();\n    ptm = gmtime(&t);\n\n    _out(ptm->tm_year - 70,\"years \");\n    _out(ptm->tm_yday,\"days \");\n    _out(ptm->tm_hour,\"hours \");\n    _out(ptm->tm_min,\"mins \");\n    _out(ptm->tm_sec,\"s \");\n\n    if(uint32_t ms = msec())\n      s<<ms<<\"ms \";\n    //s<<usec()<<u8\"µs\";\n    return s.str();\n  }\n\n  std::string UTC(){\n    std::stringstream s;\n\n    struct tm* ptm;\n    time_t t = total_sec();\n    ptm = gmtime(&t);\n    //ptm->tm_year += 1900;\n\n    //s<< std::put_time(ptm,\"%c %Z\");\n    //_out(ptm->tm_year,\"years \");\n    //_out(ptm->tm_yday,\"days \");\n    //_out(ptm->tm_hour,\"hours \");\n    //_out(ptm->tm_min,\"mins \");\n    //_out(ptm->tm_sec,\"s \");\n\n    /// Light FIXME: change buf size to the max possible formatted date size\n    char buf[1000];\n    size_t l = strftime(buf,sizeof(buf), \"%Y %B %d (%A) %X\", ptm);\n\n    s<< std::string(buf, l);\n    if(uint32_t ms = msec())\n      s<<':'<<ms;\n    s<<':'<<usec();\n    return s.str();\n  }\n#undef _out\n\n  int32_t sec()  const{ return m_usec / 1000000;}\n  int64_t msec() const{ return m_usec / 1000 % 1000;}\n  int64_t usec() const{ return m_usec % 1000;}\n\n  int64_t total_sec()  const{ return m_usec/1000000;}\n  int64_t total_msec() const{ return m_usec/1000;}\n  int64_t total_usec() const{ return m_usec;}\nprivate:\n  friend std::ostream& operator<<(std::ostream& strm, const Time& t);\n\n  int64_t m_usec;\n};\n\ninline std::ostream& operator<<(std::ostream& strm, const Time& t){\n  return (strm << (std::string)t);\n}\n\n\n#ifdef WIN32\nextern Time systemboot;\n#endif\n#endif // _TIME_H\n\n"
  },
  {
    "path": "src/threadpool.cpp",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"mineserver.h\"\n#include \"user.h\"\n#include \"tools.h\"\n\n#include \"threadpool.h\"\n#include \"json.h\"\n\n\nvoid ThreadPool::taskValidateUser(ThreadTask *task)\n{\n  // https://wiki.openssl.org/index.php/SSL/TLS_Client\n  #define HOST_NAME \"sessionserver.mojang.com\"\n  #define HOST_PORT \"443\"\n  #define HOST_RESOURCE \"/session/minecraft/hasJoined?\"\n  const char* const PREFERRED_CIPHERS = \"HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4\";\n  long res = 1;\n  int len = 0;\n  SSL_CTX* ctx = NULL;\n  BIO *web = NULL;\n  SSL *ssl = NULL;\n  char buff[1536] = {};\n  std::string::size_type findResult;\n  const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;\n  Mineserver::userValidation userValid;\n  userValid.valid = false;\n  std::string output,request_uri, get_req;  \n  X509* cert;\n\n  const SSL_METHOD* method = SSLv23_method();\n  if(!(NULL != method)) goto cleanup;\n\n  ctx = SSL_CTX_new(method);\n  if(!(ctx != NULL)) goto cleanup;\n\n  // ToDo: use cert verification\n  SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);\n\n  SSL_CTX_set_verify_depth(ctx, 4);\n\n  SSL_CTX_set_options(ctx, flags);\n\n  //res = SSL_CTX_load_verify_locations(ctx, \"chain.pem\", NULL);\n  //if(!(1 == res)) goto failure;\n\n  web = BIO_new_ssl_connect(ctx);\n  if(!(web != NULL)) goto cleanup;\n\n  res = BIO_set_conn_hostname(web, HOST_NAME \":\" HOST_PORT);\n  if(!(1 == res)) goto cleanup;\n\n  BIO_get_ssl(web, &ssl);\n  if(!(ssl != NULL)) goto cleanup;\n    \n  res = SSL_set_cipher_list(ssl, PREFERRED_CIPHERS);\n  if(!(1 == res)) goto cleanup;\n\n  res = SSL_set_tlsext_host_name(ssl, HOST_NAME);\n  if(!(1 == res)) goto cleanup;\n\n  res = BIO_do_connect(web);\n  if(!(1 == res)) goto cleanup;\n\n  res = BIO_do_handshake(web);\n  if(!(1 == res)) goto cleanup;\n\n  // verify a server certificate was presented during the negotiation\n  cert = SSL_get_peer_certificate(ssl);\n  if(cert) { X509_free(cert); } // Free immediately\n  if(NULL == cert) goto cleanup;\n\n  //ToDo: verify\n  //res = SSL_get_verify_result(ssl);\n  //if(!(X509_V_OK == res)) return;\n\n  // Hostname verification ?  \n  request_uri = HOST_RESOURCE \"username=\" + task->user->nick;\n  request_uri += std::string(\"&serverId=\") + task->user->generateDigest();\n\n  get_req  = \"GET \" + request_uri + \" HTTP/1.1\\r\\n\"\n                \"Host: \" HOST_NAME \"\\r\\n\"\n                \"Connection: close\\r\\n\"\n                \"\\r\\n\\r\\n\";\n\n  BIO_puts(web, get_req.c_str());    \n  \n  do\n  {    \n    len = BIO_read(web, buff, sizeof(buff));            \n    if(len > 0)\n      output.append(buff, len);\n\n  } while (len > 0 || BIO_should_retry(web));\n  \n  // Make sure we have the right HTTP code\n  findResult = output.find(\"200 OK\");\n  if (findResult == std::string::npos) goto cleanup;\n  findResult = output.find(\"\\r\\n\\r\\n\");\n  if (findResult == std::string::npos) goto cleanup;\n\n  {\n    // Parse the JSON\n    std::string input_json = output.substr(findResult);\n    int32_t jsonlen = input_json.length();  \n    JSON_Val value((uint8_t*)input_json.c_str(), jsonlen, JSON_Val::JSON_COMPOUND);\n\n    // Grab the values\n    if (value[\"id\"] != nullptr && value[\"id\"]->getType() == JSON_Val::JSON_STRING &&\n       value[\"name\"] != nullptr && value[\"name\"]->getType() == JSON_Val::JSON_STRING &&\n       value[\"properties\"] != nullptr && value[\"properties\"]->getType() == JSON_Val::JSON_LIST)\n    {\n      task->user->setUUID(*value[\"id\"]->getString(), false);    \n      //std::cout << \"name: \" << *value[\"name\"]->getString() << std::endl;\n      for(JSON_Val *var : *value[\"properties\"]->getList())\n      {\n        if ((*var)[\"name\"] != nullptr && (*var)[\"name\"]->getType() == JSON_Val::JSON_STRING &&\n           (*var)[\"value\"] != nullptr && (*var)[\"value\"]->getType() == JSON_Val::JSON_STRING &&\n           (*var)[\"signature\"] != nullptr && (*var)[\"signature\"]->getType() == JSON_Val::JSON_STRING)\n        {\n          task->user->properties.push_back(UserProperty(*(*var)[\"name\"]->getString(),\n                                                        *(*var)[\"value\"]->getString(),\n                                                        *(*var)[\"signature\"]->getString()));\n        }\n      }\n    } else {\n      goto cleanup;\n    }\n\n  }\n\n  //std::cout << output << std::endl;\n \n  userValid.valid = true;\n  userValid.user = task->user;\n  userValid.UID = task->user->UID;\n\ncleanup:\n\n  std::unique_lock<std::mutex> l(ServerInstance->m_validation_mutex);\n  ServerInstance->validatedUsers.push_back(userValid);\n  l.unlock();\n\n  if(web != NULL)\n    BIO_free_all(web);\n\n  if(NULL != ctx)\n    SSL_CTX_free(ctx);\n}"
  },
  {
    "path": "src/threadpool.h",
    "content": "/*\n   Copyright (c) 2016, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#pragma once\n\n#include <vector>\n#include <iostream>\n#include <thread>\n#include <mutex>\n#include <queue>\n#include <condition_variable>\n#include <chrono>\n#include <exception>\n\nenum ThreadType { THREAD_MAPGEN, THREAD_LIGHTGEN, THREAD_VALIDATEUSER };\n\nclass User;\n\nstruct ThreadTask {\n\n  ThreadTask() {};\n  ThreadTask(ThreadType _type, User* _user) : type(_type), user(_user) {};\n  ThreadType type;\n  User *user;\n\n  uint32_t taskID;\n\n  struct {\n    std::string accessToken;\n  } taskValidate;\n};\n\nclass ThreadPool{\npublic:\n    ThreadPool() : running(true),taskID(0) { }\n\n    // Only increase, cannot decrease yet\n    // ToDo: decrease thread count\n    bool setThreadCount(uint32_t val) {\n      while (threads.size() < val) {\n        // Create a thread with a lambda function looping execute();\n        threads.push_back(std::thread(\n              [&] {\n                    while (running) {\n                      try {\n                        execute(); \n                      } catch (std::exception e) {}\n                    }\n                  }));\n      }\n      return true;\n    }\n\n    // Add a new task to the pool\n    void newTask(ThreadTask* task){      \n        std::unique_lock<std::mutex> lock(inputMutex);\n        task->taskID = taskID++;\n        tasks.push(task);\n        // Use condition to notify a thread to handle this task\n        taskCondition.notify_one();\n    }\n\n    // Main function when running a thread\n    void execute(){\n\n        std::unique_lock<std::mutex> inputLock(inputMutex);\n\n        // Wait if there's no tasks in the queue\n        taskCondition.wait(inputLock, [&](){ return !tasks.empty() || !running; });\n\n        if (!running){\n            throw std::exception();\n        }\n\n        ThreadTask* task = tasks.front();\n        tasks.pop();\n        inputLock.unlock();\n\n        // Handle task\n        if (task->type == THREAD_VALIDATEUSER)\n        {\n         taskValidateUser(task);\n        }\n        else\n        {\n          // Simulate random delay\n          std::this_thread::sleep_for(std::chrono::milliseconds{ rand()%500 });\n        }\n\n        std::unique_lock<std::mutex> outputLock(outputMutex);\n        std::cout << \"Thread \" << std::this_thread::get_id() << \" handled task \" << task->taskID << std::endl;\n        outputLock.unlock();\n        delete task;\n    }\n\n    // Clean up the threads\n    void shutdown(){\n        running = false;\n        taskCondition.notify_all();\n        for (auto &thread : threads)\n        {\n          thread.join();\n        }\n    }\n\nprivate:\n    std::queue<ThreadTask*> tasks;\n    std::condition_variable taskCondition;\n    std::mutex inputMutex;\n    std::mutex outputMutex;\n    std::vector<std::thread> threads;\n    bool running;\n    uint32_t taskID;\n\n    // Tasks\n    void taskValidateUser(ThreadTask* task);\n};\n"
  },
  {
    "path": "src/tools.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#ifdef __unix__\n#include <unistd.h>\n#include <libgen.h>\n#include <wordexp.h>  // for wordexp\n#include <sys/stat.h> // for mkdir\n#include <climits>\n#endif\n\n#ifdef __APPLE__\n#include <unistd.h>\n#include <libgen.h>\n#include <wordexp.h>\n#include <sys/stat.h>\n#include <climits>\n\n// Mac workaround because lack of clock_gettime\n// (idk why. But its a common problem.)\n#include <mach/clock.h>\n#include <mach/mach.h>\n#endif\n\n#ifdef _WIN32\n#include <direct.h>\n#define _WINSOCKAPI_\n#include <ShlObj.h>\n#endif\n\n#include <iostream>\n#include <fstream>\n#include <sstream>\n#include <vector>\n#include <string>\n#include <cstdlib>\n#include <cstring>\n#include <cstdio>\n#include <ctime>\n#include <cmath>\n#include <cctype>\n#include <cassert>\n\n#include \"tools.h\"\n#include \"logger.h\"\n#include \"mineserver.h\"\n#include \"config.h\"\n\nvoid putSint64(uint8_t* buf, int64_t value)\n{\n  uint64_t nval = ntohll(value);\n  memcpy(buf, &nval, 8);\n}\n\nvoid putSint32(uint8_t* buf, int32_t value)\n{\n  uint32_t nval = htonl(value);\n  memcpy(buf, &nval, 4);\n}\n\nvoid putSint16(uint8_t* buf, int16_t value)\n{\n  short value2 = htons(value);\n  memcpy(buf, &value2, 2);\n}\n\nvoid putFloat(uint8_t* buf, float value)\n{\n  uint32_t nval;\n  memcpy(&nval, &value, 4);\n  nval = htonl(nval);\n  memcpy(buf, &nval, 4);\n}\n\nvoid putDouble(uint8_t* buf, double value)\n{\n  uint64_t nval;\n  memcpy(&nval, &value, 8);\n  nval = ntohll(nval);\n  memcpy(buf, &nval, 8);\n}\n\ndouble getDouble(uint8_t* buf)\n{\n  double val;\n  uint64_t ival;\n  memcpy(&ival, buf, 8);\n  ival = ntohll(ival);\n  memcpy(&val, &ival, 8);\n  return val;\n}\n\nfloat getFloat(uint8_t* buf)\n{\n  float val;\n  int ival = ntohl(*reinterpret_cast<const int32_t*>(buf));\n  memcpy(&val, &ival, 4);\n  return val;\n}\n\nint64_t getSint64(uint8_t* buf)\n{\n  int64_t val;\n  memcpy(&val, buf, 8);\n  val = ntohll(val);\n  return val;\n}\n\nint32_t getSint32(uint8_t* buf)\n{\n  int val = ntohl(*reinterpret_cast<const int32_t*>(buf));\n  return val;\n}\n\nint32_t getSint16(uint8_t* buf)\n{\n  short val = ntohs(*reinterpret_cast<const int16_t*>(buf));\n\n  return val;\n}\n\nstd::string base36_encode(int value)\n{\n  std::string output;\n  my_itoa((int)abs(value), output, 36);\n  if (value < 0)\n  {\n    output.insert(output.begin(), '-');\n  }\n\n  return output;\n}\n\nuint8_t hexToByte(char hex)\n{\n  if (hex >= '0' && hex <= '9')\n    return hex - '0';\n  if (hex >= 'a' && hex <= 'f')\n    return 10+(hex - 'a');\n  if (hex >= 'A' && hex <= 'F')\n    return 10+(hex - 'A');\n\n  return 0;\n}\n\nvoid my_itoa(int value, std::string& buf, int base)\n{\n  std::string hexarray(\"0123456789abcdefghijklmnopqrstuvwxyz\");\n  int i = 30;\n  buf = \"\";\n\n  if (!value)\n  {\n    buf = \"0\";\n  }\n\n  for (; value && i; --i, value /= base)\n  {\n    buf.insert(buf.begin(), (char)hexarray[value % base]);\n  }\n}\n\nstd::string my_itoa(int value, int base)\n{\n  std::string ret;\n  my_itoa(value, ret, base);\n  return ret;\n}\n\nstd::string strToLower(std::string temp)\n{\n  const int len = temp.length();\n\n  for (int i = 0; i != len; ++i)\n  {\n    temp[i] = std::tolower(temp[i]);\n  }\n\n  return temp;\n}\n\nstd::string dtos(double n)\n{\n  std::ostringstream result;\n  result << n;\n  return result.str();\n}\n\nstd::string hash(std::string value)\n{\n  // Hash the player's name along with a secret to generate a unique hash for this player\n  // Uses the DJB2 algorithm\n  unsigned long hash = 5381;\n  int c;\n\n  char* cvalue = const_cast<char*>(value.c_str());\n\n  while ((c = *cvalue++))\n  {\n    hash = ((hash << 5) + hash) + c;  /* hash * 33 + c */\n  }\n\n  std::ostringstream hashString;\n  hashString << hash;\n\n  return hashString.str();\n}\n\nbool fileExists(const std::string& filename)\n{\n  std::ifstream i(filename.c_str());\n  return i.is_open();\n}\n\nbool makeDirectory(const std::string& path)\n{\n#ifdef WIN32\n  return mkdir(path.c_str()) != -1;\n#else\n  return mkdir(path.c_str(), 0755) != -1;\n#endif\n}\n\nstd::string canonicalizePath(const std::string& pathname)\n{\n  // We assume that pathname is already a path name, with no file component!\n\n#if defined(linux)\n\n  wordexp_t exp_result;\n\n  wordexp(pathname.c_str(), &exp_result, 0);\n\n  char * d = strdup(exp_result.we_wordv[0]);\n\n  wordfree(&exp_result);\n\n  char * rp = new char[PATH_MAX];\n  std::memset(rp, 0, PATH_MAX);\n  realpath(d, rp);\n\n  std::string res(rp);\n\n  free(d);\n  delete[] rp;\n\n  return res;\n\n#elif defined(WIN32)\n\n  return pathname;\n\n#else\n  // Why is this else? what the fuck are we compiling on? - Justasic\n  return pathname;\n\n#endif\n\n}\n\nstd::string relativeToAbsolute(const std::string &path)\n{\n  /// This is a very crude way to check if the path is relative.\n  /// We must replace this by a more portable \"pathIsRelative()\" check.\n  std::string pathname = path;\n  if (!pathname.empty() && pathname[0] != PATH_SEPARATOR && pathname[0] != '~')\n    pathname = ServerInstance->config()->config_path + PATH_SEPARATOR + pathname;\n\n  pathname = canonicalizePath(pathname);\n\n  return pathname;\n}\n\nstd::string getHomeDir()\n{\n\n#if defined(linux)\n\n  return canonicalizePath(\"~/.mineserver\");\n\n#elif defined(__WIN32__)\n\nchar szPath[MAX_PATH];\nif(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, szPath) == 0)\n{\n  std::string temp = szPath;\n  temp.append(\"\\\\Mineserver\");\n  return temp;\n}\nelse\n{\n  return \"%APPDATA%\\\\Mineserver\"; // This doesn't seem to work.\n}\n\n#else\n\n  return \"[ERROR: getHomeDir() not implemented]\";\n\n#endif\n\n}\n\nstd::string pathOfExecutable()\n{\n    char buffer[512];\n    assert(getcwd(buffer, sizeof(buffer)));\n\n    return buffer;\n    /*\n  const size_t dest_len = 4096;\n  char path[dest_len];\n  std::memset(path, 0, dest_len);\n\n#if defined(linux)\n\n  if (readlink (\"/proc/self/exe\", path, dest_len) != -1)\n  {\n    dirname(path);\n  }\n\n  return std::string(path);\n\n#elif defined(WIN32)\n*/\n  /*\n  if (0 == GetModuleFileName(NULL, path, dest_len))\n  {\n    return \"\";\n  }\n\n  return pathOfFile(path).first;\n  */\n    /*\n  char buffer[512];\n  assert(getcwd(buffer, sizeof(buffer)));\n\n  return buffer;\n#else\n\n  return \"\";\n\n#endif\n*/\n}\n\nstd::pair<std::string, std::string> pathOfFile(const std::string& filename)\n{\n\n#if defined(linux)\n\n  char * a = strdup(filename.c_str());\n  char * b = strdup(filename.c_str());\n  char * d = dirname(a);\n\n  std::string res_p(d), res_f(basename(b));\n\n  free(a);\n  free(b);\n\n  return std::make_pair(canonicalizePath(res_p), res_f);\n\n#elif defined(WIN32)\n\n  const size_t dest_len = 4096;\n  char path[dest_len], *pPart;\n  std::memset(path, 0, dest_len);\n\n  GetFullPathName(filename.c_str(), dest_len, path, &pPart);\n\n  const size_t diff = pPart - path;\n\n  if (diff > 0 && diff != size_t(-1))\n    return std::make_pair(std::string(path, diff - 1), std::string(pPart));\n  else\n    return std::make_pair(std::string(path), \"\");\n\n#else\n\n  return std::make_pair(\"[ERROR IN PATH RECONSTRUCTION: Unknown platform, please implement.]\", \"\");\n\n#endif\n\n}\n\n\n#include \"stdtime.h\"\nuint64_t microTime()\n{\n#ifndef WIN32\n  #ifdef __APPLE__\n  // copied from gist.github.com/jbenet/1087739\n  clock_serv_t cclock;\n  mach_timespec_t m_ts;\n  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);\n  clock_get_time(cclock, &m_ts);\n  mach_port_deallocate(mach_task_self(), cclock);\n  return (m_ts.tv_sec*(uint64_t)1000000 + m_ts.tv_nsec/(uint64_t)1000);\n  #else\n  struct timespec now;\n  clock_gettime(CLOCK_MONOTONIC, &now);\n  return (now.tv_sec*(uint64_t)1000000 + now.tv_nsec/(uint64_t)1000);\n  #endif\n#else\n  FILETIME ft;\n  GetSystemTimeAsFileTime(&ft);\n  uint64_t out = ((uint64_t)ft.dwHighDateTime)<<32 | (uint64_t)ft.dwLowDateTime;\n  out /= 10; // from 100ns to 1us\n  return out;\n#endif\n}\n"
  },
  {
    "path": "src/tools.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _TOOLS_H\n#define _TOOLS_H\n\n#include <stdint.h>\n#include <cstdlib>\n#include <string>\n#include <time.h>\n\n#include \"extern.h\"\n\n#ifdef _WIN32\n#define NOMINMAX\n#include <winsock2.h>\n#else\n#include <arpa/inet.h>\n#endif\n\n#ifdef WIN32\n#define M_PI 3.141592653589793238462643\n#endif\n#define DEGREES_TO_RADIANS(x) ((x) / 180.0 * M_PI)\n#define RADIANS_TO_DEGREES(x) ((x) / M_PI * 180.0)\n\nvoid putSint64(uint8_t* buf, int64_t value);\nvoid putSint32(uint8_t* buf, int32_t value);\nvoid putSint16(uint8_t* buf, short value);\nvoid putDouble(uint8_t* buf, double value);\nvoid putFloat(uint8_t* buf, float value);\n\nint64_t getSint64(uint8_t* buf);\ndouble getDouble(uint8_t* buf);\nfloat  getFloat(uint8_t* buf);\nint32_t getSint32(uint8_t* buf);\nint32_t getSint16(uint8_t* buf);\n\nuint8_t hexToByte(char hex);\nvoid my_itoa(int value, std::string& buf, int base);\nstd::string my_itoa(int value, int base = 10);\nstd::string base36_encode(int value);\nstd::string strToLower(std::string temp);\n\nstd::string dtos(double n);\nstd::string hash(std::string value);\n\n#ifdef WIN32\n#define PATH_SEPARATOR  '\\\\'\n#else\n#define PATH_SEPARATOR  '/'\n#endif\n\nE bool fileExists(const std::string& filename);\nE bool makeDirectory(const std::string& path);\nE std::string canonicalizePath(const std::string& pathname);\nE std::string getHomeDir();\nE std::string pathOfExecutable();\nE std::pair<std::string, std::string> pathOfFile(const std::string& filename);\nE std::string relativeToAbsolute(const std::string &pathname);\n\n#ifndef WIN32\ninline uint64_t ntohll(uint64_t v)\n{\n  return (uint64_t)ntohl(v & 0x00000000ffffffff) << 32 | (uint64_t)ntohl((v >> 32) & 0x00000000ffffffff);\n}\n#endif\n\n//Converts block-coordinates to chunk coordinate\ninline int32_t blockToChunk(int32_t value)\n{\n  return value >> 4; //(value < 0) ? (((value+1)/16)-1) : (value/16);\n}\n\n//Converts absolute block-coordinates to chunk-block-coordinates\ninline int32_t blockToChunkBlock(int32_t value)\n{\n  return value & 15; //(value < 0) ? (15+((value+1)%16)) : (value%16);\n}\n\ninline int8_t angleToByte(float angle)\n{\n  return (int8_t)((angle / 360.f) * 256.f);\n}\n\ninline bool positionToXYZ(uint64_t position, int32_t &x, int16_t &y, int32_t &z) {\n  x = position >> 38;\n  y = (position >> 26) & 0xff;\n  z = position & 0x3ffffff;\n\n  if (z & 0x2000000) z |= 0xFC000000;\n  if (x & 0x2000000) x |= 0xFC000000;\n  return true;\n}\n\nuint64_t microTime();\n\n/// If we had any ol' good library, we would need this.\ninline std::string json_esc(const std::string str)\n{\n  std::string ret;\n\n  for(const char& c : str)\n  {\n    if(c == '\\\\')\n      ret += \"\\\\\\\\\";\n    else if(c == '\"')\n      ret += \"\\\\\\\"\";\n    else\n      ret += c;\n  }\n  return ret;\n}\n\n#endif\n"
  },
  {
    "path": "src/tree.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cmath>\n#include \"tree.h\"\n#include \"mineserver.h\"\n\n#include \"tools.h\"\n#include \"random.h\"\n\n\nvoid Tree::generate(uint8_t limit)\n{\n\n  const uint8_t m_trunkHeight = uniformUINT8(MIN_TRUNK, limit);\n\n  bool smalltree = false;\n  uint8_t type = 0;\n\n  if (m_trunkHeight < BRANCHING_HEIGHT)\n  {\n    smalltree = true;\n  }\n\n  if (uniform01() > 0.5) // 1/2 chance\n  {\n    ++type;\n    if (uniform01() > 0.5) // 1/4\n    {\n      ++type;\n    }\n  }\n\n  for (unsigned int i = 0; i + 1 < m_trunkHeight /* Trunk Height */; ++i)\n  {\n    if (smalltree)\n    {\n      const TrunkPtr v(new Trunk(_x, _y + i, _z, _map, type));\n      if (i >= MIN_TRUNK - 1)\n      {\n        m_Branch[n_branches++] = v;\n      }\n    }\n    else\n    {\n      const TrunkPtr v(new Trunk(_x, _y + i, _z, _map, type));\n      if (i > BRANCHING_HEIGHT - 1)\n      {\n        generateBranches(v);\n        m_Branch[n_branches++] = v;\n      }\n    }\n  }\n\n  const TrunkPtr v(new Trunk(_x, _y + m_trunkHeight - 1, _z, _map, type));\n  generateBranches(v);\n  generateCanopy();\n  m_Branch[n_branches++] = v;\n}\n\nvoid Tree::generateBranches(TrunkPtr wrap)\n{\n  int32_t x = wrap->_x;\n  uint8_t y = wrap->_y;\n  int32_t z = wrap->_z;\n\n  //uint32_t schanse = BRANCHING_CHANCE;\n\n  if (uniform01() > 1.0 - (1.0 / BRANCHING_CHANCE))\n  {\n    const double r = uniform01();\n    if (r < 0.2)\n    {\n      x--;\n    }\n    else if (r < 0.4)\n    {\n      x++;\n    }\n    else if (r < 0.6)\n    {\n      z++;\n    }\n    else if (r < 0.8)\n    {\n      z--;\n    }\n    if (r > 0.5)\n    {\n      y++;\n    }\n\n    const TrunkPtr v(new Trunk(x, y, z, _map));\n    m_Branch[n_branches++] = v;\n    generateBranches(v);\n  }\n}\n\nvoid Tree::generateCanopy()\n{\n  uint8_t block, meta;\n  uint8_t canopySize;\n\n  uint8_t canopy_type = 0;\n\n  int32_t t_posx, t_posy, t_posz;\n\n  if (uniform01() > 0.5) // 1/2\n  {\n    canopy_type++;\n    if (uniform01() > 0.5) // 1/4\n    {\n      canopy_type++;\n    }\n  }\n  canopySize = 3;\n  //canopySize = (BetterRand()*(MAX_CANOPY - MIN_CANOPY)) + MIN_CANOPY;\n\n  for (uint8_t i = 0; i < n_branches; i++)\n  {\n    for (int8_t xi = (-canopySize); xi <= canopySize; xi++)\n    {\n      for (int8_t yi = (-canopySize); yi <= canopySize; yi++)\n      {\n        for (int8_t zi = (-canopySize); zi <= canopySize; zi++)\n        {\n          if (abs(xi) + abs(yi) + abs(zi) <= canopySize)\n          {\n            t_posx = m_Branch[i]->_x + xi;\n            t_posy = m_Branch[i]->_y + yi;\n            t_posz = m_Branch[i]->_z + zi;\n\n            if (ServerInstance->map(_map)->getBlock(t_posx, t_posy, t_posz, &block, &meta, true) && block == BLOCK_AIR)\n            {\n              Canopy u(t_posx, t_posy, t_posz, _map, canopy_type);\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/tree.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _TREE_H_\n#define _TREE_H_\n\n#include <stack>\n\n#include <memory>\n#include <array>\n\n#include \"constants.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"vec.h\"\n\n\n\nenum { MAX_TRUNK = 13, MIN_TRUNK = 5, MAX_CANOPY = 4, MIN_CANOPY = 3 ,\n       BRANCHING_HEIGHT = 7, BRANCHING_CHANCE = 10,\n       MIN_TREE_SPACE = 5\n     };\n\nclass ITree\n{\npublic:\n\n  ITree(int32_t x, int32_t y, int32_t z, int map, uint8_t block = BLOCK_AIR, char meta = 0)\n  : _x(x), _y(y), _z(z), _map(map), _type(block), _meta(meta)\n  {\n  }\n\n  virtual ~ITree() { }\n\n  inline virtual void update()\n  {\n    ServerInstance->map(_map)->setBlock(_x, _y, _z, _type, _meta);\n    ServerInstance->map(_map)->sendBlockChange(_x, _y, _z, _type, _meta);\n  }\n\n  int32_t _x;\n  int32_t _y;\n  int32_t _z;\n\nprotected:\n  int     _map;\n  uint8_t _type;\n  char    _meta;\n};\n\n\nclass Trunk : public ITree\n{\npublic:\n  Trunk(int32_t x, int32_t y, int32_t z, int map, char meta = 0)\n  : ITree(x, y, z, map, BLOCK_LOG, meta)\n  {\n    update();\n  }\n};\n\ntypedef std::shared_ptr<Trunk> TrunkPtr;\n\n\nclass Canopy : public ITree\n{\npublic:\n  Canopy(int32_t x, int32_t y, int32_t z, int map, char meta = 0)\n  : ITree(x, y, z, map, BLOCK_LEAVES, meta)\n  {\n    update();\n  }\n};\n\nclass Tree : public ITree\n{\npublic:\n  Tree(int32_t x, int32_t y, int32_t z, int map, uint8_t limit = MAX_TRUNK)\n  : ITree(x, y, z, map), n_branches(0)\n  {\n    generate(limit);\n  }\n\n  void generate(uint8_t);\n\nprivate:\n  void set(int32_t xloc, int32_t yloc, int32_t zloc, int blocktType, char metaData);\n  std::array<TrunkPtr, 256> m_Branch; // 1KB on x86 and 2KB on x86_64 Faster than stack or vector tho :)\n\n  // With full array of allocated classes it rounds up to...\n  // 3.6KB on x86 :F 4.6KB on x86_64\n  // it is a good enough buffer for absolutely MASSIVE MASSIVE TREES\n  // Like in Avatar *_*\n\n  uint8_t n_branches;\n\n  void generateCanopy();\n  void generateBranches(TrunkPtr);\n};\n\n#endif\n"
  },
  {
    "path": "src/user.cpp",
    "content": "/*\n   Copyright (c) 2012, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cmath>\n#include <sys/stat.h>\n#include <algorithm>\n#include <stdio.h>\n\nusing namespace std;\n\n#include \"constants.h\"\n\n#include \"user.h\"\n#include \"mineserver.h\"\n#include \"map.h\"\n#include \"chat.h\"\n#include \"plugin.h\"\n#include \"permissions.h\"\n#include \"mob.h\"\n#include \"logger.h\"\n#include \"protocol.h\"\n#define LOADBLOCK(x,y,z) ServerInstance->map(pos.map)->getBlock(int(std::floor(double(x))), int(std::floor(double(y))), int(std::floor(double(z))), &type, &meta)\n\n\n// Generate \"unique\" entity ID\n\nUser::User(int sock, uint32_t EID)\n{\n  this->action          = 0;\n  this->muted           = false;\n  this->dnd             = false;\n  this->waitForData     = false;\n  this->fd              = sock;\n  this->UID             = EID;\n  this->logged          = false;\n  this->serverAdmin     = false;\n  this->pos.map         = 0;\n  this->pos.x           = ServerInstance->map(pos.map)->spawnPos.x();\n  this->pos.y           = ServerInstance->map(pos.map)->spawnPos.y();\n  this->pos.z           = ServerInstance->map(pos.map)->spawnPos.z();\n  this->write_err_count = 0;\n  this->health          = 20;\n  this->attachedTo      = 0;\n  this->timeUnderwater  = 0;\n  this->isOpenInv       = false;\n  this->lastData        = time(NULL);\n  this->permissions     = 0;\n  this->fallDistance    = -10;\n  this->healthtimeout   = time(NULL) - 1;\n  this->crypted         = false;\n  this->gameState       = 0;\n  this->compression     = 0;\n  this->packetsPerSecond = 0;\n  this->gamemode        = GameMode::Survival;\n  this->deleting        = false;\n\n  this->m_currentItemSlot = 0;\n  this->inventoryHolding  = Item(this, -1);\n  this->curItem          = 0;\n\n  //Generate UUID based on the EID\n  const char hex[] = \"0123456789abcdef\";\n  this->uuid = \"7fe8a8c1-f48c-3509-ac5c-97c3\";\n  for (int i = 0; i < 8; i++) {\n    this->uuid+=hex[(EID>>(i-7)*4)&0xf];\n  }\n\n  setUUID(this->uuid, true);\n\n  // Ignore this user if it's the server console\n  if (this->UID != SERVER_CONSOLE_UID)\n  {\n    ServerInstance->users().insert(this);\n  }\n\n  for (int count = 0; count < 45; count ++)\n  {\n    inv[count] = Item(this, count);\n  }\n\n  invulnerable = false;\n  creative = false;\n}\n\nbool User::changeNick(std::string _nick)\n{\n  runAllCallback(\"PlayerNickPost\", nick.c_str(), _nick.c_str());\n\n  nick = _nick;\n\n  return true;\n}\n\nbool User::setUUID(std::string uuid, bool dashes)\n{\n  this->uuid = uuid;\n  std::string temp_uuid = this->uuid;\n  if (dashes)\n  {\n    temp_uuid.erase(temp_uuid.begin()+23);\n    temp_uuid.erase(temp_uuid.begin()+18);\n    temp_uuid.erase(temp_uuid.begin()+13);\n    temp_uuid.erase(temp_uuid.begin()+8);\n  } else {\n    this->uuid.insert(8, \"-\");\n    this->uuid.insert(13, \"-\");\n    this->uuid.insert(18, \"-\");\n    this->uuid.insert(23, \"-\");    \n  }\n  for (int i = 0; i < 16; i++) {\n    uuid_raw[i] = (hexToByte(temp_uuid[i*2])<<4)+hexToByte(temp_uuid[i*2+1]);\n  }\n  return true;\n}\n\nUser::~User()\n{\n  EVP_CIPHER_CTX_free(en);\n  EVP_CIPHER_CTX_free(de);\n  if (this->UID != SERVER_CONSOLE_UID)\n  {\n    event_del(getReadEvent());\n    event_free(getReadEvent());\n  }\n  if (this->UID != SERVER_CONSOLE_UID)\n  {\n    event_del(getWriteEvent());\n    event_free(getWriteEvent());\n  }\n\n  if (fd != -1)\n  {\n#ifdef WIN32\n    closesocket(fd);\n#else\n    close(fd);\n#endif\n  }\n\n  this->buffer.reset();\n  this->bufferCrypted.reset();\n\n  // Create a temp array since the mapKnown is altered by the delKnown() function\n  std::vector<vec> tempMapKnown = mapKnown;\n\n  // Remove all known chunks\n  for (uint32_t i = 0; i < tempMapKnown.size(); i++)\n  {\n    delKnown(tempMapKnown[i].x(), tempMapKnown[i].z());\n  }\n\n  std::set<User*>::iterator user_set_it = ServerInstance->users().find(this);\n  if (user_set_it != ServerInstance->users().end())\n  {\n    ServerInstance->users().erase(user_set_it);\n  }\n\n  if (logged)\n  {\n    ServerInstance->chat()->sendMsg(this, this->nick + \" disconnected!\", Chat::OTHERS);\n    //LOG2(WARNING, this->nick + \" removed!\");\n    this->saveData();\n\n    // Send signal to everyone that the entity is destroyed\n    Packet pkt = Protocol::destroyEntity(this->UID);\n    this->sendOthers(pkt);\n\n    pkt = Protocol::PlayerListItemRemoveSingle(this->uuid_raw);\n    this->sendOthers(pkt);\n\n    //If still holding something, dump the items to ground\n    if (inventoryHolding.getType() != -1)\n    {\n      ServerInstance->map(pos.map)->createPickupSpawn((int)pos.x, (int)pos.y, (int)pos.z,\n                                                      inventoryHolding.getType(), inventoryHolding.getCount(),\n                                                      inventoryHolding.getHealth(), this);\n      inventoryHolding.setType(-1);\n    }\n\n    //Close open inventory\n    if (isOpenInv)\n    {\n      ServerInstance->inventory()->windowClose(this, openInv.type, openInv.x, openInv.y, openInv.z);\n    }\n\n\n  }\n\n  if (fd != -1 && logged)\n  {\n    runAllCallback(\"PlayerQuitPost\",nick.c_str());\n  }\n}\n\nbool User::sendLoginInfo()\n{\n  // Load user data\n  loadData();\n\n  writePacket(Protocol::setCompression(256));\n  this->compression = 256;\n\n  // This packet moves gameState to \"play\"\n  writePacket(Protocol::loginSuccess(this->uuid, this->nick));\n  this->gameState++;\n\n  // Login OK package\n  writePacket(Protocol::joinGame(UID));\n  setGameMode(gamemode);\n  \n  \n\n  // Send spawn position\n  writePacket(Protocol::spawnPosition(int(pos.x), int(pos.y + 2), int(pos.z)));\n  writePacket(Protocol::timeUpdate(ServerInstance->map(pos.map)->mapTime));\n\n  writePacket(Protocol::playerAbilities(5, 0.1, 0.2));\n\n  writePacket(Protocol::playerPositionAndLook(pos.x, pos.y, pos.z, pos.yaw, pos.pitch, 0));\n  \n  // Put nearby chunks to queue\n  for (int x = -viewDistance; x <= viewDistance; x++)\n  {\n    for (int z = -viewDistance; z <= viewDistance; z++)\n    {\n      addQueue((int32_t)pos.x / 16 + x, (int32_t)pos.z / 16 + z);\n    }\n  }\n  // Push chunks to user\n  pushMap(true);\n\n\n  const std::vector<MobPtr>& mobs = ServerInstance->mobs()->getAll();\n\n  for (std::vector<MobPtr>::const_iterator i = mobs.begin(); i != mobs.end(); ++i)\n  {\n    if (pos.map == (*i)->map && (*i)->spawned)\n    {\n      writePacket(Protocol::mobSpawn(**i));\n    }\n  }\n  \n\n  logged = true;\n  \n  for (int i = 1; i < 45; i++)\n  {\n    inv[i].ready = true;\n    inv[i].sendUpdate();\n  }\n\n  spawnOthers();\n\n  sethealth(health);\n\n  spawnUser((int32_t)pos.x * 32, (int32_t)((pos.y + 2) * 32), (int32_t)pos.z * 32);\n\n  // Teleport player (again)\n  teleport(pos.x, pos.y + 2, pos.z);\n\n\n\n  //ServerInstance->chat()->sendMsg(this, nick + \" connected!\", Chat::ALL);\n\n  return true;\n}\n\n// Kick player\nbool User::kick(std::string kickMsg)\n{\n  writePacket(Protocol::disconnect(\"{\\\"text\\\": \\\"\"+json_esc(kickMsg)+\"\\\"}\"));\n  runAllCallback(\"PlayerKickPost\",nick.c_str(), kickMsg.c_str());\n\n  LOG2(WARNING, nick + \" kicked. Reason: \" + kickMsg);\n\n  return true;\n}\n\nbool User::mute(std::string muteMsg)\n{\n  if (!muteMsg.empty())\n  {\n    muteMsg = MC_COLOR_YELLOW + \"You have been muted.  Reason: \" + muteMsg;\n  }\n  else\n  {\n    muteMsg = MC_COLOR_YELLOW + \"You have been muted. \";\n  }\n\n  ServerInstance->chat()->sendMsg(this, muteMsg, Chat::USER);\n  this->muted = true;\n  LOG2(WARNING, nick + \" muted. Reason: \" + muteMsg);\n  return true;\n}\n\nbool User::unmute()\n{\n  ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"You have been unmuted.\", Chat::USER);\n  this->muted = false;\n  LOG2(WARNING, nick + \" unmuted.\");\n  return true;\n}\n\nbool User::toggleDND()\n{\n  if (!this->dnd)\n  {\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"You have enabled 'Do Not Disturb' mode.\", Chat::USER);\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"You will no longer see chat or private messages.\", Chat::USER);\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"Type /dnd again to disable 'Do Not Disturb' mode.\", Chat::USER);\n    this->dnd = true;\n  }\n  else\n  {\n    this->dnd = false;\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"You have disabled 'Do Not Disturb' mode.\", Chat::USER);\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"You can now see chat and private messages.\", Chat::USER);\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"Type /dnd again to enable 'Do Not Disturb' mode.\", Chat::USER);\n  }\n  return this->dnd;\n}\n\nbool User::isAbleToCommunicate(std::string communicateCommand)\n{\n  // Check if this is chat or a regular command and prefix with a slash accordingly\n  if (communicateCommand != \"chat\")\n  {\n    communicateCommand = \"/\" + communicateCommand;\n  }\n\n  if (this->muted)\n  {\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"You cannot \" + communicateCommand + \" while muted.\", Chat::USER);\n    return false;\n  }\n  if (this->dnd)\n  {\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"You cannot \" + communicateCommand + \" while in 'Do Not Disturb' mode.\", Chat::USER);\n    ServerInstance->chat()->sendMsg(this, MC_COLOR_YELLOW + \"Type /dnd to disable.\", Chat::USER);\n    return false;\n  }\n  return true;\n}\n\nbool User::loadData()\n{\n  std::string infile = ServerInstance->map(0)->mapDirectory + \"/players/\" + this->nick + \".dat\";\n  // Player data will ALWAYS use the first world in your map\n\n  struct stat stFileInfo;\n  if (stat(infile.c_str(), &stFileInfo) != 0)\n  {\n    return false;\n  }\n\n  NBT_Value*  playerRoot = NBT_Value::LoadFromFile(infile.c_str());\n  NBT_Value& nbtPlayer = *playerRoot;\n  if (playerRoot == NULL)\n  {\n    LOGLF(\"Failed to open player file\");\n    return false;\n  }\n\n  std::vector<NBT_Value*>* _pos = nbtPlayer[\"Pos\"]->GetList();\n  pos.x = (double)(*(*_pos)[0]);\n  pos.y = (double)(*(*_pos)[1]);\n  pos.z = (double)(*(*_pos)[2]);\n\n  health = *nbtPlayer[\"Health\"];\n  gamemode = (int)*nbtPlayer[\"playerGameType\"] == 1 ? User::Creative : User::Survival;\n\n  std::vector<NBT_Value*>* rot = nbtPlayer[\"Rotation\"]->GetList();\n  pos.yaw = (float)(*(*rot)[0]);\n  pos.yaw = (float)(*(*rot)[1]);\n\n  std::vector<NBT_Value*>* _inv = nbtPlayer[\"Inventory\"]->GetList();\n  std::vector<NBT_Value*>::iterator iter = _inv->begin(), end = _inv->end();\n\n  for (; iter != end ; iter++)\n  {\n    int8_t slot, count;\n    int16_t damage, item_id;\n\n    slot    = *(**iter)[\"Slot\"];\n    count   = *(**iter)[\"Count\"];\n    damage  = *(**iter)[\"Damage\"];\n    item_id = *(**iter)[\"id\"];\n    if (item_id == 0 || count < 1)\n    {\n      item_id = -1;\n      count   =  0;\n    }\n\n    // Main inventory slot, converting 0-35 slots to 9-44\n    if (slot >= 0 && slot <= 35)\n    {\n      inv[(uint8_t)slot + 9].setCount(count);\n      inv[(uint8_t)slot + 9].setHealth(damage);\n      inv[(uint8_t)slot + 9].setType(item_id);\n    }\n    // Crafting, converting 80-83 slots to 1-4\n    else if (slot >= 80 && slot <= 83)\n    {\n      inv[(uint8_t)slot - 79].setCount(count);\n      inv[(uint8_t)slot - 79].setHealth(damage);\n      inv[(uint8_t)slot - 79].setType(item_id);\n    }\n    // Equipped, converting 100-103 slots to 8-5 (reverse order!)\n    else if (slot >= 100 && slot <= 103)\n    {\n      inv[(uint8_t)8 + (100 - slot)].setCount(count);\n      inv[(uint8_t)8 + (100 - slot)].setHealth(damage);\n      inv[(uint8_t)8 + (100 - slot)].setType(item_id);\n    }\n  }\n  delete playerRoot;\n\n  return true;\n}\n\nbool User::saveData()\n{\n  std::string outfile = ServerInstance->map(0)->mapDirectory + \"/players/\" + this->nick + \".dat\";\n  // Try to create parent directories if necessary\n  struct stat stFileInfo;\n  if (stat(outfile.c_str(), &stFileInfo) != 0)\n  {\n    std::string outdir = ServerInstance->map(0)->mapDirectory + \"/players\";\n\n    if (stat(outdir.c_str(), &stFileInfo) != 0)\n    {\n      if (!makeDirectory(outdir))\n      {\n        return false;\n      }\n    }\n  }\n\n  NBT_Value val(NBT_Value::TAG_COMPOUND);\n  val.Insert(\"OnGround\", new NBT_Value((int8_t)1));\n  val.Insert(\"Air\", new NBT_Value((int16_t)300));\n  val.Insert(\"AttackTime\", new NBT_Value((int16_t)0));\n  val.Insert(\"DeathTime\", new NBT_Value((int16_t)0));\n  val.Insert(\"Fire\", new NBT_Value((int16_t) - 20));\n  val.Insert(\"Health\", new NBT_Value((int16_t)health));\n  val.Insert(\"HurtTime\", new NBT_Value((int16_t)0));\n  val.Insert(\"FallDistance\", new NBT_Value(54.f));\n  val.Insert(\"playerGameType\", new NBT_Value(creative ? 1 : 0));\n\n  NBT_Value* nbtInv = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND);\n\n  char itemslot = 0;\n  // Start with main items\n  for (int slotid = 9; slotid < 45; slotid++, itemslot++)\n  {\n    if (inv[(uint8_t)slotid].getCount() && inv[(uint8_t)slotid].getType() != 0 && inv[(uint8_t)slotid].getType() != -1)\n    {\n      NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n      val->Insert(\"Count\", new NBT_Value((int8_t)inv[(uint8_t)slotid].getCount()));\n      val->Insert(\"Slot\", new NBT_Value((int8_t)itemslot));\n      val->Insert(\"Damage\", new NBT_Value((int16_t)inv[(uint8_t)slotid].getHealth()));\n      val->Insert(\"id\", new NBT_Value((int16_t)inv[(uint8_t)slotid].getType()));\n      nbtInv->GetList()->push_back(val);\n    }\n  }\n  // Crafting slots\n  itemslot = 80;\n  for (int slotid = 1; slotid < 6; slotid++, itemslot++)\n  {\n    if (inv[(uint8_t)slotid].getCount() && inv[(uint8_t)slotid].getType() != 0 && inv[(uint8_t)slotid].getType() != -1)\n    {\n      NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n      val->Insert(\"Count\", new NBT_Value((int8_t)inv[(uint8_t)slotid].getCount()));\n      val->Insert(\"Slot\", new NBT_Value((int8_t)itemslot));\n      val->Insert(\"Damage\", new NBT_Value((int16_t)inv[(uint8_t)slotid].getHealth()));\n      val->Insert(\"id\", new NBT_Value((int16_t)inv[(uint8_t)slotid].getType()));\n      nbtInv->GetList()->push_back(val);\n    }\n  }\n\n  // Equipped items last\n  itemslot = 103;\n  for (int slotid = 5; slotid < 9; slotid++, itemslot--)\n  {\n    if (inv[(uint8_t)slotid].getCount() && inv[(uint8_t)slotid].getType() != 0 && inv[(uint8_t)slotid].getType() != -1)\n    {\n      NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n      val->Insert(\"Count\", new NBT_Value((int8_t)inv[(uint8_t)slotid].getCount()));\n      val->Insert(\"Slot\", new NBT_Value((int8_t)itemslot));\n      val->Insert(\"Damage\", new NBT_Value((int16_t)inv[(uint8_t)slotid].getHealth()));\n      val->Insert(\"id\", new NBT_Value((int16_t)inv[(uint8_t)slotid].getType()));\n      nbtInv->GetList()->push_back(val);\n    }\n  }\n\n\n  val.Insert(\"Inventory\", nbtInv);\n\n  NBT_Value* nbtPos = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_DOUBLE);\n  nbtPos->GetList()->push_back(new NBT_Value((double)pos.x));\n  nbtPos->GetList()->push_back(new NBT_Value((double)pos.y));\n  nbtPos->GetList()->push_back(new NBT_Value((double)pos.z));\n  val.Insert(\"Pos\", nbtPos);\n\n\n  NBT_Value* nbtRot = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_FLOAT);\n  nbtRot->GetList()->push_back(new NBT_Value((float)pos.yaw));\n  nbtRot->GetList()->push_back(new NBT_Value((float)pos.pitch));\n  val.Insert(\"Rotation\", nbtRot);\n\n\n  NBT_Value* nbtMotion = new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_DOUBLE);\n  nbtMotion->GetList()->push_back(new NBT_Value((double)0.0));\n  nbtMotion->GetList()->push_back(new NBT_Value((double)0.0));\n  nbtMotion->GetList()->push_back(new NBT_Value((double)0.0));\n  val.Insert(\"Motion\", nbtMotion);\n\n  val.SaveToFile(outfile);\n\n  return true;\n\n}\n\n\nbool User::updatePosM(double x, double y, double z, size_t map, double stance)\n{\n  if (map != pos.map && logged)\n  {\n\n    // Loop every loaded chunk to make sure no user pointers are left!\n\n    for (ChunkMap::const_iterator it = ServerInstance->map(pos.map)->chunks.begin(); it != ServerInstance->map(pos.map)->chunks.end(); ++it)\n    {\n      it->second->users.erase(this);\n\n      if (it->second->users.empty())\n      {\n        ServerInstance->map(pos.map)->releaseMap(it->first.first, it->first.second);\n      }\n    }\n\n    // TODO despawn players who are no longer in view\n    // TODO despawn self to players on last world\n    pos.map = map;\n    pos.x = x;\n    pos.y = y;\n    pos.z = z;\n    LOG2(INFO, \"World changing\");\n    // TODO spawn self to nearby players\n    // TODO spawn players who are NOW in view\n    return false;\n  }\n  updatePos(x, y, z, stance);\n  return true;\n}\n\nbool User::updatePos(double x, double y, double z, double stance)\n{\n\n  // Riding other entity?\n  if (y == -999)\n  {\n    // attachedTo\n    // ToDo: Get pos from minecart/player/boat\n    return false;\n  }\n\n  if (logged)\n  {\n    sChunk* newChunk = ServerInstance->map(pos.map)->loadMap(blockToChunk((int32_t)x), blockToChunk((int32_t)z));\n    sChunk* oldChunk = ServerInstance->map(pos.map)->loadMap(blockToChunk((int32_t)pos.x), blockToChunk((int32_t)pos.z));\n\n    if (!newChunk || !oldChunk)\n    {\n      LOG2(WARNING, \"failed to update user position\");\n      return false;\n    }\n\n    if (newChunk == oldChunk)\n    {\n      Packet telePacket = Protocol::entityTeleport(UID, x, y, z, pos.yaw, pos.pitch);\n      newChunk->sendPacket(telePacket, this);\n    }\n    else\n    {\n      std::list<User*> toremove;\n      std::list<User*> toadd;\n\n      sChunk::userBoundary(oldChunk, toremove, newChunk, toadd);\n\n      /// update this player's pos for others\n\n      Packet dtPkt = Protocol::destroyEntity(UID);\n      std::list<User*>::iterator iter = toremove.begin(), end = toremove.end();\n      for (; iter != end ; iter++)\n      {\n        (*iter)->writePacket(dtPkt);\n\n        this->writePacket(Protocol::destroyEntity((*iter)->UID));\n      }\n\n      Packet spawnPkt = Protocol::spawnPlayer(UID, uuid_raw, nick, (float)health, x, y, z, pos.yaw, pos.pitch, curItem);\n      iter = toadd.begin(), end = toadd.end();\n      for (; iter != end ; iter++)\n      {\n        (*iter)->writePacket(spawnPkt);\n\n        this->writePacket(\n              Protocol::spawnPlayer((*iter)->UID, (*iter)->uuid_raw, (*iter)->nick, (float)(*iter)->health, (*iter)->pos, (*iter)->curItem));\n      }\n\n      Packet tpPkt = Protocol::entityTeleport(UID, x, y, z, pos.yaw, pos.pitch);\n\n      newChunk->sendPacket(tpPkt,this);\n\n      std::vector<vec> removeQueue;\n\n      // Check if known chunks are out of view distance now\n      for (vec& chunk : mapKnown)\n      {\n        if (!withinViewDistance(chunk.x(), newChunk->x) || !withinViewDistance(chunk.z(), newChunk->z))\n        { \n          removeQueue.push_back(vec(chunk.x(), 0, chunk.z()));          \n        }\n      }\n\n      \n      // ..or chunks in send queue for the player\n      for (vec& chunk : mapQueue)\n      {\n        if (!withinViewDistance(chunk.x(), newChunk->x) || !withinViewDistance(chunk.z(), newChunk->z))\n        {\n          removeQueue.push_back(vec(chunk.x(), 0, chunk.z()));\n        }\n      }\n\n      // Push to queue\n      for (vec& chunk : removeQueue)\n      {\n        addRemoveQueue(chunk.x(), chunk.z());\n      }\n\n      for (int mapx = newChunk->x - viewDistance; mapx <= newChunk->x + viewDistance; mapx++)\n      {\n        for (int mapz = newChunk->z - viewDistance; mapz <= newChunk->z + viewDistance; mapz++)\n        {\n          if (!withinViewDistance(mapx, oldChunk->x) || !withinViewDistance(mapz, oldChunk->z))\n          {\n            addQueue(mapx, mapz);\n          }\n        }\n      }\n    }\n\n    if (newChunk->items.size())\n    {\n      // Loop through items and check if they are close enought to be picked up\n      for (std::vector<spawnedItem*>::iterator iter = newChunk->items.begin(), end = newChunk->items.end(); iter != end; ++iter)\n      {\n        // No more than 2 blocks away\n        if (abs((int32_t)x - ((*iter)->pos.x() / 32)) < 2 &&\n            abs((int32_t)y - ((*iter)->pos.y() / 32)) < 2 &&\n            abs((int32_t)z - ((*iter)->pos.z() / 32)) < 2)\n        {\n          // Dont pickup own spawns right away\n          if ((*iter)->spawnedBy != this->UID || (*iter)->spawnedAt + 2 < time(NULL))\n          {\n            // Check player inventory for space!\n            if (ServerInstance->inventory()->isSpace(this, (*iter)->item, (*iter)->count))\n            {\n              // Send player collect item packet\n              writePacket(Protocol::collectItem((*iter)->EID, UID));\n\n              // Send everyone destroy_entity-packet\n              Packet pkt = Protocol::destroyEntity((*iter)->EID);\n              newChunk->sendPacket(pkt);\n\n              // Add items to inventory\n              ServerInstance->inventory()->addItems(this, (*iter)->item, (*iter)->count, (*iter)->health);\n\n              ServerInstance->map(pos.map)->items.erase((*iter)->EID);\n              delete *iter;\n              iter = newChunk->items.erase(iter);\n              end = newChunk->items.end();\n\n              if (iter == end)\n              {\n                break;\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (ServerInstance->m_damage_enabled)\n  {\n    uint8_t type, meta;\n    if ((std::floor(pos.y - 0.5) < 256) && LOADBLOCK(pos.x, pos.y - 0.5, pos.z))\n    {\n      switch (type)\n      {\n      case BLOCK_AIR:\n      case BLOCK_SAPLING:\n      case BLOCK_YELLOW_FLOWER:\n      case BLOCK_RED_ROSE:\n      case BLOCK_BROWN_MUSHROOM:\n      case BLOCK_RED_MUSHROOM:\n      case BLOCK_TORCH:\n      case BLOCK_FIRE:\n      case BLOCK_REDSTONE_WIRE:\n      case BLOCK_CROPS:\n      case BLOCK_MINECART_TRACKS:\n      case BLOCK_LEVER:\n      case BLOCK_REDSTONE_TORCH_OFF:\n      case BLOCK_REDSTONE_TORCH_ON:\n      case BLOCK_STONE_BUTTON:\n      case BLOCK_SNOW:\n      case BLOCK_REED:\n        fallDistance += this->pos.y - y;\n        //if(fallDistance<0){ fallDistance=0; }\n        break;\n      case BLOCK_WATER:\n      case BLOCK_STATIONARY_WATER:\n        fallDistance = 0;\n        break;\n      default:\n        if (fallDistance > 3)\n        {\n          sethealth(std::max(0, health - int(fallDistance - 4)));\n        }\n        fallDistance = 0;\n        break;\n      }\n    }\n  }\n  this->pos.x      = x;\n  this->pos.y      = y;\n  this->pos.z      = z;\n  this->pos.stance = stance;\n  curChunk.x() = (int)(x / 16);\n  curChunk.z() = (int)(z / 16);\n  checkEnvironmentDamage();\n  return true;\n}\n\nbool User::checkOnBlock(int32_t x, int16_t y, int32_t z)\n{\n  const double diffX = x - this->pos.x;\n  const double diffZ = z - this->pos.z;\n\n  if ((y == (int)this->pos.y)\n      && (diffZ > -1.3 && diffZ < 0.3)\n      && (diffX > -1.3 && diffX < 0.3))\n  {\n    return true;\n  }\n  return false;\n}\n\nbool User::updateLook(float yaw, float pitch)\n{\n\n  sChunk* chunk = ServerInstance->map(pos.map)->getChunk(blockToChunk((int32_t)pos.x), blockToChunk((int32_t)pos.z));\n  if (chunk != NULL)\n  {\n    chunk->sendPacket(Protocol::entityLook(UID, yaw, pitch), this);\n    chunk->sendPacket(Protocol::entityHeadLook(UID, angleToByte(yaw)), this);\n  }\n\n  this->pos.yaw   = yaw;\n  this->pos.pitch = pitch;\n  return true;\n}\n\nbool User::sendOthers(const Packet& packet)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd != this->fd && (*it)->logged && (packet.firstwrite() != PACKET_OUT_CHAT_MESSAGE || !((*it)->dnd)))\n    {\n      (*it)->writePacket(packet);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendOthers(uint8_t* data, size_t len)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd != this->fd && (*it)->logged && !((*it)->dnd && data[0] == PACKET_OUT_CHAT_MESSAGE))\n    {\n      (*it)->buffer.addToWrite(data, len);\n    }\n  }\n\n  return true;\n}\n\nint8_t User::relativeToBlock(const int32_t x, const int16_t y, const int32_t z)\n{\n  int8_t direction;\n  double diffX, diffZ;\n  diffX = x - this->pos.x;\n  diffZ = z - this->pos.z;\n\n  if (diffX > diffZ)\n  {\n    // We compare on the x axis\n    if (diffX > 0)\n    {\n      direction = BLOCK_BOTTOM;\n    }\n    else\n    {\n      direction = BLOCK_EAST;\n    }\n  }\n  else\n  {\n    // We compare on the z axis\n    if (diffZ > 0)\n    {\n      direction = BLOCK_SOUTH;\n    }\n    else\n    {\n      direction = BLOCK_NORTH;\n    }\n  }\n  return direction;\n}\n\nbool User::sendAll(const Packet& packet)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged)\n    {\n      (*it)->writePacket(packet);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendAll(uint8_t* data, size_t len)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged)\n    {\n      (*it)->buffer.addToWrite(data, len);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendAdmins(const Packet& packet)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged && IS_ADMIN((*it)->permissions))\n    {\n      (*it)->writePacket(packet);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendAdmins(uint8_t* data, size_t len)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged && IS_ADMIN((*it)->permissions))\n    {\n      (*it)->buffer.addToWrite(data, len);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendOps(const Packet& packet)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged && IS_ADMIN((*it)->permissions))\n    {\n      (*it)->writePacket(packet);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendOps(uint8_t* data, size_t len)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged && IS_ADMIN((*it)->permissions))\n    {\n      (*it)->buffer.addToWrite(data, len);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendGuests(const Packet& packet)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged && IS_ADMIN((*it)->permissions))\n    {\n      (*it)->writePacket(packet);\n    }\n  }\n\n  return true;\n}\n\nbool User::sendGuests(uint8_t* data, size_t len)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd && (*it)->logged && IS_ADMIN((*it)->permissions))\n    {\n      (*it)->buffer.addToWrite(data, len);\n    }\n  }\n\n  return true;\n}\n\nbool User::addQueue(int x, int z)\n{\n  vec newMap(x, 0, z);\n\n  // Make sure this chunk is not being removed, if it is, delete it from remove queue\n  for (unsigned int i = 0; i < mapRemoveQueue.size(); i++)\n  {\n    if (mapRemoveQueue[i].x() == newMap.x() && mapRemoveQueue[i].z() == newMap.z())\n    {\n      mapRemoveQueue.erase(mapRemoveQueue.begin() + i);\n      break;\n    }\n  }\n\n  for (unsigned int i = 0; i < mapQueue.size(); i++)\n  {\n    // Check for duplicates\n    if (mapQueue[i].x() == newMap.x() && mapQueue[i].z() == newMap.z())\n    {\n      return false;\n    }\n  }\n\n  for (unsigned int i = 0; i < mapKnown.size(); i++)\n  {\n    // Check for duplicates\n    if (mapKnown[i].x() == newMap.x() && mapKnown[i].z() == newMap.z())\n    {\n      return false;\n    }\n  }\n\n  this->mapQueue.push_back(newMap);\n\n  return true;\n}\n\nbool User::addRemoveQueue(int x, int z)\n{\n  vec newMap(x, 0, z);\n\n  for (unsigned int i = 0; i < mapQueue.size(); i++)\n  {\n    // Check if the chunk is going to be loaded, and erase it from the queue\n    if (mapQueue[i].x() == newMap.x() && mapQueue[i].z() == newMap.z())\n    {\n      mapQueue.erase(mapQueue.begin() + i);\n      break;\n    }\n  }\n\n  this->mapRemoveQueue.push_back(newMap);\n\n  return true;\n}\n\nbool User::addKnown(int x, int z)\n{\n  vec newMap(x, 0, z);\n  sChunk* chunk = ServerInstance->map(pos.map)->getChunk(x, z);\n  if (chunk == NULL)\n  {\n    return false;\n  }\n\n  chunk->users.insert(this);\n  this->mapKnown.push_back(newMap);\n\n  return true;\n}\n\nbool User::delKnown(int x, int z)\n{\n  sChunk* chunk = ServerInstance->map(pos.map)->getChunk(x, z);\n  if (chunk != NULL)\n  {\n    chunk->users.erase(this);\n  }\n\n  for (unsigned int i = 0; i < mapKnown.size(); i++)\n  {\n    if (mapKnown[i].x() == x && mapKnown[i].z() == z)\n    {\n      mapKnown.erase(mapKnown.begin() + i);\n      return true;\n    }\n  }\n\n  return false;\n}\n\nbool User::popMap()\n{\n  // If map in queue, push it to client\n  while (this->mapRemoveQueue.size())\n  {\n    // Delete from known list\n    delKnown(mapRemoveQueue[0].x(), mapRemoveQueue[0].z());\n\n    // Send unload packet to client\n    writePacket(Protocol::chunkDataUnload(mapRemoveQueue[0].x(), mapRemoveQueue[0].z()));\n\n    // Remove from queue\n    mapRemoveQueue.erase(mapRemoveQueue.begin());\n\n    // return true;\n  }\n\n  return false;\n}\n\nnamespace\n{\n\nclass DistanceComparator\n{\nprivate:\n  vec target;\npublic:\n  DistanceComparator(vec tgt) : target(tgt)\n  {\n    target.y() = 0;\n  }\n  bool operator()(vec a, vec b) const\n  {\n    a.y() = 0;\n    b.y() = 0;\n    return vec::squareDistance(a, target) <\n        vec::squareDistance(b, target);\n  }\n};\n\n}\n\nbool User::pushMap(bool login)\n{\n  //Dont send all at once\n  int maxcount = 5;\n  // If map in queue, push it to client\n  while (this->mapQueue.size() > 0 && maxcount > 0)\n  {\n    maxcount--;\n    // Sort by distance from center\n    vec target(static_cast<int>(pos.x / 16),\n               static_cast<int>(pos.y / 16),\n               static_cast<int>(pos.z / 16));\n    sort(mapQueue.begin(), mapQueue.end(), DistanceComparator(target));\n\n    ServerInstance->map(pos.map)->sendToUser(this, mapQueue[0].x(), mapQueue[0].z(), login);\n\n    // Add this to known list\n    addKnown(mapQueue[0].x(), mapQueue[0].z());\n\n    // Remove from queue\n    mapQueue.erase(mapQueue.begin());\n  }\n\n  return true;\n}\n\nbool User::teleport(double x, double y, double z, size_t map)\n{\n  if (map == size_t(-1))\n  {\n    map = pos.map;\n  }\n  if (y > 255.0)\n  {\n    y = 255.0;\n    LOGLF(\"Player Attempted to teleport with y > 255.0\");\n  }\n  if (map == pos.map)\n  {\n    writePacket(Protocol::playerPositionAndLook(x, y, z, 0, 0, 0));\n  }\n\n  //Also update pos for other players\n  updatePosM(x, y, z, map, pos.stance);\n  pushMap();\n  pushMap();\n  pushMap();\n  updatePosM(x, y, z, map, pos.stance);\n  return true;\n}\n\nbool User::spawnUser(int x, int y, int z)\n{\n  Packet pkt = Protocol::spawnPlayer(UID, uuid_raw, nick, (float)health, x, y, z, 0, 0, 0);\n  Packet playerListAddPkt = Protocol::PlayerListItemAddSingle(uuid_raw, nick, gamemode, 10, properties);\n  sChunk* chunk = ServerInstance->map(pos.map)->getChunk(blockToChunk(x >> 5), blockToChunk(z >> 5));\n  if (chunk != NULL)\n  {\n    chunk->sendPacket(playerListAddPkt);\n    chunk->sendPacket(pkt, this);    \n  }\n  return true;\n}\n\nbool User::spawnOthers()\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->logged && (*it)->UID != this->UID)\n    {\n      this->writePacket(Protocol::PlayerListItemAddSingle((*it)->uuid_raw, (*it)->nick, (*it)->gamemode, 10, (*it)->properties));\n      this->writePacket(Protocol::spawnPlayer((*it)->UID, (*it)->uuid_raw, (*it)->nick, (float)(*it)->health, (*it)->pos.x, (*it)->pos.y, (*it)->pos.z, 0, 0, 0));      \n      for (int b = 0; b < 5; b++)\n      {\n        const int n = b == 0 ? (*it)->curItem + 36 : 9 - b;\n        this->writePacket(Protocol::entityEquipment((*it)->UID, b, (*it)->inv[n]));\n      }\n      this->writePacket(Protocol::entityHeadLook((*it)->UID,angleToByte((*it)->pos.yaw)));\n    }\n  }\n  return true;\n}\n\nvoid User::checkEnvironmentDamage()\n{\n  const double yVal = std::floor(pos.y - 0.5);\n\n  if (yVal > 255.0)\n  {\n    return;\n  }\n\n  /// louisdx: This makes no sense at the moment; type is not initialized!\n  //uint8_t type, meta;\n  uint8_t type = 0, meta = 0;\n\n  int16_t d = 0;\n  /*\n  if (type == BLOCK_CACTUS && LOADBLOCK(pos.x, yVal, pos.z))\n  {\n    d = 1;\n  }\n  */\n\n  const double xbit = pos.x - std::floor(pos.x);\n  const double zbit = pos.z - std::floor(pos.z);\n\n  if (xbit > 0.6)\n  {\n    LOADBLOCK(pos.x + 1, pos.y + 0.5, pos.z);\n    if (type == BLOCK_CACTUS)\n    {\n      d = 1;\n    }\n  }\n  else if (xbit < 0.4)\n  {\n    LOADBLOCK(pos.x - 1, pos.y + 0.5, pos.z);\n    if (type == BLOCK_CACTUS)\n    {\n      d = 1;\n    }\n  }\n  if (zbit > 0.6)\n  {\n    LOADBLOCK(pos.x, pos.y + 0.5, pos.z + 1);\n    if (type == BLOCK_CACTUS)\n    {\n      d = 1;\n    }\n  }\n  else if (zbit < 0.4)\n  {\n    LOADBLOCK(pos.x, pos.y + 0.5, pos.z - 1);\n    if (type == BLOCK_CACTUS)\n    {\n      d = 1;\n    }\n  }\n\n  if (LOADBLOCK(pos.x, pos.y + 0.5, pos.z))\n  {\n    if (type == BLOCK_LAVA || type == BLOCK_STATIONARY_LAVA)\n    {\n      d = 10;\n    }\n    else if (type == BLOCK_FIRE)\n    {\n      d = 5;\n    }\n  }\n\n  if(std::floor(pos.y + 1.5) > 255)\n  {\n    sethealth(std::max(0, health - d));\n    return;\n  }\n\n  if (LOADBLOCK(pos.x, pos.y + 1.5, pos.z))\n  {\n    switch (type)\n    {\n    case BLOCK_AIR:\n    case BLOCK_SAPLING:\n    case BLOCK_WATER:            // For a certain value of \"breathable\" ;)\n    case BLOCK_STATIONARY_WATER: // Water is treated seperatly\n    case BLOCK_YELLOW_FLOWER:\n    case BLOCK_RED_ROSE:\n    case BLOCK_BROWN_MUSHROOM:\n    case BLOCK_RED_MUSHROOM:\n    case BLOCK_TORCH:\n    case BLOCK_REDSTONE_WIRE:\n    case BLOCK_CROPS:\n    case BLOCK_LEVER:\n    case BLOCK_REDSTONE_TORCH_ON:\n    case BLOCK_REDSTONE_TORCH_OFF:\n    case BLOCK_SNOW:\n    case BLOCK_STONE_BUTTON:\n    case BLOCK_REED:\n    case BLOCK_PORTAL:\n    case BLOCK_LADDER:\n    case BLOCK_WOODEN_DOOR:\n    case BLOCK_IRON_DOOR:\n    case BLOCK_WALL_SIGN:\n    case BLOCK_SIGN_POST:\n      break;\n    default:\n      if (d == 0)\n      {\n        d = 1;\n      }\n      break;\n    }\n  }\n\n  sethealth(std::max(0, health - d));\n}\n\nbool User::sethealth(int userHealth)\n{\n  if (!logged)\n    return false;\n\n  health = min(max(userHealth, 0), 20);\n\n  if (health == userHealth)\n  {\n    return false;\n  }\n  if (userHealth < health)\n  {\n    // One hit per 2 seconds\n    if (time(NULL) - healthtimeout < 1)\n    {\n      return false;\n    }\n    sendAll(Protocol::animation(UID, ANIMATE_DAMAGE));\n    sendAll(Protocol::entityStatus(UID, ENTITY_STATUS_HURT));\n  }\n  healthtimeout = time(NULL);\n\n  health = userHealth;\n  writePacket(Protocol::updateHealth(userHealth));\n  return true;\n}\n\nbool User::respawn()\n{\n  this->health = 20;\n  this->timeUnderwater = 0;\n  writePacket(Protocol::respawn()); //FIXME: send the correct world id\n  sethealth(20);\n  Packet destroyPkt;\n  destroyPkt << Protocol::destroyEntity(UID);\n  sChunk* chunk = ServerInstance->map(pos.map)->getMapData(blockToChunk((int32_t)pos.x), blockToChunk((int32_t)pos.z));\n  if (chunk != NULL)\n  {\n    chunk->sendPacket(destroyPkt, this);\n  }\n\n  runCallbackUntilFalse(\"PlayerRespawn\",nick.c_str());\n  if (callbackReturnValue)\n  {\n    // In this case, the plugin teleports automatically\n  }\n  else\n  {\n    teleport(ServerInstance->map(pos.map)->spawnPos.x(), ServerInstance->map(pos.map)->spawnPos.y() + 2, ServerInstance->map(pos.map)->spawnPos.z(), 0);\n  }\n\n  Packet spawnPkt = Protocol::spawnPlayer(UID, uuid_raw, nick, (float)health, pos.x, pos.y, pos.z, pos.yaw, pos.pitch, curItem);  \n\n  chunk = ServerInstance->map(pos.map)->getMapData(blockToChunk((int32_t)pos.x), blockToChunk((int32_t)pos.z));\n  if (chunk != NULL)\n  {\n    chunk->sendPacket(spawnPkt, this);\n  }\n\n  return true;\n}\n\nbool User::dropInventory()\n{\n  for (int i = 1; i < 45; i++)\n  {\n    if (inv[i].getType() != -1)\n    {\n      ServerInstance->map(pos.map)->createPickupSpawn((int)pos.x, (int)pos.y, (int)pos.z, inv[i].getType(), inv[i].getCount(), inv[i].getHealth(), this);\n      inv[i].setType(-1);\n    }\n  }\n  return true;\n}\n\nbool User::isUnderwater()\n{\n  uint8_t topblock, topmeta;\n  const int y = int((pos.y - int(pos.y) <= 0.25) ? pos.y + 1 : pos.y + 2);\n\n  if (y > 127)\n  {\n    return false;\n  }\n\n  ServerInstance->map(pos.map)->getBlock((int)pos.x, y, (int)pos.z, &topblock, &topmeta);\n\n  if (topblock == BLOCK_WATER || topblock == BLOCK_STATIONARY_WATER)\n  {\n    if ((timeUnderwater / 5) > 15 && timeUnderwater % 5 == 0)  // 13 is Trial and Erorr\n    {\n      sethealth(health - 2);\n    }\n    timeUnderwater += 1;\n    return true;\n  }\n\n  timeUnderwater = 0;\n  return false;\n}\n\nstruct event* User::getReadEvent()\n{\n  return m_readEvent;\n}\n\nbool User::setReadEvent(struct event* new_event)\n{\n  m_readEvent = new_event;\n  return true;\n}\n\nstruct event* User::getWriteEvent()\n{\n  return m_writeEvent;\n}\n\nbool User::setWriteEvent(struct event* new_event)\n{\n  m_writeEvent = new_event;\n  return true;\n}\n\nstd::set<User*>& User::all()\n{\n  return ServerInstance->users();\n}\n\nbool User::isUser(int sock)\n{\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if ((*it)->fd == sock) return true;\n  }\n\n  return false;\n}\n\n// Not case-sensitive search\nUser* User::byNick(std::string nick)\n{\n  // Get coordinates\n  for (std::set<User*>::const_iterator it = ServerInstance->users().begin(); it != ServerInstance->users().end(); ++it)\n  {\n    if (strToLower((*it)->nick) == strToLower(nick))\n    {\n      return *it;\n    }\n  }\n  return NULL;\n}\n\n// Getter/Setter for item currently in hold\nint16_t User::currentItemSlot()\n{\n  return m_currentItemSlot;\n}\n\nvoid User::setCurrentItemSlot(int16_t item_slot)\n{\n  m_currentItemSlot = item_slot;\n}\n\nstd::string User::generateDigest()\n{\n  SHA_CTX context;\n  unsigned char md[20];\n  std::string out;\n  int i;\n  const char hex[] = \"0123456789abcdef\";\n\n  SHA1_Init(&context);\n  SHA1_Update(&context, (unsigned char*)ServerInstance->serverID.data(), ServerInstance->serverID.size());\n  SHA1_Update(&context, (unsigned char*)secret.data(), secret.size());\n  SHA1_Update(&context, (unsigned char*)ServerInstance->publicKey.data(), ServerInstance->publicKey.size());\n  SHA1_Final(md, &context);\n\n  if(md[0] & 0x80)\n  {\n    unsigned char carry = 1;\n    out = '-';\n    for (i = 19; i >= 0; i--)\n    {\n      unsigned short twocomp = (unsigned char)~md[i];\n      twocomp+=carry;\n      if(twocomp & 0xff00)\n      {\n        twocomp = twocomp&0xff;\n      }\n      else\n      {\n        carry = 0;\n      }\n      md[i] = (uint8_t)twocomp;\n    }\n  }\n\n  for (i = 0; i < 20; i++)\n  {\n    if(i || md[i]>>4)\n    {\n      out += hex[(md[i]>>4)];\n    }\n    if(i || md[i]>>4 || md[i]&0xf)\n    {\n      out += hex[(md[i]&0xf)];\n    }\n  }\n\n  return out;\n}\n\nbool User::setGameMode(User::GameMode gameMode)\n{\n  writePacket(Protocol::gameMode(3,gameMode));\n\n  invulnerable = gameMode == User::Creative;\n  creative = gameMode == User::Creative;\n  return true;\n}\n"
  },
  {
    "path": "src/user.h",
    "content": "/*\n    Copyright (c) 2012, The Mineserver Project\n    All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _USER_H\n#define _USER_H\n\n#include <vector>\n#include <set>\n\n#ifdef WIN32\n// This is needed for event to work on Windows.\n#define NOMINMAX\n#include <winsock2.h>\n#endif\n#include <event.h>\n\n#include \"vec.h\"\n#include \"inventory.h\"\n#include \"packets.h\"\n#include \"mineserver.h\"\n\n//#include \"chunkmap.h\"\n\nbool client_write(User *user);\n\n\n\nstruct UserProperty {\n  UserProperty() {};\n  UserProperty(std::string _name, std::string _value, std::string _signature):\n    name(_name), value(_value), signature(_signature) {};\n  std::string name;\n  std::string value;\n  std::string signature;\n};\n\nstruct position\n{\n  double x;\n  double y;\n  double z;\n  size_t map;\n  double stance;\n  float yaw;\n  float pitch;\n  position(): x(0), y(0), z(0), map(0)\n  { }\n};\n\nclass User\n{\npublic:\n\n  User(int sock, uint32_t EID);\n  ~User();\n\n  int fd;\n\n  //When we last received data from this user\n  time_t lastData;\n\n  //View distance in chunks -viewDistance <-> viewDistance\n  static const int viewDistance = 10;\n\n  std::string nick;\n  position pos;\n  int16_t health;\n\n  Item inv[45];\n  int16_t curItem;\n\n  /// gamemode\n  enum GameMode : uint8_t{\n      Survival=0,Creative\n  };\n\n  bool setGameMode(GameMode gameMode);\n\n  GameMode gamemode;\n  bool invulnerable;\n  bool creative; /// flying etc.\n\n  uint8_t action;\n  bool waitForData;\n  uint32_t write_err_count;\n  bool deleting;\n  bool logged;\n  bool muted;\n  bool dnd;\n  int32_t packetsPerSecond;\n  uint16_t timeUnderwater;\n  double fallDistance;\n  unsigned int UID;\n  std::string uuid;\n  uint8_t uuid_raw[16];\n  std::string temp_nick;\n  vec curChunk;\n  time_t healthtimeout;\n  uint16_t compression; // Protocol compression threshold\n\n  /* INVENTORY RELATED HELPERS */\n  Item inventoryHolding;\n  //Do we have an open _shared_ inventory?\n  bool isOpenInv;\n  //More info on the inventory\n  OpenInventory openInv;\n\n  std::string secret;\n  EVP_CIPHER_CTX* en, *de;\n  std::string generateDigest();\n  void initCipher()\n  {\n    unsigned char key[16], iv[16];\n    memcpy(&iv,secret.c_str(),16);\n    memcpy(&key,secret.c_str(),16);\n    en = EVP_CIPHER_CTX_new();\n    EVP_CIPHER_CTX_init(en);\n    EVP_EncryptInit_ex(en, EVP_aes_128_cfb8(), NULL, key, iv);\n    de = EVP_CIPHER_CTX_new();\n    EVP_CIPHER_CTX_init(de);\n    EVP_DecryptInit_ex(de, EVP_aes_128_cfb8(), NULL, key, iv);\n  }\n  bool crypted;\n  int uncryptedLeft;\n\n  bool serverAdmin;\n  int permissions; // bitmask for permissions. See permissions.h\n\n  int32_t attachedTo;\n\n  //Input buffer\n  Packet buffer;\n  Packet bufferCrypted;\n  int32_t packetLen;\n  uint8_t gameState;\n\n  static std::set<User*>& all();\n  static bool isUser(int sock);\n  static User* byNick(std::string nick);\n\n  bool changeNick(std::string _nick);\n  void checkEnvironmentDamage();\n\n  bool updatePos(double x, double y, double z, double stance);\n  bool updatePosM(double x, double y, double z, size_t map, double stance);\n  /** Check if the user is standing on this block */\n  bool checkOnBlock(int32_t x, int16_t y, int32_t z);\n  bool updateLook(float yaw, float pitch);\n  int8_t relativeToBlock(const int32_t x, const int16_t y, const int32_t z);\n\n  bool sendOthers(const Packet& packet);\n  bool sendOthers(uint8_t* data, size_t len);\n  static bool sendAll(const Packet& packet);\n  static bool sendAll(uint8_t* data, size_t len);\n  static bool sendAdmins(const Packet& packet);\n  static bool sendAdmins(uint8_t* data, size_t len);\n  static bool sendOps(const Packet& packet);\n  static bool sendOps(uint8_t* data, size_t len);\n  static bool sendGuests(const Packet& packet);\n  static bool sendGuests(uint8_t* data, size_t len);\n\n  //Login\n  bool sendLoginInfo();\n  bool setUUID(std::string uuid, bool stripDashes);\n\n  //Load/save player data from/to a file at <mapdir>/players/<nick>.dat\n  bool saveData();\n  bool loadData();\n\n  // Kick player\n  bool kick(std::string kickMsg);\n\n  // Chat blocking\n  bool mute(std::string muteMsg);\n  bool unmute();\n  bool toggleDND();\n  bool isAbleToCommunicate(std::string communicateCommand);\n\n  //Map related\n\n  //Map queue\n  std::vector<vec> mapQueue;\n\n  //Chunks needed to be removed from client\n  std::vector<vec> mapRemoveQueue;\n\n  //Known map pieces\n  std::vector<vec> mapKnown;\n\n  //Add map coords to queue\n  bool addQueue(int x, int z);\n\n  //Add map coords to remove queue\n  bool addRemoveQueue(int x, int z);\n\n  //Add known map piece\n  bool addKnown(int x, int z);\n\n  //Delete known map piece\n  bool delKnown(int x, int z);\n\n  //Push queued map data to client\n  bool pushMap(bool login = false);\n\n  //Push remove queued map data to client\n  bool popMap();\n\n  bool teleport(double x, double y, double z, size_t map = -1);\n  bool spawnUser(int x, int y, int z);\n  bool spawnOthers();\n  bool sethealth(int userHealth);\n  bool respawn();\n  bool dropInventory();\n  bool isUnderwater();\n\n  void clearLoadingMap();\n\n  // Getter/Setter for item currently in hold\n  int16_t currentItemSlot();\n  void setCurrentItemSlot(int16_t item_slot);\n\n\n  bool withinViewDistance(int a, int b)\n  {\n    return a > b ? (a - b) < viewDistance : (b - a) < viewDistance;\n  }\n\n  struct event* getReadEvent();\n  struct event* getWriteEvent();\n\n  bool setReadEvent(struct event* new_event);\n  bool setWriteEvent(struct event* new_event);\n\n  bool writePacket(const Packet &pkt) {\n    this->buffer.writePacket(pkt, this->compression);\n    client_write(this);\n    return true;\n  }\n\n  std::vector<UserProperty> properties;\n\nprivate:\n  event* m_readEvent;\n  event* m_writeEvent;\n\n  // Item currently in hold\n  int16_t m_currentItemSlot;\n};\n\n#endif\n"
  },
  {
    "path": "src/utf8.h",
    "content": "#ifndef _UTF8_H\n#define _UTF8_H\n\n\ntypedef union t_codepoint_tmp\n{\n  char c[7];\n  unsigned char u[7];\n} t_codepoint;\n\n/** Creates a UTF-8 representation of a single unicode codepoint.\n *  Will convert UCS2, UCS4 and UTF-32 to UTF-8.\n */\ninline void codepointToUTF8(unsigned int cp, t_codepoint * szOut)\n{\n  szOut->u[0] = szOut->u[1] = szOut->u[2] = szOut->u[3] = szOut->u[4] = szOut->u[5] = szOut->u[6] = 0;\n\n  size_t i = 0;\n\n  if (cp < 0x80)            // ASCII\n  {\n    szOut->u[i++] = (unsigned char) cp;\n  }\n  else if (cp < 0x800)      // Many common scripts\n  {\n    szOut->u[i++] = 0xC0 | ((cp) >> 6          );\n    szOut->u[i++] = 0x80 | ( cp          & 0x3F);\n  }\n  else if (cp < 0x10000)    // Basic Multilingual Plane\n  {\n    szOut->u[i++] = 0xE0 | ( (cp) >> 12        );\n    szOut->u[i++] = 0x80 | (((cp) >>  6) & 0x3F);\n    szOut->u[i++] = 0x80 | ( cp          & 0x3F);\n  }\n  else if (cp < 0x200000)   // All known planes up to Unicode 5.0 (?)\n  {\n    szOut->u[i++] = 0xF0 | ( (cp) >> 18        );\n    szOut->u[i++] = 0x80 | (((cp) >> 12) & 0x3F);\n    szOut->u[i++] = 0x80 | (((cp) >> 6)  & 0x3F);\n    szOut->u[i++] = 0x80 | (  cp         & 0x3F);\n  }\n  else if (cp < 0x4000000)  // Hypothetical\n  {\n    szOut->u[i++] = 0xF8 | ( (cp) >> 24        );\n    szOut->u[i++] = 0x80 | (((cp) >> 18) & 0x3F);\n    szOut->u[i++] = 0x80 | (((cp) >> 12) & 0x3F);\n    szOut->u[i++] = 0x80 | (((cp) >> 6)  & 0x3F);\n    szOut->u[i++] = 0x80 | (  cp         & 0x3F);\n  }\n  else if (cp < 0x80000000) // Hypothetical\n  {\n    szOut->u[i++] = 0xFC | ( (cp) >> 30        );\n    szOut->u[i++] = 0x80 | (((cp) >> 24) & 0x3F);\n    szOut->u[i++] = 0x80 | (((cp) >> 18) & 0x3F);\n    szOut->u[i++] = 0x80 | (((cp) >> 12) & 0x3F);\n    szOut->u[i++] = 0x80 | (((cp) >> 6)  & 0x3F);\n    szOut->u[i++] = 0x80 | (  cp         & 0x3F);\n  }\n  else\n  {\n    // Error, can only represent codepoints of length 31 bits.\n  }\n}\n\n\n/** Extracts one Unicode codepoint from a string in UTF-8 encoding; updates position.\n */\ninline unsigned int getOneCodepointFromUTF8(const std::string& str, size_t & position)\n{\n  if (position >= str.length()) return -1;\n\n  unsigned char data[7];\n  data[0] = str[position++];\n\n  if ((data[0] & 0x80) == 0) // first byte: 0xxxxxxx\n  {\n    // 1 code unit\n\n    return data[0];\n  }\n\n  else if ((data[0] & 0xE0) == 0xC0) // first byte: 110xxxxx\n  {\n    // 2 code units\n\n    if (position >= str.length()) { position = str.length(); return -1; }\n\n    data[1] = str[position++];\n\n    if ((data[1] & 0xC0) != 0x80) // second byte: 10xxxxxx\n    {\n      position = str.length();\n      return -1;\n    }\n\n    return ((data[0] & 0x1F) << 6) | (data[1] & 0x3F);\n  }\n\n  else if ((data[0] & 0xF0) == 0xE0) // first byte: 1110xxxx\n  {\n    // 3 code units\n\n    if (position + 1 >= str.length()) { position = str.length(); return -1; }\n\n    data[1] = str[position++];\n    data[2] = str[position++];\n\n    if ((data[1] & 0xC0) != 0x80 || (data[2] & 0xC0) != 0x80) // second and third byte: 10xxxxxx\n    {\n      position = str.length();\n      return -1;\n    }\n    return ((data[0] & 0x0F) << 12) | ((data[1] & 0x3F) << 6) | (data[2] & 0x3F);\n  }\n\n  else if ((data[0] & 0xF8) == 0xF0) // first byte: 11110xxx\n  {\n    // 4 code units\n\n    if (position + 2 >= str.length()) { position = str.length(); return -1; }\n\n    data[1] = str[position++];\n    data[2] = str[position++];\n    data[3] = str[position++];\n\n    if ((data[1] & 0xC0) != 0x80 || (data[2] & 0xC0) != 0x80 || (data[3] & 0xC0) != 0x80) // following bytes: 10xxxxxx\n    {\n      position = str.length();\n      return -1;\n    }\n\n    return ((data[0] & 0x07) << 18) | ((data[1] & 0x3F) << 12) | ((data[2] & 0x3F) << 6) | (data[3] & 0x3F);\n  }\n\n  else if ((data[0] & 0xFC) == 0xF8) // first byte: 111110xx\n  {\n    // 5 code units\n\n    if (position + 3 >= str.length()) { position = str.length(); return -1; }\n\n    data[1] = str[position++];\n    data[2] = str[position++];\n    data[3] = str[position++];\n    data[4] = str[position++];\n\n    if ((data[1] & 0xC0) != 0x80 || (data[2] & 0xC0) != 0x80 || (data[3] & 0xC0) != 0x80 || (data[4] & 0xC0) != 0x80) // following bytes: 10xxxxxx\n    {\n      position = str.length();\n      return -1;\n    }\n\n    return ((data[0] & 0x03) << 24) | ((data[1] & 0x3F) << 18) | ((data[2] & 0x3F) << 12) | ((data[3] & 0x3F) << 6) | (data[4] & 0x3F);\n  }\n\n  else if ((data[0] & 0xFE) == 0xFC)\n  {\n    // 6 code units\n\n    if (position + 4 >= str.length()) { position = str.length(); return -1; }\n\n    data[1] = str[position++];\n    data[2] = str[position++];\n    data[3] = str[position++];\n    data[4] = str[position++];\n    data[5] = str[position++];\n\n    if ((data[1] & 0xC0) != 0x80 || (data[2] & 0xC0) != 0x80 || (data[3] & 0xC0) != 0x80 || (data[4] & 0xC0) != 0x80 || (data[5] & 0xC0) != 0x80) // following bytes: 10xxxxxx\n    {\n      position = str.length();\n      return -1;\n    }\n\n    return ((data[0] & 0x01) << 30) | ((data[1] & 0x3F) << 24) | ((data[2] & 0x3F) << 18) | ((data[3] & 0x3F) << 12) | ((data[4] & 0x3F) << 6) | (data[5] & 0x3F);\n  }\n\n  else\n  {\n    position = str.length();\n    return -1;\n  }\n}\n\n\n/** This utility function creates a UCS2 \"string\" (actually a vector of uint16_t's) from\n *  a UTF-8-encoded input string. Non-BMP characters are replaced by 0xFFFD.\n */\ninline void makeUCS2MessageFromUTF8(const std::string & str, std::vector<uint16_t> & result)\n{\n  unsigned int codepoint;\n  result.clear();\n  result.reserve(str.length() * 2);\n\n  for (size_t position = 0; position < str.length(); )\n  {\n    codepoint = getOneCodepointFromUTF8(str, position);\n\n    // Break on error\n    if (codepoint == (unsigned int)(-1)) break;\n\n    // Check that the codepoint is in the BMP and valid, otherwise insert dummy character.\n    if (codepoint < 0xFFFE && (codepoint < 0xD800 || codepoint > 0xDFFF))\n    {\n      result.push_back(codepoint);\n    }\n    else\n    {\n      result.push_back(0xFFFD); // replacement character\n    }\n  }\n}\n\n#endif\n"
  },
  {
    "path": "src/vec.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _VEC_H\n#define _VEC_H\n\n#if defined(__clang__) || defined(__gcc__)\n#define VEC_VECTORISED\n#endif\n\nclass vec\n{\nprivate:\n#ifdef VEC_VECTORISED\n  typedef int ivec __attribute__((vector_size(16)));\n  union\n  {\n    int arrayValue[4];\n    ivec vectorValue;\n  } data;\n  vec(ivec vector)\n  {\n    data.vectorValue = vector;\n  }\n#else\n  union\n  {\n    int arrayValue[3];\n  } data;\n#endif\npublic:\n  explicit vec(int x = 0, int y = 0, int z = 0)\n  {\n    data.arrayValue[0] = x;\n    data.arrayValue[1] = y;\n    data.arrayValue[2] = z;\n  }\n  vec(const int values[3])\n  {\n    data.arrayValue[0] = values[0];\n    data.arrayValue[1] = values[1];\n    data.arrayValue[2] = values[2];\n  }\n  vec(const vec& ov)\n  {\n#ifdef VEC_VECTORISED\n    data.vectorValue   = ov.data.vectorValue;\n#else\n    data.arrayValue[0] = ov.data.arrayValue[0];\n    data.arrayValue[1] = ov.data.arrayValue[1];\n    data.arrayValue[2] = ov.data.arrayValue[2];\n#endif\n  }\n\n  vec& operator=(const vec& ov)\n  {\n#ifdef VEC_VECTORISED\n    data.vectorValue   = ov.data.vectorValue;\n#else\n    data.arrayValue[0] = ov.data.arrayValue[0];\n    data.arrayValue[1] = ov.data.arrayValue[1];\n    data.arrayValue[2] = ov.data.arrayValue[2];\n#endif\n    return *this;\n  }\n\n  int& x()\n  {\n    return data.arrayValue[0];\n  }\n  int& y()\n  {\n    return data.arrayValue[1];\n  }\n  int& z()\n  {\n    return data.arrayValue[2];\n  }\n  const int& x() const\n  {\n    return data.arrayValue[0];\n  }\n  const int& y() const\n  {\n    return data.arrayValue[1];\n  }\n  const int& z() const\n  {\n    return data.arrayValue[2];\n  }\n\n  vec operator+(const vec& ov) const\n  {\n#ifdef VEC_VECTORISED\n    return vec(data.vectorValue + ov.data.vectorValue);\n\n#else\n    return vec(x() + ov.x(),\n               y() + ov.y(),\n               z() + ov.z());\n\n#endif\n  }\n  vec operator-(const vec& ov) const\n  {\n#ifdef VEC_VECTORISED\n    return vec(data.vectorValue - ov.data.vectorValue);\n\n#else\n    return vec(x() - ov.x(),\n               y() - ov.y(),\n               z() - ov.z());\n\n#endif\n  }\n  vec operator-() const\n  {\n#ifdef VEC_VECTORISED\n    return vec(-data.vectorValue);\n\n#else\n    return vec(-x(),\n               -y(),\n               -z());\n\n#endif\n  }\n\n  vec& operator+=(const vec& ov)\n  {\n    return *this = *this + ov;\n  }\n  vec& operator-=(const vec& ov)\n  {\n    return *this = *this - ov;\n  }\n  bool operator==(const vec& b) const\n  {\n    return x() == b.x() && y() == b.y() && z() == b.z();\n  }\n  bool operator<(const vec& b) const\n  {\n    return x() < b.x() || (x() == b.x() && y() < b.y()) || (x() == b.x() && y() == b.y() && z() < b.z());\n  }\n\n  int squareLength() const\n  {\n    return x() * x() + y() * y() + z() * z();\n  }\n\n  static int squareDistance(const vec& x, const vec& y)\n  {\n    return (x - y).squareLength();\n  }\n};\n\n#endif\n"
  },
  {
    "path": "src/worldgen/biomegen.cpp",
    "content": "/*\n    Copyright (c) 2012, The Mineserver Project\n    All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"biomegen.h\"\n\n#include \"mineserver.h\"\n#include \"config.h\"\n#include \"tree.h\"\n#include \"random.h\"\n\nBiomeGen::BiomeGen()\n  : blocks(16 * 16 * 128, 0),\n    blockdata(16 * 16 * 128 / 2, 0),\n    skylight(16 * 16 * 128 / 2, 0),\n    blocklight(16 * 16 * 128 / 2, 0),\n    heightmap(16 * 16, 0)\n{\n}\n\nvoid BiomeGen::init(int seed)\n{\n  cave.init(seed + 7);\n  //###### TREE GEN #####\n  treenoise.SetSeed(seed + 404);\n  treenoise.SetFrequency(0.01);\n  treenoise.SetOctaveCount(3);\n  //###### END TREE GEN #######\n  seaLevel = ServerInstance->config()->iData(\"mapgen.sea.level\");\n  addTrees = ServerInstance->config()->bData(\"mapgen.trees.enabled\");\n  expandBeaches = ServerInstance->config()->bData(\"mapgen.beaches.expand\");\n  beachExtent = ServerInstance->config()->iData(\"mapgen.beaches.extent\");\n  beachHeight = ServerInstance->config()->iData(\"mapgen.beaches.height\");\n\n  addOre = ServerInstance->config()->bData(\"mapgen.addore\");\n  addCaves = ServerInstance->config()->bData(\"mapgen.caves.enabled\");\n\n  BiomeBase.SetFrequency(0.2);\n  BiomeBase.SetSeed(seed - 1);\n  BiomeSelect.SetSourceModule(0, BiomeBase);\n  BiomeSelect.SetScale(2.5);\n  BiomeSelect.SetBias(2.5);\n  mountainTerrainBase.SetSeed(seed + 1);\n  mountainTerrain.SetSourceModule(0, mountainTerrainBase);\n  mountainTerrain.SetScale(0.5);\n  mountainTerrain.SetBias(0.5);\n  jaggieEdges.SetSourceModule(0, terrainType);\n  jaggieEdges.SetSourceModule(1, plain);\n  plain.SetConstValue(0.5);\n  jaggieEdges.SetControlModule(jaggieControl);\n  jaggieEdges.SetBounds(0.5, 1.0);\n  jaggieEdges.SetEdgeFalloff(0.11);\n  jaggieControl.SetSeed(seed + 20);\n  baseFlatTerrain.SetSeed(seed);\n  baseFlatTerrain.SetFrequency(0.2);\n  flatTerrain.SetSourceModule(0, baseFlatTerrain);\n  flatTerrain.SetScale(0.125);\n  flatTerrain.SetBias(0.07);\n  baseWater.SetSeed(seed - 1);\n  water.SetSourceModule(0, baseWater);\n  water.SetScale(0.3);\n  water.SetBias(-0.5);\n  terrainType.SetSeed(seed + 2);\n  terrainType.SetFrequency(0.5);\n  terrainType.SetPersistence(0.25);\n  terrainType2.SetSeed(seed + 7);\n  terrainType2.SetFrequency(0.5);\n  terrainType2.SetPersistence(0.25);\n  waterTerrain.SetSourceModule(0, water);\n  waterTerrain.SetSourceModule(1, flatTerrain);\n  waterTerrain.SetControlModule(terrainType2);\n  waterTerrain.SetEdgeFalloff(0.1);\n  waterTerrain.SetBounds(-0.5, 1.0);\n  secondTerrain.SetSourceModule(1, waterTerrain);\n  secondTerrain.SetSourceModule(0, mountainTerrain);\n  secondTerrain.SetControlModule(terrainType);\n  secondTerrain.SetEdgeFalloff(0.3);\n  secondTerrain.SetBounds(-0.5, 1.0);\n  finalTerrain.SetSourceModule(0, secondTerrain);\n  finalTerrain.SetSourceModule(1, waterTerrain);\n  finalTerrain.SetControlModule(jaggieEdges);\n  finalTerrain.SetEdgeFalloff(0.2);\n  finalTerrain.SetBounds(-0.3, 1.0);\n  flowers.SetSeed(seed + 10);\n  flowers.SetFrequency(3);\n  winterEnabled = false;\n}\n\nvoid BiomeGen::re_init(int seed)\n{\n  cave.init(seed + 7);\n  treenoise.SetSeed(seed + 404);\n  BiomeBase.SetSeed(seed - 1);\n  mountainTerrainBase.SetSeed(seed + 1);\n  baseFlatTerrain.SetSeed(seed);\n  baseWater.SetSeed(seed - 1);\n  terrainType2.SetSeed(seed + 7);\n  terrainType.SetSeed(seed + 2);\n}\n\n\nvoid BiomeGen::generateFlatgrass(int x, int z, int map)\n{\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n  Block top = BLOCK_GRASS;\n  if (winterEnabled)\n  {\n    top = BLOCK_SNOW;\n  }\n\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      heightmap_pointer[(bZ << 4) + bX] = 64;\n      for (int bY = 0; bY < 128; bY++)\n      {\n        if (bY == 0)\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = BLOCK_BEDROCK;\n        }\n        else if (bY < 64)\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = BLOCK_DIRT;\n        }\n        else if (bY == 64)\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = top;\n        }\n        else\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = BLOCK_AIR;\n        }\n      }\n    }\n  }\n}\n\nvoid BiomeGen::generateChunk(int x, int z, int map)\n{\n  NBT_Value* main = new NBT_Value(NBT_Value::TAG_COMPOUND);\n  NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n\n  val->Insert(\"Sections\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n\n  val->Insert(\"HeightMap\", new NBT_Value(heightmap));\n  val->Insert(\"Entities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"TileEntities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"LastUpdate\", new NBT_Value((int64_t)time(NULL)));\n  val->Insert(\"xPos\", new NBT_Value(x));\n  val->Insert(\"zPos\", new NBT_Value(z));\n  val->Insert(\"TerrainPopulated\", new NBT_Value((int8_t)1));\n\n  main->Insert(\"Level\", val);\n\n  sChunk* chunk = new sChunk();\n  //chunk->blocks = new uint8_t[16 * 16 * 256];\n  //chunk->addblocks = new uint8_t[16 * 16 * 256 / 2];\n  //chunk->data = new uint8_t[16 * 16 * 256 / 2];\n  //chunk->blocklight = new uint8_t[16 * 16 * 256 / 2];\n  //chunk->skylight = new uint8_t[16 * 16 * 256 / 2];\n  chunk->heightmap = &((*(*val)[\"HeightMap\"]->GetIntArray())[0]);\n  heightmap_pointer = chunk->heightmap;\n  chunk->nbt = main;\n  chunk->x = x;\n  chunk->z = z;\n\n  memset(chunk->blocks, 0, 16*16*256);\n  memset(chunk->addblocks, 0, 16*16*256/2);\n  memset(chunk->data, 0, 16*16*256/2);\n  memset(chunk->blocklight, 0, 16*16*256/2);\n  memset(chunk->skylight, 0, 16*16*256/2);\n  chunk->chunks_present = 0xffff;\n\n  ServerInstance->map(map)->chunks.insert(ChunkMap::value_type(ChunkMap::key_type(x, z), chunk));\n\n  if (ServerInstance->config()->bData(\"mapgen.flatgrass\"))\n  {\n    generateFlatgrass(x, z, map);\n  }\n  else\n  {\n    generateWithNoise(x, z, map);\n  }\n\n\n  // Update last used time\n  //ServerInstance->map()->mapLastused[chunkid] = (int)time(0);\n\n  // Not changed\n  chunk->changed = ServerInstance->config()->bData(\"map.save_unchanged_chunks\");\n\n  //ServerInstance->map()->maps[chunkid].nbt = main;\n\n  if (addOre)\n  {\n    AddOre(x, z, map, BLOCK_COAL_ORE);\n    AddOre(x, z, map, BLOCK_IRON_ORE);\n    AddOre(x, z, map, BLOCK_GOLD_ORE);\n    AddOre(x, z, map, BLOCK_DIAMOND_ORE);\n    AddOre(x, z, map, BLOCK_REDSTONE_ORE);\n    AddOre(x, z, map, BLOCK_LAPIS_ORE);\n  }\n\n  AddOre(x, z, map, BLOCK_GRAVEL);\n\n  // Add trees\n  if (addTrees)\n  {\n    AddTrees(x, z, map);  // add trees will make a *kind-of* forest of 16*16 chunks\n  }\n\n}\n\n//#define PRINT_MAPGEN_TIME\n\n\nvoid BiomeGen::AddTrees(int x, int z, int map)\n{\n  int32_t xBlockpos = x << 4;\n  int32_t zBlockpos = z << 4;\n  int blockX, blockZ;\n  uint8_t blockY, block, meta;\n\n  bool empty[16][16]; // is block empty \n\n  memset(empty, 1, 256);\n\n  uint8_t trees = uint8_t(uniform01() * 7 + 13);\n  uint8_t i = 0;\n  while (i < trees)\n  {\n    uint8_t a = uint8_t(uniform01() * 16);\n    uint8_t b = uint8_t(uniform01() * 16);\n\n    if (empty[a][b])\n    {\n      blockX = a + xBlockpos;\n      blockZ = b + zBlockpos;\n      blockY = heightmap_pointer[(b<<4)+a];\n\n      // Another dirty haxx!\n      if (blockY > 120)\n      {\n        i++;\n        continue;\n      }\n      ServerInstance->map(map)->getBlock(blockX, blockY, blockZ, &block, &meta);\n\n      int biome = int(BiomeSelect.GetValue(blockX / 100.0, 0, blockZ / 100.0));\n      if (biome == 1 &&\n          treenoise.GetValue(blockX, 0, blockZ) > -0.3 &&\n          ((rand() % 16) < 7)) // Dirty haxx!\n      {\n        // Desert, make cactus\n        int count = 3;\n        if ((count + blockY) > 126)\n        {\n          continue;\n        }\n          //LOGLF(\"testing reed area\");\n          ServerInstance->map(map)->getBlock(blockX, (blockY + i), blockZ, &block, &meta);\n          if(block == BLOCK_SAND){\n            ServerInstance->map(map)->setBlock(blockX, (blockY + 1 + i), blockZ, (char)BLOCK_CACTUS, (char)meta);\n            ServerInstance->map(map)->setBlock(blockX, (blockY + 2 + i), blockZ, (char)BLOCK_CACTUS, (char)meta);\n            ServerInstance->map(map)->setBlock(blockX, (blockY + 3 + i), blockZ, (char)BLOCK_CACTUS, (char)meta);\n            //printf(\"successful cactus! x%d y%d z%d\\n\", blockX, blockY, blockZ);\n          }\n\n\n\n        // Check that it's not in water\n        /*ServerInstance->map(map)->getBlock(blockX, ++blockY, blockZ, &block, &meta);\n        if (!(block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER))\n        {\n          sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n          uint8_t* curBlock;\n          int count = (fastrand() % 3) + 3;\n          if (count + blockY > 127)\n          {\n            continue;\n          }\n          curBlock = &(chunk->blocks[(a << 7) + (b << 11) + blockY]);\n          for (int i = 0; i < count; i++)\n          {\n            curBlock[i] = BLOCK_CACTUS;\n          }\n        }*/\n      }\n      else if (biome == 4 &&\n               block != BLOCK_WATER &&\n               block != BLOCK_STATIONARY_WATER &&\n               treenoise.GetValue(blockX, 0, blockZ) > -0.2)\n      {\n        //Reed forest\n        int count = 3;\n        if ((count + blockY) > 126)\n        {\n          continue;\n        }\n          //LOGLF(\"testing reed area\");\n        int xOffset = 0;\n        ServerInstance->map(map)->getBlock(blockX + xOffset, (blockY + i), blockZ, &block, &meta);\n          if(block == BLOCK_DIRT || block == BLOCK_REED || block == BLOCK_GRASS){\n            if(block == BLOCK_GRASS){\n              ServerInstance->map(map)->setBlock(blockX + xOffset, (blockY + i), blockZ, (char)BLOCK_DIRT, (char)meta);\n              block = BLOCK_DIRT;\n            }\n            ServerInstance->map(map)->setBlock(blockX + xOffset, (blockY + 1 + i), blockZ, (char)BLOCK_REED, (char)meta);\n            ServerInstance->map(map)->setBlock(blockX + xOffset, (blockY + 2 + i), blockZ, (char)BLOCK_REED, (char)meta);\n            ServerInstance->map(map)->setBlock(blockX + xOffset, (blockY + 3 + i), blockZ, (char)BLOCK_REED, (char)meta);\n            //printf(\"successful reed! x%d y%d z%d\\n\", blockX + xOffset, blockY, blockZ);\n          }\n\n      }\n      else if (biome == 2 || biome == 3)\n      {\n        if (block == BLOCK_DIRT || block == BLOCK_GRASS)\n        {\n          // Trees only grow on dirt and grass? =b\n          ServerInstance->map(map)->getBlock(blockX, ++blockY, blockZ, &block, &meta);\n          if (block == BLOCK_AIR || block == BLOCK_SNOW)\n          {\n            if (treenoise.GetValue(blockX, 0, blockZ) > -0.4)\n            {\n              Tree tree(blockX, blockY, blockZ, map);\n            }\n          }\n        }\n      }\n      for (int8_t u = -2; u < 2; u++)\n      {\n        for (int8_t v = -2; v < 2; v++)\n        {\n          //Check for array boundaries\n          if((a+u) >= 0 && (b+v) >= 0 &&\n             (a+u) < 16 && (b+v) < 16)\n          {\n            empty[a+u][b+v] = false;\n          }\n        }\n      }\n      i++;\n    }\n  }\n}\n\nvoid BiomeGen::generateWithNoise(int x, int z, int map)\n{\n  // Debug..\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  DWORD t_begin, t_end;\n  t_begin = timeGetTime();\n#else\n  struct timeval start, end;\n  gettimeofday(&start, NULL);\n#endif\n#endif\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n  // Winterland\n  Block topBlock = BLOCK_GRASS;\n  if (winterEnabled)\n  {\n    topBlock = BLOCK_SNOW;\n  }\n\n  // Populate blocks in chunk\n  int32_t currentHeight;\n  int32_t ymax;\n  uint8_t* curBlock;\n\n  double xBlockpos = x << 4;\n  double zBlockpos = z << 4;\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      heightmap_pointer[(bZ << 4) + bX] = ymax = currentHeight = (uint8_t)((finalTerrain.GetValue((xBlockpos + bX) / 100.0, 0, (zBlockpos + bZ) / 100.0) * 60) + 64);\n      int biome = int(BiomeSelect.GetValue((xBlockpos + bX) / 100.0, 0, (zBlockpos + bZ) / 100.0));\n      char toplayer;\n      if (biome == 0)\n      {\n        toplayer = BLOCK_DIRT;\n      }\n      if (biome == 1)\n      {\n        toplayer = BLOCK_SAND;\n      }\n      if (biome == 2)\n      {\n        toplayer = BLOCK_DIRT;\n      }\n      if (biome == 3)\n      {\n        toplayer = BLOCK_DIRT;\n      }\n      if (biome == 4)\n      {\n        toplayer = BLOCK_DIRT;\n      }\n      if (biome == 5)\n      {\n        toplayer = BLOCK_CLAY;\n      }\n\n      int32_t stoneHeight = (int32_t)currentHeight - ((64 - (currentHeight % 64)) / 8) + 1;\n      //int32_t bYbX = ((bZ << 7) + (bX << 11));\n\n      if (ymax < seaLevel)\n      {\n        ymax = seaLevel;\n      }\n      ymax++;\n\n      for (int bY = 0; bY <= ymax; bY++)\n      {\n        curBlock = &(chunk->blocks[bX + (bZ << 4) + (bY << 8)]);\n\n        // Place bedrock\n        if (bY == 0)\n        {\n          *curBlock = BLOCK_BEDROCK;\n          continue;\n        }\n\n        if (bY < currentHeight)\n        {\n          if (bY < stoneHeight)\n          {\n            *curBlock = BLOCK_STONE;\n            // Add caves\n            if (addCaves)\n            {\n              cave.AddCaves(*curBlock, int(xBlockpos + bX), bY, int(zBlockpos + bZ));\n            }\n          }\n          else\n          {\n            *curBlock = toplayer;\n          }\n        }\n        else if ((currentHeight + 1) == bY && bY > seaLevel && biome == 3)\n        {\n          *curBlock = BLOCK_SNOW;\n          continue;\n        }\n        else if ((currentHeight + 1) == bY && bY > seaLevel + 1)\n        {\n          if (biome == 1 || biome == 0)\n          {\n            continue;\n          }\n          double f = flowers.GetValue(xBlockpos + bX / 10.0, 0, zBlockpos + bZ / 10.0);\n          if (f < -0.999)\n          {\n            *curBlock = BLOCK_RED_ROSE;\n          }\n          else if (f > 0.999)\n          {\n            *curBlock = BLOCK_YELLOW_FLOWER;\n          }\n          else if (f < 0.001 && f > -0.001)\n          {\n            *curBlock = BLOCK_PUMPKIN;\n          }\n        }\n        else if (currentHeight == bY)\n        {\n          if (bY == seaLevel || bY == seaLevel - 1 || bY == seaLevel - 2)\n          {\n            *curBlock = BLOCK_SAND;  // FF\n          }\n          else if (bY < seaLevel - 1)\n          {\n            *curBlock = BLOCK_GRAVEL;  // FF\n          }\n          else if (toplayer == BLOCK_DIRT)\n          {\n            *curBlock = BLOCK_GRASS;\n          }\n          else\n          {\n            *curBlock = toplayer; // FF\n          }\n        }\n        else\n        {\n          if (bY <= seaLevel)\n          {\n            *curBlock = BLOCK_WATER;  // FF\n          }\n          else\n          {\n            *curBlock = BLOCK_AIR;  // FF\n          }\n          if (bY == seaLevel && biome == 3)\n          {\n            *curBlock = BLOCK_ICE;\n          }\n\n        }\n      }\n    }\n  }\n\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  t_end = timeGetTime();\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(t_end - t_begin) + \"ms\");\n#else\n  gettimeofday(&end, NULL);\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(end.tv_usec - start.tv_usec));\n#endif\n#endif\n}\n\n\nMAKE_UNIFORM_DIST(10, 30)\nMAKE_UNIFORM_DIST(20, 30)\nMAKE_UNIFORM_DIST( 1,  3)\nMAKE_UNIFORM_DIST(10, 18)\nMAKE_UNIFORM_DIST( 4,  9)\nMAKE_UNIFORM_DIST( 5, 10)\nMAKE_UNIFORM_DIST( 8, 12)\nMAKE_UNIFORM_DIST( 0,  1)\n\n\nvoid BiomeGen::AddOre(int x, int z, int map, uint8_t type)\n{\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n  int blockX, blockY, blockZ;\n  uint8_t block;\n\n  // Parameters for deposits\n  int startHeight, minDepoSize, maxDepoSize;\n  unsigned int count;\n\n  switch (type)\n  {\n  case BLOCK_COAL_ORE:\n    count = uniform_20_30(); // 20-30 coal deposits\n    startHeight = 90;\n    minDepoSize = 8;\n    maxDepoSize = 20;\n    break;\n  case BLOCK_IRON_ORE:\n    count = uniform_10_18(); // 10-18 iron deposits\n    startHeight = 60;\n    minDepoSize = 5;\n    maxDepoSize = 10;\n    break;\n  case BLOCK_GOLD_ORE:\n    count = uniform_4_9(); // 4-9 gold deposits\n    startHeight = 32;\n    minDepoSize = 5;\n    maxDepoSize = 8;\n    break;\n  case BLOCK_DIAMOND_ORE:\n    count = uniform_1_3(); // 1-3 diamond deposits\n    startHeight = 17;\n    minDepoSize = 4;\n    maxDepoSize = 7;\n    break;\n  case BLOCK_REDSTONE_ORE:\n    count = uniform_5_10(); // 5-10 redstone deposits\n    startHeight = 25;\n    minDepoSize = 5;\n    maxDepoSize = 20;\n    break;\n  case BLOCK_LAPIS_ORE:\n    count = uniform_1_3(); // 1-3 lapis lazuli deposits\n    startHeight = 17;\n    minDepoSize = 5;\n    maxDepoSize = 20;\n    break;\n  case BLOCK_GRAVEL:\n    count = uniform_10_30(); // 10-30 gravel deposits\n    startHeight = 90;\n    minDepoSize = 5;\n    maxDepoSize = 50;\n    break;\n  default:\n    return;\n  }\n\n  for (unsigned int i = 0; i < count; ++i)\n  {\n    blockX = uniform_8_12();\n    blockZ = uniform_8_12();\n\n    blockY = heightmap_pointer[(blockZ << 4) + blockX];\n    blockY -= 5;\n\n    // Check that startheight is not higher than height at that column\n    if (blockY > startHeight)\n    {\n      blockY = startHeight;\n    }\n\n    //blockX += xBlockpos;\n    //blockZ += zBlockpos;\n\n    // Calculate Y\n    blockY = uniformUINT(0, blockY);\n\n    \n    block = chunk->blocks[blockX + (blockZ << 4) + (blockY << 8)];\n\n    // No ore in caves\n    if (block == BLOCK_AIR)\n    {\n      continue;\n    }\n\n    AddDeposit(blockX, blockY, blockZ, map, type, minDepoSize, maxDepoSize, chunk);\n  }\n}\n\nvoid BiomeGen::AddDeposit(int x, int y, int z, int map, uint8_t block, int minDepoSize, int maxDepoSize, sChunk* chunk)\n{\n  int depoSize = uniformUINT(maxDepoSize - minDepoSize, maxDepoSize);\n\n  for (int i = 0; i < depoSize; i++)\n  {\n    if (chunk->blocks[x + (z << 4) + (y << 8)] == BLOCK_STONE)\n    {\n      chunk->blocks[x + (z << 4) + (y << 8)] = block;\n    }\n\n    z = z + int(uniform_0_1()) - 1;\n    x = x + int(uniform_0_1()) - 1;\n    y = y + int(uniform_0_1()) - 1;\n\n    // If over chunk borders\n    if (z < 0 || z > 15 || x < 0 || x > 15 || y < 1)\n    {\n      break;\n    }\n  }\n}\n"
  },
  {
    "path": "src/worldgen/biomegen.h",
    "content": "/*\n    Copyright (c) 2011, The Mineserver Project\n    All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef _BIOMEGEN_H\n#define _BIOMEGEN_H\n\n#include \"mapgen.h\"\n\nclass BiomeGen: public MapGen\n{\npublic:\n  BiomeGen();\n  void init(int seed);\n  void re_init(int seed); // Used when generating multiple maps\n  void generateChunk(int x, int z, int map);\n\nprivate:\n  std::vector<uint8_t> blocks;\n  std::vector<uint8_t> blockdata;\n  std::vector<uint8_t> skylight;\n  std::vector<uint8_t> blocklight;\n  std::vector<int32_t> heightmap;\n\n  int32_t* heightmap_pointer;\n\n  int seaLevel;\n\n  bool addTrees;\n\n  bool expandBeaches;\n  int beachExtent;\n  int beachHeight;\n\n  bool addOre;\n  bool addCaves;\n  bool winterEnabled;\n\n  void generateFlatgrass(int x, int z, int map);\n  void generateWithNoise(int x, int z, int map);\n\n  void AddTrees(int x, int z, int map);\n\n  void AddOre(int x, int z, int map, uint8_t type);\n  void AddDeposit(int x, int y, int z, int map, uint8_t block, int minDepoSize, int maxDepoSize, sChunk* chunk);\n\n  CaveGen cave;\n\n  // Heightmap composition\n  noise::module::Perlin BiomeBase;\n  noise::module::ScaleBias BiomeSelect;\n  noise::module::RidgedMulti mountainTerrainBase;\n  noise::module::ScaleBias mountainTerrain;\n  noise::module::Billow baseFlatTerrain;\n  noise::module::ScaleBias flatTerrain;\n  noise::module::Billow baseWater;\n  noise::module::ScaleBias water;\n  noise::module::Perlin terrainType;\n  noise::module::Perlin terrainType2;\n  noise::module::Select waterTerrain;\n  noise::module::Select finalTerrain;\n  noise::module::Voronoi flowers;\n  noise::module::Select jaggieEdges;\n  noise::module::Select secondTerrain;\n  noise::module::Const plain;\n  noise::module::Billow jaggieControl;\n  // ##### TREE GEN #####\n  noise::module::Billow treenoise;\n  // ##### END TREE GEN ####\n};\n\n#endif\n"
  },
  {
    "path": "src/worldgen/cavegen.cpp",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <cstdlib>\n#include <cstdio>\n#include <iostream>\n\n#ifdef LIBNOISE\n#include <libnoise/noise.h>\n#else\n#include <noise/noise.h>\n#endif\n\n#include \"logger.h\"\n#include \"constants.h\"\n#include \"tools.h\"\n#include \"map.h\"\n#include \"config.h\"\n#include \"mineserver.h\"\n\n#include \"cavegen.h\"\n\nvoid CaveGen::init(int seed)\n{\n  addCaveLava = ServerInstance->config()->bData(\"mapgen.caves.lava\");\n  caveSize = ServerInstance->config()->iData(\"mapgen.caves.size\");\n  caveTreshold = ServerInstance->config()->dData(\"mapgen.caves.treshold\");\n\n  // Set up us the Perlin-noise module.\n  caveNoise.SetSeed(seed + 22);\n  caveNoise.SetFrequency(1.0 / caveSize);\n  caveNoise.SetOctaveCount(4);\n}\n\nvoid CaveGen::AddCaves(uint8_t& block, int x, int y, int z)\n{\n  if (caveNoise.GetValue(x / 4.0, y / 1.5, z / 4.0) > caveTreshold)\n  {\n    if (y < 10 && addCaveLava)\n    {\n      block = BLOCK_LAVA;\n    }\n    else\n    {\n      block = BLOCK_AIR;\n    }\n  }\n}\n"
  },
  {
    "path": "src/worldgen/cavegen.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _CAVEGEN_H\n#define _CAVEGEN_H\n\n#include <stdint.h>\n\nclass CaveGen\n{\npublic:\n  void init(int seed);\n  void AddCaves(uint8_t& block, int x, int y, int z);\n\nprivate:\n  noise::module::RidgedMulti caveNoise;\n  bool addCaveLava;\n  int caveSize;\n  double caveTreshold;\n};\n\n#endif\n"
  },
  {
    "path": "src/worldgen/eximgen.cpp",
    "content": "/*\nCopyright (c) 2011, The Mineserver Project\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n* Neither the name of the The Mineserver Project nor the\nnames of its contributors may be used to endorse or promote products\nderived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include \"eximgen.h\"\n\n#include \"mineserver.h\"\n#include \"config.h\"\n#include \"map.h\"\n#include \"tree.h\"\n#include \"tools.h\"\n#include \"random.h\"\n\n#include <cassert>\n\nEximGen::EximGen()\n    : blocks(16 * 16 * 128, 0),\n      blockdata(16 * 16 * 128 / 2, 0),\n      skylight(16 * 16 * 128 / 2, 0),\n      blocklight(16 * 16 * 128 / 2, 0),\n      heightmap(16 * 16, 0)\n{\n\n}\n\nvoid EximGen::init(int seed)\n{\n    seaLevel = ServerInstance->config()->iData(\"mapgen.sea.level\");\n    addTrees = ServerInstance->config()->bData(\"mapgen.trees.enabled\");\n    expandBeaches = ServerInstance->config()->bData(\"mapgen.beaches.expand\");\n    beachExtent = ServerInstance->config()->iData(\"mapgen.beaches.extent\");\n    beachHeight = ServerInstance->config()->iData(\"mapgen.beaches.height\");\n\n    addOre = ServerInstance->config()->bData(\"mapgen.addore\");\n    addCaves = ServerInstance->config()->bData(\"mapgen.caves.enabled\");\n\n    winterEnabled = ServerInstance->config()->bData(\"mapgen.winter.enabled\");\n\n\n    //cave.init(seed + 7);\n\n    int upperLevel = 255-seaLevel;\n\n    mountainTerrain.SetSeed(seed);\n    mountainTerrain.SetFrequency(1.0/180.0);\n    mountainTerrain.SetOctaveCount(6);\n\n    mountainScale.SetSourceModule(0, mountainTerrain);\n    mountainScale.SetScale(upperLevel * 0.4);\n    mountainScale.SetBias(upperLevel * 0.4 + seaLevel);\n\n    baseFlatTerrain.SetSeed(seed);\n    baseFlatTerrain.SetFrequency(1.0/512.0);\n    baseFlatTerrain.SetOctaveCount(6);\n    baseFlatTerrain.SetPersistence(0.3);\n\n    flatTerrain.SetSourceModule(0, baseFlatTerrain);\n    flatTerrain.SetScale(seaLevel / 2.0);\n    flatTerrain.SetBias(seaLevel / 2.0 + 40);\n\n    terrainType.SetSeed(seed);\n    terrainType.SetFrequency(1.0/512.0);\n    terrainType.SetOctaveCount(4);\n    terrainType.SetPersistence(0.3);\n\n    terrainSelector.SetSourceModule(0, flatTerrain);\n    terrainSelector.SetSourceModule(1, mountainScale);\n    terrainSelector.SetControlModule(terrainType);\n    terrainSelector.SetBounds(0.3, 1.1);\n    terrainSelector.SetEdgeFalloff(0.25);\n\n    finalTerrain.SetSourceModule(0, terrainSelector);\n    finalTerrain.SetScale(1.0);\n    finalTerrain.SetBias(0);\n\n    treenoise.SetSeed(seed + 404);\n    treenoise.SetFrequency(1.0/64);\n    treenoise.SetOctaveCount(3);\n\n    earthNoise.SetSeed(seed + 900);\n    earthNoise.SetFrequency(1.0/32);\n    earthNoise.SetOctaveCount(5);\n\n    caveNoise.SetSeed(seed + 1000);\n    caveNoise.SetFrequency(1.0/20);\n    caveNoise.SetOctaveCount(2);\n\n}\n\nvoid EximGen::re_init(int seed)\n{\n    //cave.init(seed + 7);\n\n    mountainTerrain.SetSeed(seed);\n    baseFlatTerrain.SetSeed(seed);\n    terrainType.SetSeed(seed);\n\n    treenoise.SetSeed(seed + 404);\n    earthNoise.SetSeed(seed + 900);\n    caveNoise.SetSeed(seed + 1000);\n}\n\n\nvoid EximGen::generateChunk(int x, int z, int map)\n{\n    NBT_Value* main = new NBT_Value(NBT_Value::TAG_COMPOUND);\n    NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n\n    val->Insert(\"Sections\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n\n    val->Insert(\"HeightMap\", new NBT_Value(heightmap));\n    val->Insert(\"Entities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n    val->Insert(\"TileEntities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n    val->Insert(\"LastUpdate\", new NBT_Value((int64_t)time(NULL)));\n    val->Insert(\"xPos\", new NBT_Value(x));\n    val->Insert(\"zPos\", new NBT_Value(z));\n    val->Insert(\"TerrainPopulated\", new NBT_Value((int8_t)1));\n\n    main->Insert(\"Level\", val);\n\n    sChunk* chunk = new sChunk();\n\n    NBT_Value* val1 = (*val)[\"HeightMap\"];\n    chunk->heightmap = val1->GetIntArray()->data();\n    chunk->nbt = main;\n    chunk->x = x<<4;\n    chunk->z = z<<4;\n    ServerInstance->map(map)->chunks.insert(ChunkMap::value_type(ChunkMap::key_type(x, z), chunk));\n\n    memset(chunk->blocks, 0, 16*16*256);\n    memset(chunk->addblocks, 0, 16*16*256/2);\n    memset(chunk->data, 0, 16*16*256/2);\n    memset(chunk->blocklight, 0, 16*16*256/2);\n    memset(chunk->skylight, 0, 16*16*256/2);\n    chunk->chunks_present = 0xffff;\n\n    ChunkInfo info(chunk);\n\n\n    if (ServerInstance->config()->bData(\"mapgen.flatgrass\"))\n    {\n        generateFlatgrass(x, z, map);\n    }\n    else\n    {\n        generateWithNoise(info);\n    }\n\n\n    // Not changed\n    chunk->changed = ServerInstance->config()->bData(\"map.save_unchanged_chunks\");\n\n    if (false && addOre)\n    {\n        AddOre(x, z, map, BLOCK_COAL_ORE);\n        AddOre(x, z, map, BLOCK_IRON_ORE);\n        AddOre(x, z, map, BLOCK_GOLD_ORE);\n        AddOre(x, z, map, BLOCK_DIAMOND_ORE);\n        AddOre(x, z, map, BLOCK_REDSTONE_ORE);\n        AddOre(x, z, map, BLOCK_LAPIS_ORE);\n    }\n\n    //AddOre(x, z, map, BLOCK_GRAVEL);\n    //AddOre(x, z, map, BLOCK_DIRT); // guess what, dirt also exists underground\n\n    // Add trees\n    if (addTrees)\n    {\n        //AddTrees(x, z, map);\n    }\n\n    if (expandBeaches)\n    {\n        //ExpandBeaches(x, z, map);\n    }\n\n    // AddRiver(x, z, map);\n\n}\n\n\n#include <iostream>\nusing namespace std;\nvoid EximGen::AddTrees(int x, int z, int map)\n{\n    int32_t xBlockpos = x << 4;\n    int32_t zBlockpos = z << 4;\n    int blockX, blockZ;\n    uint8_t blockY, block, meta;\n\n    bool empty[16][16]; // is block emptey~\n\n    memset(empty, 1, 256);\n\n    uint8_t trees = uint8_t(uniform01() * 7 + 13);\n    uint8_t i = 0;\n    while (i < trees)\n    {\n        uint8_t a = uint8_t(uniform01() * 16);\n        uint8_t b = uint8_t(uniform01() * 16);\n\n        if (empty[a][b])\n        {\n            blockX = a + xBlockpos;\n            blockZ = b + zBlockpos;\n            blockY = heightmap[(b<<4)+a] ;\n\n            ServerInstance->map(map)->getBlock(blockX, blockY, blockZ, &block, &meta);\n            if (block == BLOCK_DIRT || block == BLOCK_GRASS)\n            {\n                // Trees only grow on dirt and grass? =b\n                ServerInstance->map(map)->getBlock(blockX, ++blockY, blockZ, &block, &meta);\n                if (block == BLOCK_AIR || block == BLOCK_SNOW)\n                {\n                    if (treenoise.GetValue(blockX, 0, blockZ) > -0.4)\n                    {\n                        Tree tree(blockX, blockY, blockZ, map);\n                    }\n                }\n            }\n            for (int8_t u = -2; u < 2; u++)\n            {\n                for (int8_t v = -2; v < 2; v++)\n                {\n                    //Check for array boundaries\n                    if((a+u) >= 0 && (b+v) >= 0 &&\n                            (a+u) < 16 && (b+v) < 16)\n                    {\n                        empty[a+u][b+v] = false;\n                    }\n                }\n            }\n            i++;\n        }\n    }\n}\n\nvoid EximGen::generateWithNoise(ChunkInfo& info)\n{\n    // Debug..\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n    DWORD t_begin, t_end;\n    t_begin = timeGetTime();\n#else\n    struct timeval start, end;\n    gettimeofday(&start, NULL);\n#endif\n#endif\n\n    AnvilAccessor& blocks = info.blocks;\n\n    for(int x=0;x<16;x++){\n        for(int z=0;z<16;z++){\n            blocks(x,0,z).id(BLOCK_BEDROCK);\n        }\n    }\n\n    int chunkX = info.chunk->x;\n    int chunkZ = info.chunk->z;\n\n    for(int x=0;x<16;x++){\n        for(int z=0;z<16;z++){\n\n            int32_t& currentHeight = heightmap[(z << 4) + x];\n\n            currentHeight = (int)finalTerrain.GetValue(chunkX + x,0,chunkZ + z);\n\n            if(currentHeight > 256)\n                currentHeight = 256;\n\n            int stoneHeight = currentHeight - (int)uniform01()*4;\n\n            int y=1;\n            bool cave=false;\n            int cave_start;\n            for(;y<=stoneHeight;y++){\n                if(caveNoise.GetValue(chunkX +x,y,chunkZ +z) > 0.8){\n                    if(!cave){\n                        cave =true;\n                        cave_start =y;\n                    }\n                }\n                else{\n                    cave = false;\n                    double density = earthNoise.GetValue(chunkX + x,y, chunkZ + z);\n\n                    BlockRef b = blocks(x,y,z);\n                    if(density < -0.75){\n                        b.id(BLOCK_SAND);\n                    }\n                    else if(density < -0.2){\n                        b.id(BLOCK_DIRT);\n                    }\n                    else if(density < 0.0){\n                        b.id(BLOCK_GRAVEL);\n                    }\n                    else b.id(BLOCK_STONE);\n                }\n            }\n\n            if(cave){\n                heightmap[(z << 4) + x] = cave_start;\n            }\n            if(currentHeight <= seaLevel){\n                for(;y<=currentHeight;y++)\n                    blocks(x,y,z).id(BLOCK_SAND);\n                for(;y<=seaLevel;y++)\n                    blocks(x,y,z).id(BLOCK_STATIONARY_WATER);\n            }else{\n                if(!cave){\n                    for(;y<currentHeight;y++)\n                        blocks(x,y,z).id(BLOCK_DIRT);\n                    blocks(x,y,z).id(BLOCK_GRASS);\n                }\n                else\n                    blocks(x,cave_start,z).id(BLOCK_GRASS);\n            }\n            if( currentHeight >= (230 + uniform01()*5) ){\n                blocks(x, currentHeight +1 ,z).id(BLOCK_SNOW_BLOCK);\n            }\n            else if(winterEnabled || currentHeight >= (225 + uniform01()*5) ){\n                blocks(x, currentHeight +1 ,z).id(BLOCK_SNOW);\n            }\n        }\n    }\n\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n    t_end = timeGetTime();\n    ServerInstance->logger()->log(\"Mapgen: \" + dtos(t_end - t_begin) + \"ms\");\n#else\n    gettimeofday(&end, NULL);\n    ServerInstance->logger()->log(\"Mapgen: \" + dtos(end.tv_usec - start.tv_usec));\n#endif\n#endif\n}\n\nvoid EximGen::ExpandBeaches(int x, int z, int map)\n{\n    sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));\n    int beachExtentSqr = (beachExtent + 1) * (beachExtent + 1);\n    int xBlockpos = x << 4;\n    int zBlockpos = z << 4;\n\n    int blockX, blockZ, h;\n    uint8_t block = 0;\n    uint8_t meta = 0;\n\n    for (int bX = 0; bX < 16; bX++)\n    {\n        for (int bZ = 0; bZ < 16; bZ++)\n        {\n            blockX = xBlockpos + bX;\n            blockZ = zBlockpos + bZ;\n\n            h = heightmap[(bZ<<4)+bX];\n\n            if (h < 0)\n            {\n                continue;\n            }\n\n            bool found = false;\n            for (int dx = -beachExtent; !found && dx <= beachExtent; dx++)\n            {\n                for (int dz = -beachExtent; !found && dz <= beachExtent; dz++)\n                {\n                    for (int dh = -beachHeight; !found && dh <= 0; dh++)\n                    {\n                        if (dx * dx + dz * dz + dh * dh > beachExtentSqr)\n                        {\n                            continue;\n                        }\n\n                        int xx = bX + dx;\n                        int zz = bZ + dz;\n                        int hh = h + dh;\n                        if (xx < 0 || xx >= 15 || zz < 0 || zz >= 15 || hh < 0 || hh >= 127)\n                        {\n                            continue;\n                        }\n\n                        //ToDo: add getBlock!!\n                        if (block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER)\n                        {\n                            found = true;\n                            break;\n                        }\n                    }\n                }\n            }\n            if (found)\n            {\n                ServerInstance->map(map)->sendBlockChange(blockX, h, blockZ, BLOCK_SAND, 0);\n                ServerInstance->map(map)->setBlock(blockX, h, blockZ, BLOCK_SAND, 0);\n\n                ServerInstance->map(map)->getBlock(blockX, h - 1, blockZ, &block, &meta);\n\n                if (h > 0 && block == BLOCK_DIRT)\n                {\n                    ServerInstance->map(map)->sendBlockChange(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n                    ServerInstance->map(map)->setBlock(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n                }\n            }\n        }\n    }\n}\n\nvoid EximGen::AddOre(int x, int z, int map, uint8_t type)\n{\n    sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n    int32_t blockX, blockZ;\n    uint8_t block, blockY;\n\n    // Parameters for deposits\n    uint8_t count, startHeight = 128, minDepoSize, maxDepoSize;\n\n    switch (type)\n    {\n    case BLOCK_COAL_ORE:\n        count = uint8_t(uniform01() * 10 + 20); // 20-30 coal deposits\n        //startHeight = 90;\n        minDepoSize = 3;\n        maxDepoSize = 7;\n        break;\n    case BLOCK_IRON_ORE:\n        count = uint8_t(uniform01() * 8 + 10); // 10-18 iron deposits\n        startHeight = 90;\n        minDepoSize = 2;\n        maxDepoSize = 5;\n        break;\n    case BLOCK_GOLD_ORE:\n        count = uint8_t(uniform01() * 4 + 5); // 4-9 gold deposits\n        startHeight = 42;\n        minDepoSize = 2;\n        maxDepoSize = 4;\n        break;\n    case BLOCK_DIAMOND_ORE:\n        count = uint8_t(uniform01() * 1 + 2); // 1-3 diamond deposits\n        startHeight = 17;\n        minDepoSize = 1;\n        maxDepoSize = 2;\n        break;\n    case BLOCK_REDSTONE_ORE:\n        count = uint8_t(uniform01() * 5 + 5); // 5-10 redstone deposits\n        startHeight = 25;\n        minDepoSize = 2;\n        maxDepoSize = 4;\n        break;\n    case BLOCK_LAPIS_ORE:\n        count = uint8_t(uniform01() * 1 + 2); // 1-3 lapis lazuli deposits\n        startHeight = 17;\n        minDepoSize = 1;\n        maxDepoSize = 2;\n        break;\n    case BLOCK_GRAVEL:\n        count = uint8_t(uniform01() * 10 + 20); // 20-30 gravel deposits\n        //startHeight = 90;\n        minDepoSize = 6;\n        maxDepoSize = 10;\n        break;\n    case BLOCK_DIRT:\n        count = uint8_t(uniform01() * 10 + 20); // 20-30 gravel deposits\n        //startHeight = 90;\n        minDepoSize = 6;\n        maxDepoSize = 10;\n        break;\n    default:\n        return;\n    }\n\n    int i = 0;\n    while (i < count)\n    {\n        blockX = int32_t(uniform01() * 16);\n        blockZ = int32_t(uniform01() * 16);\n\n        blockY = heightmap[(blockZ<<4)+blockX];\n        blockY -= uint8_t(uniform01() * 5);\n\n        // Check that startheight is not higher than height at that column\n        if (blockY > startHeight)\n        {\n            blockY = startHeight;\n        }\n\n        // Calculate Y\n        blockY = uint8_t(uniform01() * (blockY));\n\n        i++;\n\n        block = chunk->blocks[(blockX << 11) + (blockZ << 7) + blockY];\n        // No ore in caves\n        if (block == BLOCK_AIR)\n        {\n            continue;\n        }\n\n        AddDeposit(blockX, blockY, blockZ, map, type, minDepoSize, maxDepoSize, chunk);\n\n    }\n}\n\nvoid EximGen::AddDeposit(int x, int y, int z, int map, uint8_t block, uint8_t minDepoSize, uint8_t maxDepoSize, sChunk* chunk)\n{\n    uint8_t depoSize = uint8_t((uniform01() * (maxDepoSize - minDepoSize) + minDepoSize) / 2);\n    int32_t t_posx, t_posy, t_posz;\n    for (int8_t xi = (-depoSize); xi <= depoSize; xi++)\n    {\n        for (int8_t yi = (-depoSize); yi <= depoSize; yi++)\n        {\n            for (int8_t zi = (-depoSize); zi <= depoSize; zi++)\n            {\n                if (abs(xi) + abs(yi) + abs(zi) <= depoSize)\n                {\n                    t_posx = x + xi;\n                    t_posy = y + yi;\n                    t_posz = z + zi;\n\n                    if (t_posz < 0 || t_posz > 15 || t_posx < 0 || t_posx > 15 || t_posy < 1)\n                    {\n                        break;\n                    }\n\n                    if (chunk->blocks[t_posy + (t_posz << 7) + (t_posx << 11)] == BLOCK_STONE)\n                    {\n                        chunk->blocks[t_posy + (t_posz << 7) + (t_posx << 11)] = block;\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/worldgen/eximgen.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _EXIMGEN_H\n#define _EXIMGEN_H\n\n\n#include \"mapgen.h\"\n\n#include <iostream>\n\nstruct BlockRef{\n    BlockRef(sChunk* chunk,int x, int y, int z){\n        int index = x + (z<<4) + (y<<8);\n\n        m_block = chunk->blocks+index;\n        m_data  = chunk->data + (index>>1);\n\n        meta_top = x & 1;\n    }\n\n    uint8_t id(){return *m_block;}\n    uint8_t meta(){\n        if(meta_top) return (*m_data)>>4;\n\n        else return (*m_data)&0xf;\n\n    }\n\n    void id(uint8_t id){\n        *m_block = id;\n    }\n    void meta(uint8_t meta){\n        assert(meta <= 15);\n        if(meta_top){\n            *m_data &= 0xf;\n            *m_data += meta<<4;\n        }\n        else{\n            *m_data &= 0xf0;\n            *m_data += meta;\n        }\n    }\nprivate:\n    uint8_t* m_block;\n    bool     meta_top;\n    uint8_t* m_data;\n};\n\nstruct AnvilAccessor{\n    AnvilAccessor(sChunk* chunk)\n        :m_chunk(chunk){}\n\n    BlockRef operator()(int x, int y, int z){\n        return BlockRef(m_chunk, x, y, z);\n    }\n\nprivate:\n    sChunk* m_chunk;\n};\nstruct ChunkInfo{\n    ChunkInfo(sChunk* chunk):chunk(chunk),blocks(chunk){}\n\n    sChunk* chunk;\n    AnvilAccessor blocks;\n};\n\nclass EximGen: public MapGen\n{\npublic:\n    EximGen();\n    void init(int seed);\n    void re_init(int seed); // Used when generating multiple maps\n    void generateChunk(int x, int z, int map);\n\nprivate:\n    std::vector<uint8_t> blocks;\n    std::vector<uint8_t> blockdata;\n    std::vector<uint8_t> skylight;\n    std::vector<uint8_t> blocklight;\n    std::vector<int32_t> heightmap;\n\n    int seaLevel;\n\n    bool addTrees;\n\n    bool expandBeaches;\n    int beachExtent;\n    int beachHeight;\n\n    bool addOre;\n    bool addCaves;\n    bool winterEnabled;\n\n    void generateWithNoise(ChunkInfo &info);\n\n    void AddOre  (sChunk* chunk);\n    void AddTrees(sChunk* chunk);\n\n    void ExpandBeaches(int x, int z, int map);\n    void AddTrees(int x, int z, int map);\n\n    void AddOre(int x, int z, int map, uint8_t type);\n    void AddDeposit(int x, int y, int z, int map, uint8_t block, uint8_t minDepoSize, uint8_t maxDepoSize, sChunk* chunk);\n\n    // Heightmap composition\n\n    noise::module::RidgedMulti mountainTerrain;\n    noise::module::ScaleBias mountainScale;\n    noise::module::Billow baseFlatTerrain;\n    noise::module::ScaleBias flatTerrain;\n    noise::module::Billow terrainType;\n    noise::module::Select terrainSelector;\n    noise::module::ScaleBias finalTerrain;\n\n    // stuff\n\n    noise::module::RidgedMulti earthNoise;\n    noise::module::Billow caveNoise;\n    // ##### TREE GEN #####\n\n    noise::module::Billow treenoise;\n    // ##### END TREE GEN ####\n\n};\n\n#endif\n"
  },
  {
    "path": "src/worldgen/heavengen.cpp",
    "content": "/*\nCopyright (c) 2010, The Mineserver Project\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n* Neither the name of the The Mineserver Project nor the\nnames of its contributors may be used to endorse or promote products\nderived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cstdlib>\n#include <cstdio>\n#include <iostream>\n#include <string>\n#include <algorithm>\n#include <vector>\n#include <cmath>\n#include <ctime>\n#include <stdio.h>\n#include <stdlib.h>\n\n\n// libnoise\n#ifdef LIBNOISE\n#include <libnoise/noise.h>\n#else\n#include <noise/noise.h>\n#endif\n\n#include \"heavengen.h\"\n#include \"cavegen.h\"\n\n#include \"mineserver.h\"\n#include \"config.h\"\n#include \"constants.h\"\n#include \"logger.h\"\n#include \"map.h\"\n#include \"nbt.h\"\n#include \"tree.h\"\n\n#include \"tools.h\"\n#include \"random.h\"\n\nint heaven_seed;\n\nHeavenGen::HeavenGen()\n  : heightmap(16 * 16, 0)\n{\n}\n\n\nstatic inline int fastrand()\n{\n  heaven_seed = (214013 * heaven_seed + 2531011);\n  return (heaven_seed >> 16) & 0x7FFF;\n}\n\nvoid HeavenGen::init(int seed)\n{\n  heaven_seed = seed;\n\n  Randomgen.SetSeed(seed);\n  Randomgen.SetOctaveCount(6);\n  Randomgen.SetFrequency(1.0 / 180.0);\n  Randomgen.SetLacunarity(2.0);\n  Randomgen2.SetSeed(seed);\n  Randomgen2.SetOctaveCount(6);\n  Randomgen2.SetFrequency(1.0 / 180.0);\n  Randomgen2.SetLacunarity(2.0);\n\n  seaLevel = ServerInstance->config()->iData(\"mapgen.sea.level\");\n  addTrees = false;//ServerInstance->config()->bData(\"mapgen.trees.enabled\");\n  expandBeaches = false;//ServerInstance->config()->bData(\"mapgen.beaches.expand\");\n  beachExtent = false;//ServerInstance->config()->iData(\"mapgen.beaches.extent\");\n  beachHeight = false;//ServerInstance->config()->iData(\"mapgen.beaches.height\");\n  addOre = true;//ServerInstance->config()->bData(\"mapgen.caves.ore\");\n}\n\nvoid HeavenGen::re_init(int seed)\n{\n  Randomgen.SetSeed(seed);\n}\n\nvoid HeavenGen::generateChunk(int x, int z, int map)\n{\n  NBT_Value* main = new NBT_Value(NBT_Value::TAG_COMPOUND);\n  NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n\n  val->Insert(\"Sections\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n\n  val->Insert(\"HeightMap\", new NBT_Value(heightmap));\n  val->Insert(\"Entities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"TileEntities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"LastUpdate\", new NBT_Value((int64_t)time(NULL)));\n  val->Insert(\"xPos\", new NBT_Value(x));\n  val->Insert(\"zPos\", new NBT_Value(z));\n  val->Insert(\"TerrainPopulated\", new NBT_Value((char)1));\n\n  main->Insert(\"Level\", val);\n\n  /*  uint32_t chunkid;\n  ServerInstance->map()->posToId(x, z, &chunkid);\n\n  ServerInstance->map()->maps[chunkid].x = x;\n  ServerInstance->map()->maps[chunkid].z = z; */\n\n  sChunk* chunk = new sChunk();\n  //chunk->blocks = &((*t_blocks)[0]);\n  //chunk->data = &((*t_data)[0]);\n  //chunk->blocklight = &((*t_blocklight)[0]);\n  //chunk->skylight = &((*t_skylight)[0]);\n  chunk->heightmap = &(heightmap[0]);\n  chunk->nbt = main;\n  chunk->x = x;\n  chunk->z = z;\n\n  ServerInstance->map(map)->chunks.insert(ChunkMap::value_type(ChunkMap::key_type(x, z), chunk));\n\n  memset(chunk->blocks, 0, 16*16*256);\n  memset(chunk->addblocks, 0, 16*16*256/2);\n  memset(chunk->data, 0, 16*16*256/2);\n  memset(chunk->blocklight, 0, 16*16*256/2);\n  memset(chunk->skylight, 0, 16*16*256/2);\n  chunk->chunks_present = 0xffff;\n\n  generateWithNoise(x, z, map);\n\n  // Update last used time\n  //ServerInstance->map()->mapLastused[chunkid] = (int)time(0);\n\n  // Not changed\n  //ServerInstance->map()->mapChanged[chunkid] = ServerInstance->config()->bData(\"save_unchanged_chunks\");\n\n  //ServerInstance->map()->maps[chunkid].nbt = main;\n\n  if (addOre)\n  {\n    AddOre(x, z, map, BLOCK_STATIONARY_WATER);\n  }\n\n  // Add trees\n  if (addTrees)\n  {\n    AddTrees(x, z, map,  fastrand() % 2 + 3);\n  }\n\n  if (expandBeaches)\n  {\n    ExpandBeaches(x, z, map);\n  }\n\n}\n\n//#define PRINT_MAPGEN_TIME\n\n\nvoid HeavenGen::AddTrees(int x, int z, int map, uint16_t count)\n{\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockY, blockZ;\n  uint8_t block;\n  uint8_t meta;\n\n  for (uint16_t i = 0; i < count; i++)\n  {\n    blockX = fastrand() % 16;\n    blockZ = fastrand() % 16;\n\n    blockY = heightmap[(blockZ << 4) + blockX] + 1;\n\n    blockX += xBlockpos;\n    blockZ += zBlockpos;\n\n    ServerInstance->map(map)->getBlock(blockX, blockY, blockZ, &block, &meta);\n    // No trees on water\n    if (block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER)\n    {\n      continue;\n    }\n\n    Tree tree(blockX, blockY, blockZ, map);\n  }\n}\n\nvoid HeavenGen::generateWithNoise(int x, int z, int map)\n{\n  // Debug..\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  DWORD t_begin, t_end;\n  t_begin = timeGetTime();\n#else\n  struct timeval start, end;\n  gettimeofday(&start, NULL);\n#endif\n#endif\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n  // Populate blocks in chunk\n  int32_t currentHeight = 0;\n  int32_t ymax = 0;\n  uint16_t ciel = 0;\n  uint8_t* curBlock;\n  uint8_t* curData;\n  uint8_t col[2] = {0, 8};\n\n  double xBlockpos = x << 4;\n  double zBlockpos = z << 4;\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      double h = (int8_t)((Randomgen.GetValue(xBlockpos + bX, 0 , zBlockpos + bZ) * 20));\n      double n = (int8_t)((Randomgen2.GetValue(xBlockpos + bX, 0, zBlockpos + bZ) * 10) + 64);\n\n      heightmap[(bZ << 4) + bX] = (uint8_t)(h + n);\n\n      for (int bY = 0; bY < 128; bY++)\n      {\n        int index = bX + (bZ << 4) + (bY << 8);\n        curBlock = &(chunk->blocks[index]);\n        curData = &(chunk->data[index >> 1]);\n        if (bY > n - h && bY < n)\n        {\n          *curBlock = BLOCK_WOOL;\n          *curData = (index & 1) ? col[rand() % 2] : col[rand() % 2] << 4;\n          continue;\n        }\n        *curBlock = BLOCK_AIR;\n      }\n    }\n  }\n\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  t_end = timeGetTime();\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(t_end - t_begin) + \"ms\");\n#else\n  gettimeofday(&end, NULL);\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(end.tv_usec - start.tv_usec));\n#endif\n#endif\n}\n\nvoid HeavenGen::ExpandBeaches(int x, int z, int map)\n{\n  int beachExtentSqr = (beachExtent + 1) * (beachExtent + 1);\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockZ, h;\n  uint8_t block;\n  uint8_t meta;\n\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      blockX = xBlockpos + bX;\n      blockZ = zBlockpos + bZ;\n\n      h = heightmap[(bZ << 4) + bX];\n\n      if (h < 0)\n      {\n        continue;\n      }\n\n      bool found = false;\n      for (int dx = -beachExtent; !found && dx <= beachExtent; dx++)\n      {\n        for (int dz = -beachExtent; !found && dz <= beachExtent; dz++)\n        {\n          for (int dh = -beachHeight; !found && dh <= 0; dh++)\n          {\n            if (dx * dx + dz * dz + dh * dh > beachExtentSqr)\n            {\n              continue;\n            }\n\n            int xx = bX + dx;\n            int zz = bZ + dz;\n            int hh = h + dh;\n            if (xx < 0 || xx >= 15 || zz < 0 || zz >= 15 || hh < 0 || hh >= 127)\n            {\n              continue;\n            }\n\n            ServerInstance->map(map)->getBlock(xBlockpos + xx, hh, zBlockpos + zz, &block, &meta);\n            if (block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER)\n            {\n              found = true;\n              break;\n            }\n          }\n        }\n      }\n      if (found)\n      {\n        ServerInstance->map(map)->sendBlockChange(blockX, h, blockZ, BLOCK_SAND, 0);\n        ServerInstance->map(map)->setBlock(blockX, h, blockZ, BLOCK_SAND, 0);\n\n        ServerInstance->map(map)->getBlock(blockX, h - 1, blockZ, &block, &meta);\n\n        if (h > 0 && block == BLOCK_DIRT)\n        {\n          ServerInstance->map(map)->sendBlockChange(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n          ServerInstance->map(map)->setBlock(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n        }\n      }\n    }\n  }\n}\n\nvoid HeavenGen::AddOre(int x, int z, int map, uint8_t type)\n{\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockY, blockZ;\n  uint8_t block;\n  uint8_t meta;\n\n  int count, startHeight;\n\n  switch (type)\n  {\n  case BLOCK_STATIONARY_WATER:\n    count = fastrand() % 20 + 20;\n    startHeight = 128;\n    break;\n  }\n\n  int i = 0;\n  while (i < count)\n  {\n    blockX = fastrand() % 8 + 4;\n    blockZ = fastrand() % 8 + 4;\n\n    blockY = heightmap[(blockZ << 4) + blockX];\n    blockY -= 5;\n\n    // Check that startheight is not higher than height at that column\n    if (blockY > startHeight)\n    {\n      blockY = startHeight;\n    }\n\n    blockX += xBlockpos;\n    blockZ += zBlockpos;\n\n    // Calculate Y\n    blockY = fastrand() % blockY;\n\n    i++;\n\n    ServerInstance->map(map)->getBlock(blockX, blockY, blockZ, &block, &meta);\n    // No ore in caves\n    if (block != BLOCK_WOOL)\n    {\n      continue;\n    }\n\n    AddDeposit(blockX, blockY, blockZ, map, type, 2);\n\n  }\n}\n\nvoid HeavenGen::AddDeposit(int x, int y, int z, int map, uint8_t block, int depotSize)\n{\n  for (int bX = x; bX < x + depotSize; bX++)\n  {\n    for (int bY = y; bY < y + depotSize; bY++)\n    {\n      for (int bZ = z; bZ < z + depotSize; bZ++)\n      {\n        if (uniform01() < 0.5)\n        {\n          ServerInstance->map(map)->sendBlockChange(bX, bY, bZ, block, 0);\n          ServerInstance->map(map)->setBlock(bX, bY, bZ, block, 0);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/worldgen/heavengen.h",
    "content": "/*\n   Copyright (c) 2010, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _HEAVENGEN_H\n#define _HEAVENGEN_H\n\n#ifdef LIBNOISE\n#include <libnoise/noise.h>\n#else\n#include <noise/noise.h>\n#endif\n\n#include \"mapgen.h\"\n#include \"cavegen.h\"\n\nclass HeavenGen : public MapGen\n{\npublic:\n  HeavenGen();\n  void init(int seed);\n  void re_init(int seed);\n  void generateChunk(int x, int z, int map);\n\nprivate:\n  std::vector<int32_t> heightmap;\n\n  int seaLevel;\n\n  bool addTrees;\n\n  bool expandBeaches;\n  int beachExtent;\n  int beachHeight;\n\n  bool addOre;\n\n  void generateWithNoise(int x, int z, int map);\n\n  void ExpandBeaches(int x, int z, int map);\n  void AddTrees(int x, int z, int map, uint16_t count);\n\n  void AddOre(int x, int z, int map, uint8_t type);\n  void AddDeposit(int x, int y, int z, int map, uint8_t block, int depotSize);\n\n\n  CaveGen cave;\n\n  // Heightmap composition\n  noise::module::Billow Randomgen;\n  noise::module::Billow Randomgen2;\n\n  /*noise::module::ScaleBias perlinBiased;\n\n  noise::module::Perlin baseFlatTerrain;\n  noise::module::ScaleBias flatTerrain;\n\n  noise::module::Perlin seaFloor;\n  noise::module::ScaleBias seaBias;\n\n  noise::module::Perlin terrainType;\n\n  noise::module::Perlin seaControl;\n\n  noise::module::Select seaTerrain;\n  noise::module::Select finalTerrain;*/\n};\n\n#endif\n"
  },
  {
    "path": "src/worldgen/mapgen.cpp",
    "content": "/*\nCopyright (c) 2011, The Mineserver Project\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n* Neither the name of the The Mineserver Project nor the\nnames of its contributors may be used to endorse or promote products\nderived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n\n// libnoise\n#ifdef LIBNOISE\n#include <libnoise/noise.h>\n#else\n#include <noise/noise.h>\n#endif\n\n#include \"cavegen.h\"\n#include \"mapgen.h\"\n\n#include \"mineserver.h\"\n#include \"config.h\"\n#include \"logger.h\"\n#include \"map.h\"\n#include \"tree.h\"\n\nint g_seed;\nint f_seed;\n\nstatic inline int fastrand()\n{\n  f_seed = (214013 * f_seed + 2531011);\n  return (f_seed >> 16) & 0x7FFF;\n}\n\nMapGen::MapGen()\n  : blocks(16 * 16 * 256, 0),\n    addblocks(16 * 16 * 256 / 2, 0),\n    blockdata(16 * 16 * 256 / 2, 0),\n    skylight(16 * 16 * 256 / 2, 0),\n    blocklight(16 * 16 * 256 / 2, 0),    \n    heightmap(16 * 16, 0)\n{\n}\n\nvoid MapGen::init(int seed)\n{\n  cave.init(seed + 7);\n  f_seed = seed; // used for fastrand and can change\n  g_seed = seed; // used for height map, cannot change\n\n  ridgedMultiNoise.SetSeed(seed);\n  ridgedMultiNoise.SetOctaveCount(6);\n  ridgedMultiNoise.SetFrequency(1.0 / 180.0);\n  ridgedMultiNoise.SetLacunarity(2.0);\n\n  //###### TREE GEN #####\n  treenoise.SetSeed(seed + 2);\n  treenoise.SetOctaveCount(6);\n  treenoise.SetFrequency(1.0 / 180.0);\n  treenoise.SetLacunarity(2.0);\n\n  //###### END TREE GEN #######\n  seaLevel = ServerInstance->config()->iData(\"mapgen.sea.level\");\n  addTrees = ServerInstance->config()->bData(\"mapgen.trees.enabled\");\n  expandBeaches = ServerInstance->config()->bData(\"mapgen.beaches.expand\");\n  beachExtent = ServerInstance->config()->iData(\"mapgen.beaches.extent\");\n  beachHeight = ServerInstance->config()->iData(\"mapgen.beaches.height\");\n\n  addOre = ServerInstance->config()->bData(\"mapgen.addore\");\n  addCaves = ServerInstance->config()->bData(\"mapgen.caves.enabled\");\n\n  winterEnabled = ServerInstance->config()->bData(\"mapgen.winter.enabled\");\n\n}\n\nvoid MapGen::re_init(int seed)\n{\n  cave.init(seed + 7);\n  ridgedMultiNoise.SetSeed(seed);\n  treenoise.SetSeed(seed + 2);\n}\n\n\nvoid MapGen::generateFlatgrass(int x, int z, int map)\n{\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n  Block top = BLOCK_GRASS;\n  if (winterEnabled)\n  {\n    top = BLOCK_SNOW;\n  }\n\n  for (uint32_t bX = 0; bX < 16; bX++)\n  {\n    for (uint32_t bZ = 0; bZ < 16; bZ++)\n    {\n      heightmap[(bZ << 4) + bX] = 64;\n      for (uint32_t bY = 0; bY < 128; bY++)\n      {\n        if (bY == 0)\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = BLOCK_BEDROCK;\n        }\n        else if (bY < 64)\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = BLOCK_DIRT;\n        }\n        else if (bY == 64)\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = top;\n        }\n        else\n        {\n          chunk->blocks[bX + (bZ << 4) + (bY << 8)] = BLOCK_AIR;\n        }\n      }\n    }\n  }  \n}\n\nvoid MapGen::generateChunk(int x, int z, int map)\n{\n  NBT_Value* main = new NBT_Value(NBT_Value::TAG_COMPOUND);\n  NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n\n  val->Insert(\"Sections\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n\n  val->Insert(\"HeightMap\", new NBT_Value(heightmap));\n  val->Insert(\"Entities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"TileEntities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"LastUpdate\", new NBT_Value((int64_t)time(NULL)));\n  val->Insert(\"xPos\", new NBT_Value(x));\n  val->Insert(\"zPos\", new NBT_Value(z));\n  val->Insert(\"TerrainPopulated\", new NBT_Value((int8_t)1));\n\n  main->Insert(\"Level\", val);\n\n  sChunk* chunk = new sChunk();\n  /*\n  chunk->blocks = new uint8_t[16 * 16 * 256];\n  chunk->addblocks = new uint8_t[16 * 16 * 256 / 2];\n  chunk->data = new uint8_t[16 * 16 * 256 / 2];\n  chunk->blocklight = new uint8_t[16 * 16 * 256 / 2];\n  chunk->skylight = new uint8_t[16 * 16 * 256 / 2];\n  */\n  NBT_Value* val1 = (*val)[\"HeightMap\"];\n  chunk->heightmap = val1->GetIntArray()->data();\n\n  chunk->nbt = main;\n  chunk->x = x;\n  chunk->z = z;\n  ServerInstance->map(map)->chunks.insert(ChunkMap::value_type(ChunkMap::key_type(x, z), chunk));\n\n  memset(chunk->blocks, 0, 16*16*256);\n  memset(chunk->addblocks, 0, 16*16*256/2);\n  memset(chunk->data, 0, 16*16*256/2);\n  memset(chunk->blocklight, 0, 16*16*256/2);\n  memset(chunk->skylight, 0, 16*16*256/2);\n  chunk->chunks_present = 0xffff;\n\n  if (ServerInstance->config()->bData(\"mapgen.flatgrass\"))\n  {\n    generateFlatgrass(x, z, map);\n  }\n  else\n  {\n    generateWithNoise(x, z, map);\n  }\n\n\n  // Update last used time\n  //ServerInstance->map()->mapLastused[chunkid] = (int)time(0);\n\n  // Not changed\n  chunk->changed = ServerInstance->config()->bData(\"map.save_unchanged_chunks\");\n\n  //ServerInstance->map()->maps[chunkid].nbt = main;\n  \n  if (addOre)\n  {\n    AddOre(x, z, map, BLOCK_COAL_ORE);\n    AddOre(x, z, map, BLOCK_IRON_ORE);\n    AddOre(x, z, map, BLOCK_GOLD_ORE);\n    AddOre(x, z, map, BLOCK_DIAMOND_ORE);\n    AddOre(x, z, map, BLOCK_REDSTONE_ORE);\n    AddOre(x, z, map, BLOCK_LAPIS_ORE);\n  }\n\n  AddOre(x, z, map, BLOCK_GRAVEL);\n\n  // Add trees\n  if (addTrees)\n  {\n    AddTrees(x, z, map);  // add trees will make a *kind-of* forest of 16*16 chunks\n  }\n\n  if (expandBeaches)\n  {\n    ExpandBeaches(x, z, map);\n  }\n\n}\n\n//#define PRINT_MAPGEN_TIME\n\n\nvoid MapGen::AddTrees(int x, int z, int map)\n{\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockZ;\n  uint8_t blockY;\n\n  uint8_t block;\n  uint8_t meta;\n\n  uint8_t un = fastrand() % 4 + 2;\n  uint8_t vn = fastrand() % 4 + 2;\n\n  float uFactor = (16 / (float)un);   //relational to literal\n  float vFactor = (16 / (float)vn);\n  for (uint8_t u = 0; u < un; u++)\n  {\n    //u for x and v for z iteration\n    for (uint8_t v = 0; v < vn; v++)\n    {\n      uint8_t a = uint8_t(u * uFactor);\n      uint8_t b = uint8_t(v * vFactor);\n\n      blockX = a + xBlockpos;\n      blockZ = b + zBlockpos;\n      blockY = heightmap[(b << 4) + a] + 1;\n\n      ServerInstance->map(map)->getBlock(blockX, blockY, blockZ, &block, &meta);\n\n      // No trees on water, sand or air\n      if (block != BLOCK_WATER && block != BLOCK_STATIONARY_WATER && block != BLOCK_SAND && block != BLOCK_AIR)\n      {\n        if (abs(treenoise.GetValue(blockX, 0, blockZ)) >= 0.9)\n        {\n          Tree tree(blockX, blockY, blockZ, map);\n        }\n      }\n    }\n  }\n}\n\nvoid MapGen::generateWithNoise(int x, int z, int map)\n{\n  // Debug..\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  DWORD t_begin, t_end;\n  t_begin = timeGetTime();\n#else\n  struct timeval start, end;\n  gettimeofday(&start, NULL);\n#endif\n#endif\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n  // Winterland or Summerland\n  Block topBlock = winterEnabled ? BLOCK_SNOW : BLOCK_GRASS;\n\n  // Populate blocks in chunk\n  int32_t currentHeight;\n  int32_t ymax;\n  uint8_t* curBlock;\n\n  double xBlockpos = x << 4;\n  double zBlockpos = z << 4;\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      heightmap[(bZ << 4) + bX] = ymax = currentHeight = (uint8_t)((ridgedMultiNoise.GetValue(xBlockpos + bX, 0, zBlockpos + bZ) * 15) + 64);\n\n      int32_t stoneHeight = (int32_t)(currentHeight * 0.94);\n      //int32_t bYbX = ((bZ << 7) + (bX << 11));\n\n      if (ymax < seaLevel)\n      {\n        ymax = seaLevel;\n      }\n\n      for (int bY = 0; bY <= ymax; bY++)\n      {\n        //New \"Anvil\" format\n        curBlock = &(chunk->blocks[bX + (bZ << 4) + (bY << 8)]);\n\n        // Place bedrock\n        if (bY == 0)\n        {\n          *curBlock = BLOCK_BEDROCK;\n          continue;\n        }\n\n        if (bY < currentHeight)\n        {\n          if (bY < stoneHeight)\n          {\n            *curBlock = BLOCK_STONE;\n            // Add caves\n            if (addCaves)\n            {\n              cave.AddCaves(*curBlock, int(xBlockpos + bX), bY, int(zBlockpos + bZ));\n            }\n          }\n          else\n          {\n            *curBlock = BLOCK_DIRT;\n          }\n        }\n        else if (currentHeight == bY)\n        {\n          if (bY == seaLevel || bY == seaLevel - 1 || bY == seaLevel - 2)\n          {\n            *curBlock = BLOCK_SAND;  // FF\n          }\n          else if (bY < seaLevel - 1)\n          {\n            *curBlock = BLOCK_GRAVEL;  // FF\n          }\n          else\n          {\n            *curBlock = topBlock;  // FF\n          }\n        }\n        else\n        {\n          if (bY <= seaLevel)\n          {\n            *curBlock = BLOCK_WATER;  // FF\n          }\n          else\n          {\n            *curBlock = BLOCK_AIR;  // FF\n          }\n        }\n      }\n    }\n  }\n\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  t_end = timeGetTime();\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(t_end - t_begin) + \"ms\");\n#else\n  gettimeofday(&end, NULL);\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(end.tv_usec - start.tv_usec));\n#endif\n#endif\n}\n\nvoid MapGen::ExpandBeaches(int x, int z, int map)\n{\n  sChunk* chunk = ServerInstance->map(map)->getChunk(blockToChunk(x), blockToChunk(z));\n  int beachExtentSqr = (beachExtent + 1) * (beachExtent + 1);\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockZ, h;\n  uint8_t block = 0;\n  uint8_t meta = 0;\n\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      blockX = xBlockpos + bX;\n      blockZ = zBlockpos + bZ;\n\n      h = heightmap[(bZ << 4) + bX];\n\n      if (h < 0)\n      {\n        continue;\n      }\n\n      bool found = false;\n      for (int dx = -beachExtent; !found && dx <= beachExtent; dx++)\n      {\n        for (int dz = -beachExtent; !found && dz <= beachExtent; dz++)\n        {\n          for (int dh = -beachHeight; !found && dh <= 0; dh++)\n          {\n            if (dx * dx + dz * dz + dh * dh > beachExtentSqr)\n            {\n              continue;\n            }\n\n            int xx = bX + dx;\n            int zz = bZ + dz;\n            int hh = h + dh;\n            if (xx < 0 || xx >= 15 || zz < 0 || zz >= 15 || hh < 0 || hh >= 127)\n            {\n              continue;\n            }\n\n            //ToDo: add getBlock!!\n            if (block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER)\n            {\n              found = true;\n              break;\n            }\n          }\n        }\n      }\n      if (found)\n      {\n        ServerInstance->map(map)->sendBlockChange(blockX, h, blockZ, BLOCK_SAND, 0);\n        ServerInstance->map(map)->setBlock(blockX, h, blockZ, BLOCK_SAND, 0);\n\n        ServerInstance->map(map)->getBlock(blockX, h - 1, blockZ, &block, &meta);\n\n        if (h > 0 && block == BLOCK_DIRT)\n        {\n          ServerInstance->map(map)->sendBlockChange(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n          ServerInstance->map(map)->setBlock(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n        }\n      }\n    }\n  }\n}\n\nvoid MapGen::AddOre(int x, int z, int map, uint8_t type)\n{\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n  int blockX, blockY, blockZ;\n  uint8_t block;\n\n  // Parameters for deposits\n  int count, startHeight, minDepoSize, maxDepoSize;\n\n  switch (type)\n  {\n  case BLOCK_COAL_ORE:\n    count = fastrand() % 10 + 20; // 20-30 coal deposits\n    startHeight = 90;\n    minDepoSize = 3;\n    maxDepoSize = 7;\n    break;\n  case BLOCK_IRON_ORE:\n    count = fastrand() % 8 + 10; // 10-18 iron deposits\n    startHeight = 60;\n    minDepoSize = 2;\n    maxDepoSize = 5;\n    break;\n  case BLOCK_GOLD_ORE:\n    count = fastrand() % 4 + 5; // 4-9 gold deposits\n    startHeight = 32;\n    minDepoSize = 2;\n    maxDepoSize = 4;\n    break;\n  case BLOCK_DIAMOND_ORE:\n    count = fastrand() % 1 + 2; // 1-3 diamond deposits\n    startHeight = 17;\n    minDepoSize = 1;\n    maxDepoSize = 2;\n    break;\n  case BLOCK_REDSTONE_ORE:\n    count = fastrand() % 5 + 5; // 5-10 redstone deposits\n    startHeight = 25;\n    minDepoSize = 2;\n    maxDepoSize = 4;\n    break;\n  case BLOCK_LAPIS_ORE:\n    count = fastrand() % 1 + 2; // 1-3 lapis lazuli deposits\n    startHeight = 17;\n    minDepoSize = 1;\n    maxDepoSize = 2;\n    break;\n  case BLOCK_GRAVEL:\n    count = fastrand() % 10 + 20; // 20-30 gravel deposits\n    startHeight = 90;\n    minDepoSize = 4;\n    maxDepoSize = 10;\n    break;\n  default:\n    return;\n  }\n\n  int i = 0;\n  while (i < count)\n  {\n    blockX = fastrand() % 8 + 4;\n    blockZ = fastrand() % 8 + 4;\n\n    blockY = heightmap[(blockZ << 4) + blockX];\n    blockY -= 5;\n\n    // Check that startheight is not higher than height at that column\n    if (blockY > startHeight)\n    {\n      blockY = startHeight;\n    }\n\n    //blockX += xBlockpos;\n    //blockZ += zBlockpos;\n\n    // Calculate Y\n    blockY = fastrand() % blockY;\n\n    i++;\n\n    block = chunk->blocks[blockX + (blockZ << 4) + (blockY << 8)];\n    // No ore in caves\n    if (block == BLOCK_AIR)\n    {\n      continue;\n    }\n\n    AddDeposit(blockX, blockY, blockZ, map, type, minDepoSize, maxDepoSize, chunk);\n\n  }\n}\n\nvoid MapGen::AddDeposit(int x, int y, int z, int map, uint8_t block, int minDepoSize, int maxDepoSize, sChunk* chunk)\n{\n  int depoSize = fastrand() % (maxDepoSize - minDepoSize) + minDepoSize;\n  for (int i = 0; i < depoSize; i++)\n  {\n    if (chunk->blocks[x + (z << 4) + (y << 8)] != BLOCK_GRASS ||\n        chunk->blocks[x + (z << 4) + (y << 8)] != BLOCK_SNOW)\n    {\n      chunk->blocks[x + (z << 4) + (y << 8)] = block;\n    }\n\n    z = z + ((fastrand() % 2) - 1);\n    x = x + ((fastrand() % 2) - 1);\n    y = y + ((fastrand() % 2) - 1);\n\n    // If over chunk borders\n    if (z < 0 || z > 15 || x < 0 || x > 15 || y < 1)\n    {\n      break;\n    }\n  }\n}\n"
  },
  {
    "path": "src/worldgen/mapgen.h",
    "content": "/*\n   Copyright (c) 2011, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _MAPGEN_H\n#define _MAPGEN_H\n\n#ifdef LIBNOISE\n#include <libnoise/noise.h>\n#else\n#include <noise/noise.h>\n#endif\n\n#include \"cavegen.h\"\n#include \"map.h\"\n\nclass MapGen\n{\npublic:\n  MapGen();\n  virtual ~MapGen() { }\n  virtual void init(int seed);\n  virtual void re_init(int seed); // Used when generating multiple maps\n  virtual void generateChunk(int x, int z, int map);\nprivate:\n  std::vector<uint8_t> blocks;\n  std::vector<uint8_t> addblocks;\n  std::vector<uint8_t> blockdata;\n  std::vector<uint8_t> skylight;\n  std::vector<uint8_t> blocklight;\n  std::vector<int32_t> heightmap;\n\n  int seaLevel;\n\n  bool addTrees;\n\n  bool expandBeaches;\n  int beachExtent;\n  int beachHeight;\n\n  bool addOre;\n  bool addCaves;\n  bool winterEnabled;\n\nprotected:\n\n  virtual void generateFlatgrass(int x, int z, int map);\n  virtual void generateWithNoise(int x, int z, int map);\n\n  virtual void ExpandBeaches(int x, int z, int map);\n  virtual void AddTrees(int x, int z, int map);\n\n  virtual void AddOre(int x, int z, int map, uint8_t type);\n  virtual void AddDeposit(int x, int y, int z, int map, uint8_t block, int minDepoSize, int maxDepoSize, sChunk* chunk);\nprivate:\n  CaveGen cave;\n\n  // Heightmap composition\n  noise::module::RidgedMulti ridgedMultiNoise;\n\n  // ##### TREE GEN #####\n\n  noise::module::Billow treenoise;\n  // ##### END TREE GEN ####\n\n  /*noise::module::ScaleBias perlinBiased;\n\n  noise::module::Perlin baseFlatTerrain;\n  noise::module::ScaleBias flatTerrain;\n\n  noise::module::Perlin seaFloor;\n  noise::module::ScaleBias seaBias;\n\n  noise::module::Perlin terrainType;\n\n  noise::module::Perlin seaControl;\n\n  noise::module::Select seaTerrain;\n  noise::module::Select finalTerrain;*/\n};\n\n\n#endif\n"
  },
  {
    "path": "src/worldgen/nethergen.cpp",
    "content": "/*\nCopyright (c) 2010, The Mineserver Project\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\n* Neither the name of the The Mineserver Project nor the\nnames of its contributors may be used to endorse or promote products\nderived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#include <cstdlib>\n#include <cstdio>\n#include <iostream>\n#include <string>\n#include <algorithm>\n#include <vector>\n#include <cmath>\n#include <ctime>\n#include <stdio.h>\n#include <stdlib.h>\n\n\n// libnoise\n#ifdef LIBNOISE\n#include <libnoise/noise.h>\n#else\n#include <noise/noise.h>\n#endif\n\n#include \"nethergen.h\"\n#include \"cavegen.h\"\n\n#include \"mineserver.h\"\n#include \"config.h\"\n#include \"constants.h\"\n#include \"logger.h\"\n#include \"map.h\"\n#include \"nbt.h\"\n#include \"tree.h\"\n\n#include \"tools.h\"\n#include \"random.h\"\n\nint neth_seed;\n\nNetherGen::NetherGen()\n  : heightmap(16 * 16, 0)\n{\n}\n\ninline int fastrand()\n{\n  neth_seed = (214013 * neth_seed + 2531011);\n  return (neth_seed >> 16) & 0x7FFF;\n}\n\nvoid NetherGen::init(int seed)\n{\n  neth_seed = seed;\n\n  Randomgen.SetSeed(seed);\n  Randomgen.SetFrequency(0.1);\n  Randomciel.SetSeed(seed);\n  Randomciel.SetOctaveCount(6);\n  Randomciel.SetFrequency(1.0 / 180.0);\n  Randomciel.SetLacunarity(2.0);\n\n  seaLevel = ServerInstance->config()->iData(\"mapgen.sea.level\");\n  addTrees = false;//ServerInstance->config()->bData(\"mapgen.trees.enabled\");\n  expandBeaches = false;//ServerInstance->config()->bData(\"mapgen.beaches.expand\");\n  beachExtent = false;//ServerInstance->config()->iData(\"mapgen.beaches.extent\");\n  beachHeight = false;//ServerInstance->config()->iData(\"mapgen.beaches.height\");\n\n  addOre = true;//ServerInstance->config()->bData(\"mapgen.caves.ore\");\n}\n\nvoid NetherGen::re_init(int seed)\n{\n  Randomgen.SetSeed(seed);\n}\n\nvoid NetherGen::generateChunk(int x, int z, int map)\n{\n  NBT_Value* main = new NBT_Value(NBT_Value::TAG_COMPOUND);\n  NBT_Value* val = new NBT_Value(NBT_Value::TAG_COMPOUND);\n\n  val->Insert(\"Sections\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND)); \n\n  val->Insert(\"HeightMap\", new NBT_Value(heightmap));\n  val->Insert(\"Entities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"TileEntities\", new NBT_Value(NBT_Value::TAG_LIST, NBT_Value::TAG_COMPOUND));\n  val->Insert(\"LastUpdate\", new NBT_Value((int64_t)time(NULL)));\n  val->Insert(\"xPos\", new NBT_Value(x));\n  val->Insert(\"zPos\", new NBT_Value(z));\n  val->Insert(\"TerrainPopulated\", new NBT_Value((char)1));\n\n  main->Insert(\"Level\", val);\n\n  /*  uint32_t chunkid;\n  ServerInstance->map()->posToId(x, z, &chunkid);\n\n  ServerInstance->map()->maps[chunkid].x = x;\n  ServerInstance->map()->maps[chunkid].z = z; */\n\n  sChunk* chunk = new sChunk();\n  //chunk->blocks = &((*t_blocks)[0]);\n  //chunk->data = &((*t_data)[0]);\n  //chunk->blocklight = &((*t_blocklight)[0]);\n  //chunk->skylight = &((*t_skylight)[0]);\n  chunk->heightmap = &(heightmap[0]);\n  chunk->nbt = main;\n  chunk->x = x;\n  chunk->z = z;\n\n  ServerInstance->map(map)->chunks.insert(ChunkMap::value_type(ChunkMap::key_type(x, z), chunk));\n\n  memset(chunk->blocks, 0, 16*16*256);\n  memset(chunk->addblocks, 0, 16*16*256/2);\n  memset(chunk->data, 0, 16*16*256/2);\n  memset(chunk->blocklight, 0, 16*16*256/2);\n  memset(chunk->skylight, 0, 16*16*256/2);\n  chunk->chunks_present = 0xffff;\n\n  generateWithNoise(x, z, map);\n\n  // Update last used time\n  //ServerInstance->map()->mapLastused[chunkid] = (int)time(0);\n\n  // Not changed\n  //ServerInstance->map()->mapChanged[chunkid] = ServerInstance->config()->bData(\"save_unchanged_chunks\");\n\n  //ServerInstance->map()->maps[chunkid].nbt = main;\n\n  if (addOre)\n  {\n    AddOre(x, z, map, BLOCK_GLOWSTONE);\n    AddOre(x, z, map, BLOCK_STATIONARY_LAVA);\n  }\n\n  // Add trees\n  if (addTrees)\n  {\n    AddTrees(x, z, map,  fastrand() % 2 + 3);\n  }\n\n  if (expandBeaches)\n  {\n    ExpandBeaches(x, z, map);\n  }\n\n}\n\n//#define PRINT_MAPGEN_TIME\n\n\nvoid NetherGen::AddTrees(int x, int z, int map, uint16_t count)\n{\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockY, blockZ;\n  uint8_t block;\n  uint8_t meta;\n\n  for (uint16_t i = 0; i < count; i++)\n  {\n    blockX = fastrand() % 16;\n    blockZ = fastrand() % 16;\n\n    blockY = heightmap[(blockZ << 4) + blockX] + 1;\n\n    blockX += xBlockpos;\n    blockZ += zBlockpos;\n\n    ServerInstance->map(map)->getBlock(blockX, blockY, blockZ, &block, &meta);\n    // No trees on water\n    if (block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER)\n    {\n      continue;\n    }\n\n    Tree tree(blockX, blockY, blockZ, map);\n  }\n}\n\nvoid NetherGen::generateWithNoise(int x, int z, int map)\n{\n  // Debug..\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  DWORD t_begin, t_end;\n  t_begin = timeGetTime();\n#else\n  struct timeval start, end;\n  gettimeofday(&start, NULL);\n#endif\n#endif\n  sChunk* chunk = ServerInstance->map(map)->getChunk(x, z);\n\n  // Populate blocks in chunk\n  int32_t currentHeight;\n  int32_t ymax;\n  uint16_t ciel;\n  uint8_t* curBlock;\n\n  double xBlockpos = x << 4;\n  double zBlockpos = z << 4;\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      double ciel2 = (Randomciel.GetValue(xBlockpos + bX, 0 , zBlockpos + bZ) * 1.5);\n      ciel = 128 - (uint16_t)(abs(ciel2 * ciel2 * ciel2 * ciel2 * ciel2 * ciel2)); // Cubed! Get some good stalagtites!\n      heightmap[(bZ << 4) + bX] = ymax = currentHeight = (uint8_t)((Randomgen.GetValue(xBlockpos + bX, 0, zBlockpos + bZ) * 15) + 64);\n\n      int32_t stoneHeight = (int32_t)(currentHeight * 0.94);\n      int32_t bYbX = ((bZ << 7) + (bX << 11));\n\n      if (ymax < seaLevel)\n      {\n        ymax = seaLevel;\n      }\n\n      for (int bY = 0; bY < 128; bY++)\n      {\n        int index = bX + (bZ << 4) + (bY << 8);\n        curBlock = &(chunk->blocks[index]);\n        if (bY >= 126)\n        {\n          *curBlock = BLOCK_BEDROCK;\n          continue;\n        }\n        if (bY == 0)\n        {\n          *curBlock = BLOCK_BEDROCK;\n          continue;\n        }\n        if (bY > ciel)\n        {\n          *curBlock = BLOCK_NETHERSTONE;\n          continue;\n        }\n\n\n        if (bY < currentHeight)\n        {\n          if (bY < stoneHeight)\n          {\n            *curBlock = BLOCK_NETHERSTONE;\n            // Add caves\n            //            cave.AddCaves(*curBlock, xBlockpos + bX, bY, zBlockpos + bZ, map);\n          }\n          else\n          {\n            *curBlock = BLOCK_NETHERSTONE;\n          }\n        }\n        else if (currentHeight == bY)\n        {\n          if (bY == seaLevel || bY == seaLevel - 1 || bY == seaLevel - 2)\n          {\n            *curBlock = BLOCK_SLOW_SAND;  // FF\n          }\n          else if (bY < seaLevel - 1)\n          {\n            *curBlock = BLOCK_GRAVEL;  // FF\n          }\n          else\n          {\n            *curBlock = BLOCK_NETHERSTONE;  // FF\n          }\n        }\n        else\n        {\n          if (bY <= seaLevel)\n          {\n            *curBlock = BLOCK_STATIONARY_LAVA;  // FF\n          }\n          else\n          {\n            *curBlock = BLOCK_AIR;  // FF\n          }\n        }\n      }\n    }\n  }\n\n#ifdef PRINT_MAPGEN_TIME\n#ifdef WIN32\n  t_end = timeGetTime();\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(t_end - t_begin) + \"ms\");\n#else\n  gettimeofday(&end, NULL);\n  ServerInstance->logger()->log(\"Mapgen: \" + dtos(end.tv_usec - start.tv_usec));\n#endif\n#endif\n}\n\nvoid NetherGen::ExpandBeaches(int x, int z, int map)\n{\n  int beachExtentSqr = (beachExtent + 1) * (beachExtent + 1);\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockZ, h;\n  uint8_t block;\n  uint8_t meta;\n\n  for (int bX = 0; bX < 16; bX++)\n  {\n    for (int bZ = 0; bZ < 16; bZ++)\n    {\n      blockX = xBlockpos + bX;\n      blockZ = zBlockpos + bZ;\n\n      h = heightmap[(bZ << 4) + bX];\n\n      if (h < 0)\n      {\n        continue;\n      }\n\n      bool found = false;\n      for (int dx = -beachExtent; !found && dx <= beachExtent; dx++)\n      {\n        for (int dz = -beachExtent; !found && dz <= beachExtent; dz++)\n        {\n          for (int dh = -beachHeight; !found && dh <= 0; dh++)\n          {\n            if (dx * dx + dz * dz + dh * dh > beachExtentSqr)\n            {\n              continue;\n            }\n\n            int xx = bX + dx;\n            int zz = bZ + dz;\n            int hh = h + dh;\n            if (xx < 0 || xx >= 15 || zz < 0 || zz >= 15 || hh < 0 || hh >= 127)\n            {\n              continue;\n            }\n\n            ServerInstance->map(map)->getBlock(xBlockpos + xx, hh, zBlockpos + zz, &block, &meta);\n            if (block == BLOCK_WATER || block == BLOCK_STATIONARY_WATER)\n            {\n              found = true;\n              break;\n            }\n          }\n        }\n      }\n      if (found)\n      {\n        ServerInstance->map(map)->sendBlockChange(blockX, h, blockZ, BLOCK_SAND, 0);\n        ServerInstance->map(map)->setBlock(blockX, h, blockZ, BLOCK_SAND, 0);\n\n        ServerInstance->map(map)->getBlock(blockX, h - 1, blockZ, &block, &meta);\n\n        if (h > 0 && block == BLOCK_DIRT)\n        {\n          ServerInstance->map(map)->sendBlockChange(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n          ServerInstance->map(map)->setBlock(blockX, h - 1, blockZ, BLOCK_SAND, 0);\n        }\n      }\n    }\n  }\n}\n\nvoid NetherGen::AddOre(int x, int z, int map, uint8_t type)\n{\n  int xBlockpos = x << 4;\n  int zBlockpos = z << 4;\n\n  int blockX, blockY, blockZ;\n  uint8_t block;\n  uint8_t meta;\n\n  int count, startHeight;\n\n  switch (type)\n  {\n  case BLOCK_GLOWSTONE:\n    count = fastrand() % 4 + 15;\n    startHeight = 128;\n    break;\n  case BLOCK_STATIONARY_LAVA:\n    count = fastrand() % 20 + 20;\n    startHeight = 128;\n    break;\n  }\n\n  int i = 0;\n  while (i < count)\n  {\n    blockX = fastrand() % 8 + 4;\n    blockZ = fastrand() % 8 + 4;\n\n    blockY = heightmap[(blockZ << 4) + blockX];\n    blockY -= 5;\n\n    // Check that startheight is not higher than height at that column\n    if (blockY > startHeight)\n    {\n      blockY = startHeight;\n    }\n\n    blockX += xBlockpos;\n    blockZ += zBlockpos;\n\n    // Calculate Y\n    blockY = fastrand() % blockY;\n\n    i++;\n\n    ServerInstance->map(map)->getBlock(blockX, blockY, blockZ, &block, &meta);\n    // No ore in caves\n    if (block != BLOCK_NETHERSTONE)\n    {\n      continue;\n    }\n\n    AddDeposit(blockX, blockY, blockZ, map, type, 2);\n\n  }\n}\n\nvoid NetherGen::AddDeposit(int x, int y, int z, int map, uint8_t block, int depotSize)\n{\n  for (int bX = x; bX < x + depotSize; bX++)\n  {\n    for (int bY = y; bY < y + depotSize; bY++)\n    {\n      for (int bZ = z; bZ < z + depotSize; bZ++)\n      {\n        if (uniform01() < 0.5)\n        {\n          ServerInstance->map(map)->sendBlockChange(bX, bY, bZ, block, 0);\n          ServerInstance->map(map)->setBlock(bX, bY, bZ, block, 0);\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/worldgen/nethergen.h",
    "content": "/*\n   Copyright (c) 2010, The Mineserver Project\n   All rights reserved.\n\n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n  * Neither the name of the The Mineserver Project nor the\n    names of its contributors may be used to endorse or promote products\n    derived from this software without specific prior written permission.\n\n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY\n  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef _NETHERGEN_H\n#define _NETHERGEN_H\n\n#ifdef LIBNOISE\n#include <libnoise/noise.h>\n#else\n#include <noise/noise.h>\n#endif\n\n#include \"mapgen.h\"\n#include \"cavegen.h\"\n\nclass NetherGen : public MapGen\n{\npublic:\n  NetherGen();\n  void init(int seed);\n  void re_init(int seed);\n  void generateChunk(int x, int z, int map);\n\nprivate:\n  std::vector<int32_t> heightmap;\n\n  int seaLevel;\n\n  bool addTrees;\n\n  bool expandBeaches;\n  int beachExtent;\n  int beachHeight;\n\n  bool addOre;\n\n  void generateWithNoise(int x, int z, int map);\n\n  void ExpandBeaches(int x, int z, int map);\n  void AddTrees(int x, int z, int map, uint16_t count);\n\n  void AddOre(int x, int z, int map, uint8_t type);\n  void AddDeposit(int x, int y, int z, int map, uint8_t block, int depotSize);\n\n\n  CaveGen cave;\n\n  // Heightmap composition\n  noise::module::Voronoi Randomgen;\n  noise::module::Billow Randomciel;\n\n  /*noise::module::ScaleBias perlinBiased;\n\n  noise::module::Perlin baseFlatTerrain;\n  noise::module::ScaleBias flatTerrain;\n\n  noise::module::Perlin seaFloor;\n  noise::module::ScaleBias seaBias;\n\n  noise::module::Perlin terrainType;\n\n  noise::module::Perlin seaControl;\n\n  noise::module::Select seaTerrain;\n  noise::module::Select finalTerrain;*/\n};\n\n#endif\n"
  },
  {
    "path": "win32/mineserver.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\src\\blocks\\basic.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\bed.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\blockbrewingstand.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\cake.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\chest.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\default.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\door.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\falling.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\fire.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\blockfurnace.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\ice.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\jackolantern.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\ladder.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\leaves.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\liquid.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\note.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\planks.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\plant.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\pumpkin.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\redstone.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\redstoneutil.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\sign.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\snow.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\stair.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\step.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\tnt.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\torch.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\tracks.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\wood.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\wool.cpp\" />\n    <ClCompile Include=\"..\\src\\blocks\\workbench.cpp\" />\n    <ClCompile Include=\"..\\src\\chat.cpp\" />\n    <ClCompile Include=\"..\\src\\cliScreen.cpp\" />\n    <ClCompile Include=\"..\\src\\config\\lexer.cpp\" />\n    <ClCompile Include=\"..\\src\\config\\node.cpp\" />\n    <ClCompile Include=\"..\\src\\config\\parser.cpp\" />\n    <ClCompile Include=\"..\\src\\config\\scanner.cpp\" />\n    <ClCompile Include=\"..\\src\\constants.cpp\" />\n    <ClCompile Include=\"..\\src\\furnace.cpp\" />\n    <ClCompile Include=\"..\\src\\furnaceManager.cpp\" />\n    <ClCompile Include=\"..\\src\\inventory.cpp\" />\n    <ClCompile Include=\"..\\src\\inventory\\inventoryBasic.cpp\" />\n    <ClCompile Include=\"..\\src\\inventory\\inventoryBrewingstand.cpp\" />\n    <ClCompile Include=\"..\\src\\inventory\\inventoryChest.cpp\" />\n    <ClCompile Include=\"..\\src\\inventory\\inventoryFurnace.cpp\" />\n    <ClCompile Include=\"..\\src\\inventory\\inventoryPlayer.cpp\" />\n    <ClCompile Include=\"..\\src\\inventory\\inventoryWorkbench.cpp\" />\n    <ClCompile Include=\"..\\src\\items\\itembasic.cpp\" />\n    <ClCompile Include=\"..\\src\\items\\food.cpp\" />\n    <ClCompile Include=\"..\\src\\items\\projectile.cpp\" />\n    <ClCompile Include=\"..\\src\\json.cpp\" />\n    <ClCompile Include=\"..\\src\\lighting.cpp\" />\n    <ClCompile Include=\"..\\src\\logger.cpp\" />\n    <ClCompile Include=\"..\\src\\map.cpp\" />\n    <ClCompile Include=\"..\\src\\mcregion.cpp\" />\n    <ClCompile Include=\"..\\src\\metadata.cpp\" />\n    <ClCompile Include=\"..\\src\\mineserver.cpp\" />\n    <ClCompile Include=\"..\\src\\mob.cpp\" />\n    <ClCompile Include=\"..\\src\\nbt.cpp\" />\n    <ClCompile Include=\"..\\src\\packets.cpp\" />\n    <ClCompile Include=\"..\\src\\physics.cpp\" />\n    <ClCompile Include=\"..\\src\\plugin.cpp\" />\n    <ClCompile Include=\"..\\src\\plugin_api.cpp\" />\n    <ClCompile Include=\"..\\src\\protocol.cpp\" />\n    <ClCompile Include=\"..\\src\\random.cpp\" />\n    <ClCompile Include=\"..\\src\\redstoneSimulation.cpp\" />\n    <ClCompile Include=\"..\\src\\screenBase.cpp\" />\n    <ClCompile Include=\"..\\src\\signalhandler.cpp\" />\n    <ClCompile Include=\"..\\src\\sockets.cpp\" />\n    <ClCompile Include=\"..\\src\\threadpool.cpp\" />\n    <ClCompile Include=\"..\\src\\tools.cpp\" />\n    <ClCompile Include=\"..\\src\\tree.cpp\" />\n    <ClCompile Include=\"..\\src\\user.cpp\" />\n    <ClCompile Include=\"..\\src\\worldgen\\biomegen.cpp\" />\n    <ClCompile Include=\"..\\src\\worldgen\\cavegen.cpp\" />\n    <ClCompile Include=\"..\\src\\worldgen\\eximgen.cpp\" />\n    <ClCompile Include=\"..\\src\\worldgen\\heavengen.cpp\" />\n    <ClCompile Include=\"..\\src\\worldgen\\mapgen.cpp\" />\n    <ClCompile Include=\"..\\src\\worldgen\\nethergen.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\src\\blocks\\blockbrewingstand.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\planks.h\" />\n    <ClInclude Include=\"..\\src\\chat.h\" />\n    <ClInclude Include=\"..\\src\\chunkmap.h\" />\n    <ClInclude Include=\"..\\src\\cliScreen.h\" />\n    <ClInclude Include=\"..\\src\\config.h\" />\n    <ClInclude Include=\"..\\src\\constants.h\" />\n    <ClInclude Include=\"..\\src\\constants_num.h\" />\n    <ClInclude Include=\"..\\src\\extern.h\" />\n    <ClInclude Include=\"..\\src\\furnace.h\" />\n    <ClInclude Include=\"..\\src\\furnaceManager.h\" />\n    <ClInclude Include=\"..\\src\\inventory.h\" />\n    <ClInclude Include=\"..\\src\\inventory\\inventorybasic.h\" />\n    <ClInclude Include=\"..\\src\\inventory\\inventoryBrewingstand.h\" />\n    <ClInclude Include=\"..\\src\\inventory\\inventoryChest.h\" />\n    <ClInclude Include=\"..\\src\\inventory\\inventoryFurnace.h\" />\n    <ClInclude Include=\"..\\src\\inventory\\inventoryPlayer.h\" />\n    <ClInclude Include=\"..\\src\\inventory\\inventoryWorkbench.h\" />\n    <ClInclude Include=\"..\\src\\json.h\" />\n    <ClInclude Include=\"..\\src\\lighting.h\" />\n    <ClInclude Include=\"..\\src\\logger.h\" />\n    <ClInclude Include=\"..\\src\\logtype.h\" />\n    <ClInclude Include=\"..\\src\\map.h\" />\n    <ClInclude Include=\"..\\src\\mcregion.h\" />\n    <ClInclude Include=\"..\\src\\metadata.h\" />\n    <ClInclude Include=\"..\\src\\mineserver.h\" />\n    <ClInclude Include=\"..\\src\\mob.h\" />\n    <ClInclude Include=\"..\\src\\nbt.h\" />\n    <ClInclude Include=\"..\\src\\packets.h\" />\n    <ClInclude Include=\"..\\src\\permissions.h\" />\n    <ClInclude Include=\"..\\src\\physics.h\" />\n    <ClInclude Include=\"..\\src\\plugin.h\" />\n    <ClInclude Include=\"..\\src\\plugin_api.h\" />\n    <ClInclude Include=\"..\\src\\protocol.h\" />\n    <ClInclude Include=\"..\\src\\random.h\" />\n    <ClInclude Include=\"..\\src\\redstoneSimulation.h\" />\n    <ClInclude Include=\"..\\src\\screenBase.h\" />\n    <ClInclude Include=\"..\\src\\signalhandler.h\" />\n    <ClInclude Include=\"..\\src\\sockets.h\" />\n    <ClInclude Include=\"..\\src\\threadpool.h\" />\n    <ClInclude Include=\"..\\src\\tools.h\" />\n    <ClInclude Include=\"..\\src\\tree.h\" />\n    <ClInclude Include=\"..\\src\\user.h\" />\n    <ClInclude Include=\"..\\src\\utf8.h\" />\n    <ClInclude Include=\"..\\src\\vec.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\basic.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\bed.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\cake.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\chest.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\default.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\door.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\falling.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\fire.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\blockfurnace.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\ice.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\jackolantern.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\ladder.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\leaves.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\liquid.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\note.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\plant.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\pumpkin.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\redstone.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\redstoneutil.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\sign.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\snow.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\stair.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\step.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\tnt.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\torch.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\tracks.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\wood.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\wool.h\" />\n    <ClInclude Include=\"..\\src\\blocks\\workbench.h\" />\n    <ClInclude Include=\"..\\src\\config\\lexer.h\" />\n    <ClInclude Include=\"..\\src\\config\\node.h\" />\n    <ClInclude Include=\"..\\src\\config\\parser.h\" />\n    <ClInclude Include=\"..\\src\\config\\scanner.h\" />\n    <ClInclude Include=\"..\\src\\items\\itembasic.h\" />\n    <ClInclude Include=\"..\\src\\items\\food.h\" />\n    <ClInclude Include=\"..\\src\\items\\projectile.h\" />\n    <ClInclude Include=\"..\\src\\worldgen\\biomegen.h\" />\n    <ClInclude Include=\"..\\src\\worldgen\\cavegen.h\" />\n    <ClInclude Include=\"..\\src\\worldgen\\eximgen.h\" />\n    <ClInclude Include=\"..\\src\\worldgen\\heavengen.h\" />\n    <ClInclude Include=\"..\\src\\worldgen\\mapgen.h\" />\n    <ClInclude Include=\"..\\src\\worldgen\\nethergen.h\" />\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{7F6D1DAB-AA49-4343-B28E-C3E647BE5007}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>mineserver</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>NotSet</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>..\\bin\\</OutDir>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <LibraryPath>$(LibraryPath)</LibraryPath>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <OutDir>..\\bin\\</OutDir>\n    <IncludePath>C:\\Libraries\\Include;C:\\Libraries\\Include\\noise;$(IncludePath)</IncludePath>\n    <LibraryPath>C:\\Libraries\\Lib;$(LibraryPath)</LibraryPath>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;FADOR_PLUGIN;ZLIB_WINAPI;WIN32;DEBUG;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\include;..\\src;..\\buildpack\\include</AdditionalIncludeDirectories>\n      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\n      <FloatingPointModel>Fast</FloatingPointModel>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>libeay32.lib;ssleay32.lib;Winmm.lib;libnoise.lib;zlibwapi.lib;ws2_32.lib;libevent2.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <IgnoreSpecificDefaultLibraries>\n      </IgnoreSpecificDefaultLibraries>\n      <AdditionalLibraryDirectories>..\\buildpack\\lib\\</AdditionalLibraryDirectories>\n      <IgnoreAllDefaultLibraries>\n      </IgnoreAllDefaultLibraries>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>Full</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>FADOR_PLUGIN;WIN32;ZLIB_WINAPI;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CONSOLE;FTLOG=main;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>..\\include;..\\src</AdditionalIncludeDirectories>\n      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\n      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\n      <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\n      <FloatingPointModel>Fast</FloatingPointModel>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>false</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalDependencies>libeay32.lib;ssleay32.lib;Winmm.lib;libnoise.lib;zlibwapi.lib;libevent2.lib;Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n      <IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>\n      <AdditionalLibraryDirectories>\n      </AdditionalLibraryDirectories>\n      <TargetMachine>MachineX86</TargetMachine>\n      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>\n    </Link>\n    <ProjectReference>\n      <LinkLibraryDependencies>true</LinkLibraryDependencies>\n    </ProjectReference>\n  </ItemDefinitionGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "win32/mineserver.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n    <Filter Include=\"Source Files\\blocks\">\n      <UniqueIdentifier>{870a5f20-960c-468d-972e-b58632ca9da4}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\blocks\">\n      <UniqueIdentifier>{f8adaa3c-7ce8-4860-8fb2-305620e4f527}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\worldgen\">\n      <UniqueIdentifier>{67561735-9ec3-4f30-bc24-0c9768904c82}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\worldgen\">\n      <UniqueIdentifier>{df9fe047-e832-4669-b0be-34ad4724c27b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\config\">\n      <UniqueIdentifier>{0baca56f-782f-4238-ba00-017805fc77d9}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\config\">\n      <UniqueIdentifier>{95555770-77f1-4062-bc60-1316f8fb0126}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\items\">\n      <UniqueIdentifier>{b267b476-9ab6-46df-9a96-31f41bbbbc3b}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\items\">\n      <UniqueIdentifier>{aefe9250-04b8-4fba-81c9-5a99749255a5}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\inventory\">\n      <UniqueIdentifier>{2c8ce177-f098-44b2-b182-1a5d19541212}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\inventory\">\n      <UniqueIdentifier>{91c91d8f-cfdc-4861-afbf-090414621a14}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\src\\user.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\mineserver.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\map.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\chat.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\nbt.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\tools.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\logger.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\sockets.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\packets.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\constants.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\physics.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\plugin.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\door.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\falling.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\fire.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\liquid.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\plant.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\sign.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\snow.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\stair.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\torch.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\worldgen\\mapgen.cpp\">\n      <Filter>Source Files\\worldgen</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\worldgen\\cavegen.cpp\">\n      <Filter>Source Files\\worldgen</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\default.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\basic.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\furnaceManager.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\furnace.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\chest.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\tracks.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\tree.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\inventory.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\config\\scanner.cpp\">\n      <Filter>Source Files\\config</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\config\\lexer.cpp\">\n      <Filter>Source Files\\config</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\config\\node.cpp\">\n      <Filter>Source Files\\config</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\config\\parser.cpp\">\n      <Filter>Source Files\\config</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\plugin_api.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\screenBase.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\cliScreen.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\ladder.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\lighting.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\cake.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\worldgen\\heavengen.cpp\">\n      <Filter>Source Files\\worldgen</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\worldgen\\nethergen.cpp\">\n      <Filter>Source Files\\worldgen</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\mob.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\note.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\workbench.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\blockfurnace.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\items\\food.cpp\">\n      <Filter>Source Files\\items</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\items\\itembasic.cpp\">\n      <Filter>Source Files\\items</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\items\\projectile.cpp\">\n      <Filter>Source Files\\items</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\worldgen\\biomegen.cpp\">\n      <Filter>Source Files\\worldgen</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\redstone.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\mcregion.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\worldgen\\eximgen.cpp\">\n      <Filter>Source Files\\worldgen</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\leaves.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\pumpkin.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\bed.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\step.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\jackolantern.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\wool.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\wood.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\tnt.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\ice.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\metadata.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\random.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\signalhandler.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\redstoneSimulation.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\redstoneutil.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\protocol.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\planks.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\blocks\\blockbrewingstand.cpp\">\n      <Filter>Source Files\\blocks</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\inventory\\inventoryPlayer.cpp\">\n      <Filter>Source Files\\inventory</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\inventory\\inventoryChest.cpp\">\n      <Filter>Source Files\\inventory</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\inventory\\inventoryWorkbench.cpp\">\n      <Filter>Source Files\\inventory</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\inventory\\inventoryFurnace.cpp\">\n      <Filter>Source Files\\inventory</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\inventory\\inventoryBrewingstand.cpp\">\n      <Filter>Source Files\\inventory</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\inventory\\inventoryBasic.cpp\">\n      <Filter>Source Files\\inventory</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\threadpool.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"..\\src\\json.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\src\\blocks\\door.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\falling.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\fire.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\liquid.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\plant.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\sign.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\snow.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\stair.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\torch.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\worldgen\\mapgen.h\">\n      <Filter>Header Files\\worldgen</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\worldgen\\cavegen.h\">\n      <Filter>Header Files\\worldgen</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\default.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\basic.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\chest.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\tracks.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\config\\scanner.h\">\n      <Filter>Header Files\\config</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\config\\lexer.h\">\n      <Filter>Header Files\\config</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\config\\node.h\">\n      <Filter>Header Files\\config</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\config\\parser.h\">\n      <Filter>Header Files\\config</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\ladder.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\cake.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\worldgen\\heavengen.h\">\n      <Filter>Header Files\\worldgen</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\worldgen\\nethergen.h\">\n      <Filter>Header Files\\worldgen</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\note.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\workbench.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\blockfurnace.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\items\\food.h\">\n      <Filter>Header Files\\items</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\items\\itembasic.h\">\n      <Filter>Header Files\\items</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\items\\projectile.h\">\n      <Filter>Header Files\\items</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\worldgen\\biomegen.h\">\n      <Filter>Header Files\\worldgen</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\redstone.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\worldgen\\eximgen.h\">\n      <Filter>Header Files\\worldgen</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\leaves.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\pumpkin.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\bed.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\step.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\wool.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\wood.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\ice.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\tnt.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\jackolantern.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\vec.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\chat.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\chunkmap.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\cliScreen.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\config.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\constants.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\constants_num.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\furnace.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\furnaceManager.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\inventory.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\lighting.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\logger.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\logtype.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\map.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\mcregion.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\metadata.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\mineserver.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\mob.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\nbt.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\packets.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\permissions.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\physics.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\plugin.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\plugin_api.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\protocol.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\random.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\screenBase.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\sockets.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\tools.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\tree.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\user.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\utf8.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\signalhandler.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\extern.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\redstoneSimulation.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\redstoneutil.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\planks.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\blocks\\blockbrewingstand.h\">\n      <Filter>Header Files\\blocks</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\inventory\\inventorybasic.h\">\n      <Filter>Header Files\\inventory</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\inventory\\inventoryPlayer.h\">\n      <Filter>Header Files\\inventory</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\inventory\\inventoryChest.h\">\n      <Filter>Header Files\\inventory</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\inventory\\inventoryWorkbench.h\">\n      <Filter>Header Files\\inventory</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\inventory\\inventoryFurnace.h\">\n      <Filter>Header Files\\inventory</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\inventory\\inventoryBrewingstand.h\">\n      <Filter>Header Files\\inventory</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\threadpool.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"..\\src\\json.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "win32/mineserver_VS2013.sln",
    "content": "Microsoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 2013\nVisualStudioVersion = 12.0.31101.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"mineserver\", \"mineserver.vcxproj\", \"{7F6D1DAB-AA49-4343-B28E-C3E647BE5007}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"plugin_commands\", \"plugins\\plugin_commands.vcxproj\", \"{ED3F5170-79CB-4524-BF46-EBD2B5DFBBFB}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"plugin_filelog\", \"plugins\\plugin_filelog.vcxproj\", \"{675D0293-C686-4009-ACDB-5F3FC5FA03C8}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"plugin_luascript\", \"plugins\\plugin_luascript.vcxproj\", \"{67064A5E-4849-4BDB-8E15-5796B15D0E84}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"plugin_flatpermissions\", \"plugins\\plugin_flatpermissions.vcxproj\", \"{C33AEC42-DCAC-4E29-8269-3C063C929608}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"plugin_passivemobs\", \"plugins\\plugin_passivemobs.vcxproj\", \"{1D7F2766-776D-4FEF-9E69-58BB7827180A}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Win32 = Debug|Win32\n\t\tRelease|Win32 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{7F6D1DAB-AA49-4343-B28E-C3E647BE5007}.Release|Win32.Build.0 = Release|Win32\n\t\t{ED3F5170-79CB-4524-BF46-EBD2B5DFBBFB}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{ED3F5170-79CB-4524-BF46-EBD2B5DFBBFB}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{ED3F5170-79CB-4524-BF46-EBD2B5DFBBFB}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{ED3F5170-79CB-4524-BF46-EBD2B5DFBBFB}.Release|Win32.Build.0 = Release|Win32\n\t\t{675D0293-C686-4009-ACDB-5F3FC5FA03C8}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{675D0293-C686-4009-ACDB-5F3FC5FA03C8}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{675D0293-C686-4009-ACDB-5F3FC5FA03C8}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{675D0293-C686-4009-ACDB-5F3FC5FA03C8}.Release|Win32.Build.0 = Release|Win32\n\t\t{67064A5E-4849-4BDB-8E15-5796B15D0E84}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{67064A5E-4849-4BDB-8E15-5796B15D0E84}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{67064A5E-4849-4BDB-8E15-5796B15D0E84}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{67064A5E-4849-4BDB-8E15-5796B15D0E84}.Release|Win32.Build.0 = Release|Win32\n\t\t{C33AEC42-DCAC-4E29-8269-3C063C929608}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{C33AEC42-DCAC-4E29-8269-3C063C929608}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{C33AEC42-DCAC-4E29-8269-3C063C929608}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{C33AEC42-DCAC-4E29-8269-3C063C929608}.Release|Win32.Build.0 = Release|Win32\n\t\t{1D7F2766-776D-4FEF-9E69-58BB7827180A}.Debug|Win32.ActiveCfg = Debug|Win32\n\t\t{1D7F2766-776D-4FEF-9E69-58BB7827180A}.Debug|Win32.Build.0 = Debug|Win32\n\t\t{1D7F2766-776D-4FEF-9E69-58BB7827180A}.Release|Win32.ActiveCfg = Release|Win32\n\t\t{1D7F2766-776D-4FEF-9E69-58BB7827180A}.Release|Win32.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "win32/plugins/plugin_commands.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{ED3F5170-79CB-4524-BF46-EBD2B5DFBBFB}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>plugin_commands</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>commands</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>commands</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_COMMANDS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_COMMANDS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\plugins\\commands\\commands.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "win32/plugins/plugin_filelog.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>plugin_commands</RootNamespace>\n    <ProjectGuid>{675D0293-C686-4009-ACDB-5F3FC5FA03C8}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>filelog</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>filelog</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_COMMANDS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_COMMANDS_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <OutputFile>\n      </OutputFile>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\plugins\\filelog\\filelog.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "win32/plugins/plugin_flatpermissions.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>plugin_flatpermissions</RootNamespace>\n    <ProjectGuid>{C33AEC42-DCAC-4E29-8269-3C063C929608}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>NotSet</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>flatpermissions</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>flatpermissions</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_flatpermissions_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_flatpermissions_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\plugins\\flatpermissions\\flatpermissions.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "win32/plugins/plugin_luascript.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>plugin_luascript</RootNamespace>\n    <ProjectGuid>{67064A5E-4849-4BDB-8E15-5796B15D0E84}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>luascript</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>luascript</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_luascript_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <AdditionalDependencies>lua5.1.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_luascript_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <AdditionalDependencies>lua5.1.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\plugins\\luascript\\luascript.cpp\" />\n    <ClCompile Include=\"..\\..\\plugins\\luascript\\luawrapper.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"..\\..\\plugins\\luascript\\luawrapper.h\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "win32/plugins/plugin_passivemobs.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"12.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{1D7F2766-776D-4FEF-9E69-58BB7827180A}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>plugin_passivemobs</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n    <PlatformToolset>v120</PlatformToolset>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>passivemobs</TargetName>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <IncludePath>$(IncludePath)</IncludePath>\n    <OutDir>../../bin/plugins/</OutDir>\n    <TargetName>passivemobs</TargetName>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_passivemobs_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <PrecompiledHeader>\n      </PrecompiledHeader>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_passivemobs_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalIncludeDirectories>../../include;../../src</AdditionalIncludeDirectories>\n      <AdditionalOptions>/FS %(AdditionalOptions)</AdditionalOptions>\n    </ClCompile>\n    <Link>\n      <SubSystem>Windows</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"..\\..\\plugins\\passivemobs\\passivemobs.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  }
]