Merge remote-tracking branch 'origin/master' into issue850
Conflicts: src/Blocks/BlockLeaves.h src/Generating/Trees.cpp
4
.gitignore
vendored
@ -15,6 +15,7 @@ cloc.xsl
|
||||
*.suo
|
||||
/EveryNight.cmd
|
||||
/UploadLuaAPI.cmd
|
||||
AllFiles.lst
|
||||
|
||||
# IDE Stuff
|
||||
## Sublime Text
|
||||
@ -26,6 +27,7 @@ cloc.xsl
|
||||
## Eclipse
|
||||
.cproject
|
||||
.project
|
||||
*.cbp
|
||||
|
||||
# world inside source
|
||||
ChunkWorx.ini
|
||||
@ -48,6 +50,7 @@ world_nether
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
CTestTestfile.cmake
|
||||
Makefile
|
||||
|
||||
*.a
|
||||
@ -63,6 +66,7 @@ lib/tolua++/tolua
|
||||
src/Bindings/Bindings.*
|
||||
src/Bindings/BindingDependecies.txt
|
||||
MCServer.dir/
|
||||
src/AllFiles.lst
|
||||
|
||||
#win32 cmake stuff
|
||||
*.vcxproj
|
||||
|
2
.gitmodules
vendored
@ -9,4 +9,4 @@
|
||||
url = https://github.com/bearbin/transapi.git
|
||||
[submodule "lib/polarssl"]
|
||||
path = lib/polarssl
|
||||
url = https://github.com/polarssl/polarssl
|
||||
url = https://github.com/mc-server/polarssl
|
||||
|
14
.travis.yml
@ -2,8 +2,15 @@ language: cpp
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_MCSERVER_BUILD_TYPE" == "COVERAGE" ]; then sudo pip install cpp_coveralls; fi
|
||||
|
||||
# Build MCServer
|
||||
script: cmake . -DBUILD_TOOLS=1 -DSELF_TEST=1 && make -j 2 && cd MCServer/ && (echo stop | $MCSERVER_PATH)
|
||||
script: ./CIbuild.sh
|
||||
|
||||
after_success:
|
||||
- ./uploadCoverage.sh
|
||||
|
||||
env:
|
||||
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE MCSERVER_PATH=./MCServer
|
||||
@ -11,6 +18,11 @@ env:
|
||||
- TRAVIS_MCSERVER_BUILD_TYPE=RELEASE TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer
|
||||
- TRAVIS_MCSERVER_BUILD_TYPE=DEBUG TRAVIS_MCSERVER_FORCE32=1 MCSERVER_PATH=./MCServer_debug
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: TRAVIS_MCSERVER_BUILD_TYPE=COVERAGE MCSERVER_PATH=./MCServer
|
||||
|
||||
# Notification Settings
|
||||
notifications:
|
||||
email:
|
||||
|
11
CIbuild.sh
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
cmake . -DBUILD_TOOLS=1 -DSELF_TEST=1;
|
||||
make -j 2;
|
||||
make -j 2 test;
|
||||
cd MCServer/;
|
||||
if [ "$TRAVIS_MCSERVER_BUILD_TYPE" != "COVERAGE" ]
|
||||
then echo stop | $MCSERVER_PATH;
|
||||
fi
|
@ -1,4 +1,4 @@
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
cmake_minimum_required (VERSION 2.8.2)
|
||||
|
||||
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
|
||||
enable_language(CXX C)
|
||||
@ -14,6 +14,10 @@ if(DEFINED ENV{TRAVIS_MCSERVER_FORCE32})
|
||||
set(FORCE32 $ENV{TRAVIS_MCSERVER_FORCE32})
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{TRAVIS_BUILD_WITH_COVERAGE})
|
||||
set(BUILD_WITH_COVERAGE $ENV{TRAVIS_BUILD_WITH_COVERAGE})
|
||||
endif()
|
||||
|
||||
# This has to be done before any flags have been set up.
|
||||
if(${BUILD_TOOLS})
|
||||
add_subdirectory(Tools/MCADefrag/)
|
||||
@ -58,7 +62,10 @@ add_subdirectory(lib/tolua++/)
|
||||
add_subdirectory(lib/sqlite/)
|
||||
add_subdirectory(lib/expat/)
|
||||
add_subdirectory(lib/luaexpat/)
|
||||
add_subdirectory(lib/md5/)
|
||||
|
||||
if (WIN32)
|
||||
add_subdirectory(lib/luaproxy/)
|
||||
endif()
|
||||
|
||||
|
||||
# We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used
|
||||
@ -69,3 +76,8 @@ set_exe_flags()
|
||||
|
||||
add_subdirectory (src)
|
||||
|
||||
if(${SELF_TEST})
|
||||
enable_testing()
|
||||
add_subdirectory (tests)
|
||||
endif()
|
||||
|
||||
|
41
COMPILING.md
@ -45,7 +45,30 @@ It is possible to use an external profiler to learn more about how the code perf
|
||||
|
||||
There's a script file, `MCServer/profile_run.cmd` that encapsulates most of the profiling work, have a look at the comments at the top of that script for details on how to get it to work. You'll need to change to a profiled configuration (both debug and release can be profiled).
|
||||
|
||||
## Linux, MacOS, FreeBSD etc. ##
|
||||
## OSX ##
|
||||
Install git from its [website](http://git-scm.com) or homebrew: `brew install git`.
|
||||
|
||||
Install Xcode (commandline tools are recommended) from the App Store or https://developer.apple.com/downloads.
|
||||
|
||||
Install CMake from its [website](http://cmake.org) or homebrew: `brew install cmake`.
|
||||
|
||||
### Getting the sources ###
|
||||
```
|
||||
mkdir MCServer
|
||||
cd MCServer
|
||||
git clone https://github.com/mc-server/MCServer.git .
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
### Building ###
|
||||
|
||||
Follow the instructions at [CMake on Unix-based platforms](#cmake-on-unix-based-platforms), using Xcode as cmake's generator. If no generator is specified, CMake will use the Makefile generator, in which case you must build with the `make` command.
|
||||
|
||||
After doing so, run the command `xcodebuild lib/polarssl/POLARSSL.xcodeproj` in the build directory, in order to build polarssl, a library that is required by MCServer. Lastly, run the command `xcodebuild` to build MCServer. Optionally, you may open the project files for polarssl and then MCServer in Xcode and build there.
|
||||
|
||||
|
||||
## Linux, FreeBSD etc. ##
|
||||
|
||||
Install git, cmake and gcc or clang, using your platform's package manager:
|
||||
```
|
||||
@ -61,6 +84,14 @@ git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
### Building ###
|
||||
|
||||
Follow the instructions at [CMake on Unix-based platforms](#cmake-on-unix-based-platforms).
|
||||
|
||||
After doing so, run the command `make` in the build directory, and MCServer will build.
|
||||
|
||||
## CMake on Unix-based platforms ###
|
||||
|
||||
### Release Mode ###
|
||||
|
||||
Release mode is preferred for almost all cases, it has much better speed and less console spam. However, if you are developing MCServer actively, debug mode might be better.
|
||||
@ -69,8 +100,10 @@ Assuming you are in the MCServer folder created in the initial setup step, you n
|
||||
```
|
||||
mkdir Release
|
||||
cd Release
|
||||
cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make
|
||||
cmake -DCMAKE_BUILD_TYPE=RELEASE ..
|
||||
```
|
||||
NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive.
|
||||
|
||||
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`.
|
||||
|
||||
### Debug Mode ###
|
||||
@ -81,8 +114,10 @@ Assuming you are in the MCServer folder created in the Getting the sources step,
|
||||
```
|
||||
mkdir Debug
|
||||
cd Debug
|
||||
cmake -DCMAKE_BUILD_TYPE=DEBUG .. && make
|
||||
cmake -DCMAKE_BUILD_TYPE=DEBUG ..
|
||||
```
|
||||
NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive.
|
||||
|
||||
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`.
|
||||
|
||||
### 32 Bit Mode switch ###
|
||||
|
@ -27,7 +27,7 @@ Code Stuff
|
||||
- The only exception: a `switch` statement with all `case` statements being a single short statement is allowed to use the short brace-less form.
|
||||
- These two rules really mean that indent is governed by braces
|
||||
* Add an empty last line in all source files (GCC and GIT can complain otherwise)
|
||||
* Use doxy-comments for functions in the header file, format as `/** Description */`
|
||||
* All new public functions in all classes need documenting comments on what they do and what behavior they follow, use doxy-comments formatted as `/** Description */`. Do not use asterisks on additional lines in multi-line comments.
|
||||
* Use spaces after the comment markers: `// Comment` instead of `//Comment`
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
Many people have contributed to MCServer, and this list attempts to broadcast at least some of them.
|
||||
|
||||
BasedDoge (Donated AlchemistVillage prefabs)
|
||||
bearbin (Alexander Harkness)
|
||||
derouinw
|
||||
Diusrex
|
||||
@ -26,6 +27,7 @@ tonibm19
|
||||
UltraCoderRU
|
||||
worktycho
|
||||
xoft
|
||||
|
||||
Yeeeeezus (Donated AlchemistVillage prefabs)
|
||||
Howaner
|
||||
|
||||
Please add yourself to this list if you contribute to MCServer.
|
||||
|
@ -3,14 +3,14 @@ Hello! Thanks for wanting to work on this project :smile:, and I hope that this
|
||||
Minecraft Basics
|
||||
----------------
|
||||
|
||||
If you don't play Minecraft or don't have a great knowledge of the basic systems, you should get to know them. The [Minecraft Wiki](http://minecraft.gamepedia.com/Minecraft_Wiki) is quite useful for this task, although some youtubers are also fairly good at teaching the basics and just playing is quite good too.
|
||||
If you don't play Minecraft or don't have a great knowledge of the basic systems, you should get to know them. The [Minecraft Wiki](http://minecraft.gamepedia.com/Minecraft_Wiki) is quite useful for this task, although some youtubers are also fairly good at teaching the basics and just playing is quite good too. It is possible to contribute without knowing minecraft in detail though.
|
||||
|
||||
I'd say that the important topics are:
|
||||
|
||||
* Differnt types of blocks and how they act.
|
||||
* Mobs, what they do and how.
|
||||
* Redstone, pistons, and automation.
|
||||
* Farming
|
||||
* Farming.
|
||||
* Fighting, health and the hunger system.
|
||||
|
||||
Useful Resources
|
||||
@ -39,7 +39,7 @@ You'll also need CMake to generate the makefile to build from.
|
||||
|
||||
**Windows:**
|
||||
|
||||
If you use Windows, your best bet is the MSVC2008 (available as a free download in the Express edition from MS) or MSVS2013 (ditto), solution files for both are currently in the repo.
|
||||
If you use Windows, your best bet is the MSVC2008 (available as a free download in the Express edition from MS) or MSVS2013 (ditto), solution files for which can be generated with cmake. You'll also need cmake to generate the project files.
|
||||
|
||||
Setting up the Repo
|
||||
-------------------
|
||||
@ -85,7 +85,7 @@ Basically, the process is:
|
||||
|
||||
**Windows:**
|
||||
|
||||
You need to first execute the `src/Bindings/AllToLua.bat` script file, then just open the solution file in your MSVC of choice and build.
|
||||
You need to first generate a project file with `cmake . -DCMAKE_BUILD_TYPE=DEBUG` then execute the `src/Bindings/AllToLua.bat` script file, then just open the solution file in your MSVC of choice and build.
|
||||
|
||||
How to Run
|
||||
----------
|
||||
@ -99,18 +99,18 @@ There are a few fairly easy issues for you to get started with, as well as some
|
||||
|
||||
**Easy**:
|
||||
|
||||
* #288
|
||||
* #385
|
||||
* #402
|
||||
* #380
|
||||
* #503
|
||||
* #491
|
||||
* #140
|
||||
* #493
|
||||
* #577
|
||||
* #381
|
||||
* #752
|
||||
* Clean up some of the compiler warnings. (Check [Travis CI](http://travis-ci.org/mc-server/MCServer) for a list of them.) With clang, there are over 10000 lines of warnings to clean up.
|
||||
|
||||
**More Difficult**:
|
||||
|
||||
* #17
|
||||
* #398
|
||||
* #133
|
||||
* #134
|
||||
* #215
|
||||
|
||||
You may also want to write some plugins. They are written in lua, with excellent API documentation available via [APIDump](http://mc-server.xoft.cz/LuaAPI). The [Core](https://github.com/mc-server/Core) plugin should also help quite a bit here.
|
||||
|
||||
|
4
MCServer/.gitignore
vendored
@ -30,3 +30,7 @@ motd.txt
|
||||
*.xml
|
||||
mcserver_api.lua
|
||||
|
||||
# Ignore the webadmin certs / privkey, so that no-one commits theirs by accident:
|
||||
webadmin/httpscert.crt
|
||||
webadmin/httpskey.pem
|
||||
|
||||
|
@ -114,6 +114,7 @@ g_APIDesc =
|
||||
GetBlockSkyLight = { Params = "BlockX, BlockY, BlockZ", Return = "NIBBLETYPE", Notes = "Returns the skylight at the specified absolute coords" },
|
||||
GetBlockType = { Params = "BlockX, BlockY, BlockZ", Return = "BLOCKTYPE", Notes = "Returns the block type at the specified absolute coords" },
|
||||
GetBlockTypeMeta = { Params = "BlockX, BlockY, BlockZ", Return = "BLOCKTYPE, NIBBLETYPE", Notes = "Returns the block type and meta at the specified absolute coords" },
|
||||
GetCoordRange = {Params = "", Return = "MaxX, MaxY, MaxZ", Notes = "Returns the maximum relative coords in all 3 axes. See also GetSize()." },
|
||||
GetDataTypes = { Params = "", Return = "number", Notes = "Returns the mask of datatypes that the object is currently holding" },
|
||||
GetOrigin = { Params = "", Return = "OriginX, OriginY, OriginZ", Notes = "Returns the origin coords of where the area was read from." },
|
||||
GetOriginX = { Params = "", Return = "number", Notes = "Returns the origin x-coord" },
|
||||
@ -124,7 +125,7 @@ g_APIDesc =
|
||||
GetRelBlockSkyLight = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "NIBBLETYPE", Notes = "Returns the skylight at the specified relative coords" },
|
||||
GetRelBlockType = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "BLOCKTYPE", Notes = "Returns the block type at the specified relative coords" },
|
||||
GetRelBlockTypeMeta = { Params = "RelBlockX, RelBlockY, RelBlockZ", Return = "BLOCKTYPE, NIBBLETYPE", Notes = "Returns the block type and meta at the specified relative coords" },
|
||||
GetSize = { Params = "", Return = "SizeX, SizeY, SizeZ", Notes = "Returns the size of the area in all 3 axes." },
|
||||
GetSize = { Params = "", Return = "SizeX, SizeY, SizeZ", Notes = "Returns the size of the area in all 3 axes. See also GetCoordRange()." },
|
||||
GetSizeX = { Params = "", Return = "number", Notes = "Returns the size of the held data in the x-axis" },
|
||||
GetSizeY = { Params = "", Return = "number", Notes = "Returns the size of the held data in the y-axis" },
|
||||
GetSizeZ = { Params = "", Return = "number", Notes = "Returns the size of the held data in the z-axis" },
|
||||
@ -522,13 +523,16 @@ end
|
||||
|
||||
Functions =
|
||||
{
|
||||
GenerateOfflineUUID = { Params = "Username", Return = "string", Notes = "(STATIC) Generates an UUID based on the player name provided. This is used for the offline (non-auth) mode, when there's no UUID source. Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same. Returns a 36-char UUID (with dashes)." },
|
||||
GetLocale = { Params = "", Return = "Locale", Notes = "Returns the locale string that the client sends as part of the protocol handshake. Can be used to provide localized strings." },
|
||||
GetPing = { Params = "", Return = "number", Notes = "Returns the ping time, in ms" },
|
||||
GetPlayer = { Params = "", Return = "{{cPlayer|cPlayer}}", Notes = "Returns the player object connected to this client. Note that this may be nil, for example if the player object is not yet spawned." },
|
||||
GetUniqueID = { Params = "", Return = "number", Notes = "Returns the UniqueID of the client used to identify the client in the server" },
|
||||
GetUUID = { Params = "", Return = "string", Notes = "Returns the authentication-based UUID of the client. This UUID should be used to identify the player when persisting any player-related data." },
|
||||
GetUsername = { Params = "", Return = "string", Notes = "Returns the username that the client has provided" },
|
||||
GetViewDistance = { Params = "", Return = "number", Notes = "Returns the viewdistance (number of chunks loaded for the player in each direction)" },
|
||||
HasPluginChannel = { Params = "ChannelName", Return = "bool", Notes = "Returns true if the client has registered to receive messages on the specified plugin channel." },
|
||||
IsUUIDOnline = { Params = "UUID", Return = "bool", Notes = "(STATIC) Returns true if the UUID is generated by online auth, false if it is an offline-generated UUID. We use Version-3 UUIDs for offline UUIDs, online UUIDs are Version-4, thus we can tell them apart. Accepts both 32-char and 36-char UUIDs (with and without dashes). If the string given is not a valid UUID, returns false."},
|
||||
Kick = { Params = "Reason", Return = "", Notes = "Kicks the user with the specified reason" },
|
||||
SendPluginMessage = { Params = "Channel, Message", Return = "", Notes = "Sends the plugin message on the specified channel." },
|
||||
SetLocale = { Params = "Locale", Return = "", Notes = "Sets the locale that MCServer keeps on record. Initially the locale is initialized in protocol handshake, this function allows plugins to override the stored value (but only server-side and only until the user disconnects)." },
|
||||
@ -1151,6 +1155,7 @@ These ItemGrids are available in the API and can be manipulated by the plugins,
|
||||
HasItems = { Params = "{{cItem|cItem}}", Return = "bool", Notes = "Returns true if there are at least as many items of the specified type as in the parameter" },
|
||||
HowManyCanFit = { Params = "{{cItem|cItem}}", Return = "number", Notes = "Returns the number of the specified items that can fit in the storage, including empty slots" },
|
||||
HowManyItems = { Params = "{{cItem|cItem}}", Return = "number", Notes = "Returns the number of the specified items that are currently stored" },
|
||||
RemoveItem = { Params = "{{cItem}}", Return = "number", Notes = "Removes the specified item from the inventory, as many as possible, up to the item's m_ItemCount. Returns the number of items that were removed." },
|
||||
RemoveOneEquippedItem = { Params = "", Return = "", Notes = "Removes one item from the hotbar's currently selected slot" },
|
||||
SetArmorSlot = { Params = "ArmorSlotNum, {{cItem|cItem}}", Return = "", Notes = "Sets the specified armor slot contents" },
|
||||
SetEquippedSlotNum = { Params = "EquippedSlotNum", Return = "", Notes = "Sets the currently selected hotbar slot number" },
|
||||
@ -1380,6 +1385,7 @@ local Item5 = cItem(E_ITEM_DIAMOND_CHESTPLATE, 1, 0, "thorns=1;unbreaking=3");
|
||||
{ Params = "SlotNum", Return = "bool", Notes = "Returns true if the specified slot is empty, or an invalid slot is specified" },
|
||||
{ Params = "X, Y", Return = "bool", Notes = "Returns true if the specified slot is empty, or an invalid slot is specified" },
|
||||
},
|
||||
RemoveItem = { Params = "{{cItem}}", Return = "number", Notes = "Removes the specified item from the grid, as many as possible, up to the item's m_ItemCount. Returns the number of items that were removed." },
|
||||
RemoveOneItem =
|
||||
{
|
||||
{ Params = "SlotNum", Return = "{{cItem|cItem}}", Notes = "Removes one item from the stack in the specified slot and returns it as a single cItem. Empty slots are skipped and an empty item is returned" },
|
||||
@ -1687,6 +1693,9 @@ a_Player:OpenWindow(Window);
|
||||
TakeDamage = { Return = "" },
|
||||
KilledBy = { Return = "" },
|
||||
GetHealth = { Return = "number" },
|
||||
AddEntityEffect = { Params = "EffectType, {{cEntityEffect}}", Return = "", Notes = "Applies an entity effect" },
|
||||
RemoveEntityEffect = { Params = "EffectType", Return = "", Notes = "Removes a currently applied entity effect" },
|
||||
ClearEntityEffects = { Return = "", Notes = "Removes all currently applied entity effects" },
|
||||
},
|
||||
Inherits = "cEntity",
|
||||
}, -- cPawn
|
||||
@ -1871,9 +1880,9 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
|
||||
},
|
||||
CallPlugin = { Params = "PluginName, FunctionName, [FunctionArgs...]", Return = "[FunctionRets]", Notes = "(STATIC) Calls the specified function in the specified plugin, passing all the given arguments to it. If it succeeds, it returns all the values returned by that function. If it fails, returns no value at all. Note that only strings, numbers, bools, nils and classes can be used for parameters and return values; tables and functions cannot be copied across plugins." },
|
||||
DisablePlugin = { Params = "PluginName", Return = "bool", Notes = "Disables a plugin specified by its name. Returns true if the plugin was disabled, false if it wasn't found or wasn't active." },
|
||||
ExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "bool", Notes = "Executes the command as if given by the specified Player. Checks permissions. Returns true if executed." },
|
||||
ExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Executes the command as if given by the specified Player. Checks permissions." },
|
||||
FindPlugins = { Params = "", Return = "", Notes = "Refreshes the list of plugins to include all folders inside the Plugins folder (potentially new disabled plugins)" },
|
||||
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "bool", Notes = "Same as ExecuteCommand, but doesn't check permissions" },
|
||||
ForceExecuteCommand = { Params = "{{cPlayer|Player}}, CommandStr", Return = "{{cPluginManager#CommandResult|CommandResult}}", Notes = "Same as ExecuteCommand, but doesn't check permissions" },
|
||||
ForEachCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function(Command, Permission, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
||||
ForEachConsoleCommand = { Params = "CallbackFn", Return = "bool", Notes = "Calls the CallbackFn function for each command that has been bound using BindConsoleCommand(). The CallbackFn has the following signature: <pre class=\"prettyprint lang-lua\">function (Command, HelpString)</pre>. If the callback returns true, the enumeration is aborted and this API function returns false; if it returns false or no value, the enumeration continues with the next command, and the API function returns true." },
|
||||
Get = { Params = "", Return = "cPluginManager", Notes = "(STATIC) Returns the single instance of the plugin manager" },
|
||||
@ -1889,8 +1898,23 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
|
||||
LogStackTrace = { Params = "", Return = "", Notes = "(STATIC) Logs a current stack trace of the Lua engine to the server console log. Same format as is used when the plugin fails." },
|
||||
ReloadPlugins = { Params = "", Return = "", Notes = "Reloads all active plugins" },
|
||||
},
|
||||
ConstantGroups=
|
||||
{
|
||||
CommandResult =
|
||||
{
|
||||
Include = "^cr.*",
|
||||
TextBefore = [[
|
||||
Results that the (Force)ExecuteCommand return. This gives information if the command is executed or not and the reason.
|
||||
]],
|
||||
},
|
||||
},
|
||||
Constants =
|
||||
{
|
||||
crBlocked = { Notes = "When a plugin stopped the command using the OnExecuteCommand hook" },
|
||||
crError = { Notes = "When the command handler for the given command results in an error" },
|
||||
crExecuted = { Notes = "When the command is successfully executed." },
|
||||
crNoPermission = { Notes = "When the player doesn't have permission to execute the given command." },
|
||||
crUnknownCommand = { Notes = "When the given command doesn't exist." },
|
||||
HOOK_BLOCK_SPREAD = { Notes = "Called when a block spreads based on world conditions" },
|
||||
HOOK_BLOCK_TO_PICKUPS = { Notes = "Called when a block has been dug and is being converted to pickups. The server has provided the default pickups and the plugins may modify them." },
|
||||
HOOK_CHAT = { Notes = "Called when a client sends a chat message that is not a command. The plugin may modify the chat message" },
|
||||
@ -1969,7 +1993,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
|
||||
BroadcastChatSuccess = { Params = "Message", Return = "", Notes = "Prepends Green [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For success messages." },
|
||||
BroadcastChatWarning = { Params = "Message", Return = "", Notes = "Prepends Rose [WARN] / colours entire text (depending on ShouldUseChatPrefixes()) and broadcasts message. For concerning events, such as plugin reload etc." },
|
||||
CreateAndInitializeWorld = { Params = "WorldName", Return = "{{cWorld|cWorld}}", Notes = "Creates a new world and initializes it. If there is a world whith the same name it returns nil." },
|
||||
FindAndDoWithPlayer = { Params = "PlayerName, CallbackFunction", Return = "", Notes = "Calls the given callback function for the given player." },
|
||||
FindAndDoWithPlayer = { Params = "PlayerName, CallbackFunction", Return = "", Notes = "Calls the given callback function for all players with names partially (or fully) matching the name string provided." },
|
||||
ForEachPlayer = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each player. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|cPlayer}})</pre>" },
|
||||
ForEachWorld = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each world. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cWorld|cWorld}})</pre>" },
|
||||
GetCraftingRecipes = { Params = "", Return = "{{cCraftingRecipe|cCraftingRecipe}}", Notes = "Returns the CraftingRecipes object" },
|
||||
@ -2294,10 +2318,14 @@ end
|
||||
IsGameModeCreative = { Params = "", Return = "bool", Notes = "Returns true if the current gamemode is gmCreative." },
|
||||
IsGameModeSurvival = { Params = "", Return = "bool", Notes = "Returns true if the current gamemode is gmSurvival." },
|
||||
IsPVPEnabled = { Params = "", Return = "bool", Notes = "Returns whether PVP is enabled in the world settings." },
|
||||
IsWeatherRain = { Params = "", Return = "bool", Notes = "Returns true if the current weather is rain." },
|
||||
IsWeatherStorm = { Params = "", Return = "bool", Notes = "Returns true if the current weather is a storm." },
|
||||
IsWeatherRain = { Params = "", Return = "bool", Notes = "Returns true if the current world is raining." },
|
||||
IsWeatherRainAt = { Params = "BlockX, BlockZ", Return = "bool", Notes = "Returns true if the specified location is raining (takes into account biomes)." },
|
||||
IsWeatherStorm = { Params = "", Return = "bool", Notes = "Returns true if the current world is stormy." },
|
||||
IsWeatherStormAt = { Params = "BlockX, BlockZ", Return = "bool", Notes = "Returns true if the specified location is stormy (takes into account biomes)." },
|
||||
IsWeatherSunny = { Params = "", Return = "bool", Notes = "Returns true if the current weather is sunny." },
|
||||
IsWeatherWet = { Params = "", Return = "bool", Notes = "Returns true if the current weather has any precipitation (rain or storm)." },
|
||||
IsWeatherSunnyAt = { Params = "BlockX, BlockZ", Return = "bool", Notes = "Returns true if the current weather is sunny at the specified location (takes into account biomes)." },
|
||||
IsWeatherWet = { Params = "", Return = "bool", Notes = "Returns true if the current world has any precipitation (rain or storm)." },
|
||||
IsWeatherWetAt = { Params = "BlockX, BlockZ", Return = "bool", Notes = "Returns true if the specified location has any precipitation (rain or storm) (takes into account biomes)." },
|
||||
QueueBlockForTick = { Params = "BlockX, BlockY, BlockZ, TicksToWait", Return = "", Notes = "Queues the specified block to be ticked after the specified number of gameticks." },
|
||||
QueueSaveAllChunks = { Params = "", Return = "", Notes = "Queues all chunks to be saved in the world storage thread" },
|
||||
QueueSetBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta, TickDelay", Return = "", Notes = "Queues the block to be set to the specified blocktype and meta after the specified amount of game ticks. Uses SetBlock() for the actual setting, so simulators are woken up and block entities are handled correctly." },
|
||||
@ -2317,6 +2345,7 @@ end
|
||||
{ Params = "BlockX, BlockY, BlockZ, BlockMeta", Return = "", Notes = "Sets the meta for the block at the specified coords." },
|
||||
{ Params = "{{Vector3i|BlockCoords}}, BlockMeta", Return = "", Notes = "Sets the meta for the block at the specified coords." },
|
||||
},
|
||||
SetChunkAlwaysTicked = { Params = "ChunkX, ChunkZ, IsAlwaysTicked", Return = "", Notes = "Sets the chunk to always be ticked even when it doesn't contain any clients. IsAlwaysTicked set to true turns forced ticking on, set to false turns it off. Every call with 'true' should be paired with a later call with 'false', otherwise the ticking won't stop. Multiple actions can request ticking independently, the ticking will continue until the last call with 'false'. Note that when the chunk unloads, it loses the value of this flag." },
|
||||
SetNextBlockTick = { Params = "BlockX, BlockY, BlockZ", Return = "", Notes = "Sets the blockticking to start at the specified block in the next tick." },
|
||||
SetCommandBlockCommand = { Params = "BlockX, BlockY, BlockZ, Command", Return = "bool", Notes = "Sets the command to be executed in a command block at the specified coordinates. Returns if command was changed." },
|
||||
SetCommandBlocksEnabled = { Params = "IsEnabled (bool)", Return = "", Notes = "Sets whether command blocks should be enabled on the (entire) server." },
|
||||
@ -2929,6 +2958,7 @@ end
|
||||
{
|
||||
-- No sorting is provided for these, they will be output in the same order as defined here
|
||||
{ FileName = "Writing-a-MCServer-plugin.html", Title = "Writing a MCServer plugin" },
|
||||
{ FileName = "InfoFile.html", Title = "Using the Info.lua file" },
|
||||
{ FileName = "SettingUpDecoda.html", Title = "Setting up the Decoda Lua IDE" },
|
||||
{ FileName = "SettingUpZeroBrane.html", Title = "Setting up the ZeroBrane Studio Lua IDE" },
|
||||
{ FileName = "UsingChunkStays.html", Title = "Using ChunkStays" },
|
||||
|
@ -2,23 +2,33 @@ return
|
||||
{
|
||||
HOOK_DISCONNECT =
|
||||
{
|
||||
CalledWhen = "A player has explicitly disconnected.",
|
||||
CalledWhen = [[
|
||||
A client has disconnected, either by explicitly sending the disconnect packet (in older protocols) or
|
||||
their connection was terminated
|
||||
]],
|
||||
DefaultFnName = "OnDisconnect", -- also used as pagename
|
||||
Desc = [[
|
||||
This hook is called when a client is about to be disconnected from the server, for whatever reason.
|
||||
|
||||
<p><b>Note that this hook will be removed after <1.7 protocol support is removed, as it was originally a hook for
|
||||
the client sending the server a disconnect packet, which no longer happens.</b></p>
|
||||
This hook is called when a client has disconnected from the server, for whatever reason. It is also
|
||||
called when the client sends the Disconnect packet (only in pre-1.7 protocols). This hook is not called
|
||||
for server ping connections.</p>
|
||||
<p>
|
||||
Note that the hook is called even for connections to players who failed to auth. In such a case there's
|
||||
no {{cPlayer}} object associated with the client.</p>
|
||||
<p>
|
||||
See also the {{OnHandshake|HOOK_HANDSHAKE}} hook which is called when the client connects (and presents
|
||||
a handshake message, so that they are not just status-pinging). If you need to store a per-player
|
||||
object, use the {{OnPlayerJoined|HOOK_PLAYER_JOINED}} and {{OnPlayerDestroyed|HOOK_PLAYER_DESTROYED}}
|
||||
hooks instead, those are guaranteed to have the {{cPlayer}} object associated.
|
||||
]],
|
||||
Params =
|
||||
{
|
||||
{ Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has disconnected" },
|
||||
{ Name = "Client", Type = "{{cClientHandle}}", Notes = "The client who has disconnected" },
|
||||
{ Name = "Reason", Type = "string", Notes = "The reason that the client has sent in the disconnect packet" },
|
||||
},
|
||||
Returns = [[
|
||||
If the function returns false or no value, MCServer calls other plugins' callbacks for this event.
|
||||
If the function returns true, no other plugins are called for this event. In either case,
|
||||
the player is disconnected.
|
||||
the client is disconnected.
|
||||
]],
|
||||
}, -- HOOK_DISCONNECT
|
||||
}
|
||||
|
33
MCServer/Plugins/APIDump/Hooks/OnEntityAddEffect.lua
Normal file
@ -0,0 +1,33 @@
|
||||
return
|
||||
{
|
||||
HOOK_ENTITY_ADD_EFFECT =
|
||||
{
|
||||
CalledWhen = "An entity effect is about to get added to an entity.",
|
||||
DefaultFnName = "OnEntityAddEffect", -- also used as pagename
|
||||
Desc = [[
|
||||
This hook is called whenever an entity effect is about to be added to an entity. The plugin may
|
||||
disallow the addition by returning true.</p>
|
||||
<p>Note that this hook only fires for adding the effect, but not for the actual effect application. See
|
||||
also the {{OnEntityRemoveEffect|HOOK_ENTITY_REMOVE_EFFECT}} for notification about effects expiring /
|
||||
removing, and {{OnEntityApplyEffect|HOOK_ENTITY_APPLY_EFFECT}} for the actual effect application to the
|
||||
entity.
|
||||
]],
|
||||
Params =
|
||||
{
|
||||
{ Name = "Entity", Type = "{{cEntity}}", Notes = "The entity to which the effect is about to be added" },
|
||||
{ Name = "EffectType", Type = "number", Notes = "The type of the effect to be added. One of the effXXX constants." },
|
||||
{ Name = "EffectDuration", Type = "number", Notes = "The duration of the effect to be added, in ticks." },
|
||||
{ Name = "EffectIntensity", Type = "number", Notes = "The intensity (level) of the effect to be added. " },
|
||||
{ Name = "DistanceModifier", Type = "number", Notes = "The modifier for the effect intensity, based on distance. Used mainly for splash potions." },
|
||||
},
|
||||
Returns = [[
|
||||
If the plugin returns true, the effect will not be added and none of the remaining hook handlers will
|
||||
be called. If the plugin returns false, MCServer calls all the remaining hook handlers and finally
|
||||
the effect is added to the entity.
|
||||
]],
|
||||
}, -- HOOK_EXECUTE_COMMAND
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
27
MCServer/Plugins/APIDump/Hooks/OnPlayerFoodLevelChange.lua
Normal file
@ -0,0 +1,27 @@
|
||||
return
|
||||
{
|
||||
HOOK_PLAYER_FOOD_LEVEL_CHANGE =
|
||||
{
|
||||
CalledWhen = "Called before the player food level changed. Plugin may override",
|
||||
DefaultFnName = "OnPlayerFoodLevelChange", -- also used as pagename
|
||||
Desc = [[
|
||||
This hook is called before the food level changes.
|
||||
The food level is not changed yet, plugins may choose
|
||||
to refuse the change.
|
||||
]],
|
||||
Params =
|
||||
{
|
||||
{ Name = "Player", Type = "{{cPlayer}}", Notes = "The player who changes the food level." },
|
||||
{ Name = "NewFoodLevel", Type = "number", Notes = "The new food level." },
|
||||
},
|
||||
Returns = [[
|
||||
If the function returns false or no value, the next plugin's callback is called. Afterwards, the
|
||||
server changes the food level of the player. If the function returns true, no
|
||||
other callback is called for this event and the player's food level doesn't change.
|
||||
]],
|
||||
}, -- HOOK_PLAYER_FOOD_LEVEL_CHANGE
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@ return
|
||||
{
|
||||
HOOK_PLAYER_USED_BLOCK =
|
||||
{
|
||||
CalledWhen = "A player has just used a block (chest, furnace…). Notification only.",
|
||||
CalledWhen = "A player has just used a block (chest, furnace...). Notification only.",
|
||||
DefaultFnName = "OnPlayerUsedBlock", -- also used as pagename
|
||||
Desc = [[
|
||||
This hook is called after a {{cPlayer|player}} has right-clicked a block that can be used, such as a
|
||||
|
@ -10,6 +10,11 @@ return
|
||||
Params =
|
||||
{
|
||||
{ Name = "ProjectileEntity", Type = "{{cProjectileEntity}}", Notes = "The projectile that hit an entity." },
|
||||
{ Name = "BlockX", Type = "number", Notes = "The X-coord where the projectile hit." },
|
||||
{ Name = "BlockY", Type = "number", Notes = "The Y-coord where the projectile hit." },
|
||||
{ Name = "BlockZ", Type = "number", Notes = "The Z-coord where the projectile hit." },
|
||||
{ Name = "BlockFace", Type = "number", Notes = "The side of the block where the projectile hit." },
|
||||
{ Name = "BlockHitPos", Type = "Vector3d", Notes = "The exact position where the projectile hit." },
|
||||
},
|
||||
Returns = [[
|
||||
If the function returns false or no value, the next plugin's callback is called. If the function
|
||||
|
@ -6,7 +6,7 @@ return
|
||||
DefaultFnName = "OnWeatherChanging", -- also used as pagename
|
||||
Desc = [[
|
||||
This hook is called when the current weather has expired and a new weather is selected. Plugins may
|
||||
override the new weather setting.</p>
|
||||
override the new weather being set.</p>
|
||||
<p>
|
||||
The new weather setting is sent to the clients only after this hook has been processed.</p>
|
||||
<p>
|
||||
@ -19,9 +19,12 @@ return
|
||||
{ Name = "Weather", Type = "number", Notes = "The newly selected weather. One of wSunny, wRain, wStorm" },
|
||||
},
|
||||
Returns = [[
|
||||
If the function returns false or no value, the server calls other plugins' callbacks and finally
|
||||
sets the weather. If the function returns true, the server takes the second returned value (wSunny
|
||||
by default) and sets it as the new weather. No other plugins' callbacks are called in this case.
|
||||
The hook handler can return up to two values. If the first value is false or not present, the server
|
||||
calls other plugins' callbacks and finally sets the weather. If it is true, the server doesn't call any
|
||||
more callbacks for this hook. The second value returned is used as the new weather. If no value is
|
||||
given, the weather from the parameters is used as the weather. Returning false as the first value and a
|
||||
specific weather constant as the second value makes the server call the rest of the hook handlers with
|
||||
the new weather value.
|
||||
]],
|
||||
}, -- HOOK_WEATHER_CHANGING
|
||||
}
|
||||
|
246
MCServer/Plugins/APIDump/InfoFile.html
Normal file
@ -0,0 +1,246 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>MCServer - Info.lua file</title>
|
||||
<link rel="stylesheet" type="text/css" href="main.css" />
|
||||
<link rel="stylesheet" type="text/css" href="prettify.css" />
|
||||
<script src="prettify.js"></script>
|
||||
<script src="lang-lua.js"></script>
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<h1>Info.lua file</h1>
|
||||
<h2>Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#Introduction">Introduction</a></li>
|
||||
<li><a href="#Overall">The overall structure</a></li>
|
||||
<li><a href="#AdditionalInformation">AdditionalInformation table</a></li>
|
||||
<li><a href="#Commands">Commands table</a></li>
|
||||
<li><a href="#ConsoleCommands">ConsoleCommands table</a></li>
|
||||
<li><a href="#Permissions">Permissions table</a></li>
|
||||
<li><a href="#Using">Using the file in code</a></li>
|
||||
<li><a href="#Examples">Examples</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="Introduction"><h2>Introduction</h2></a>
|
||||
|
||||
<p>For a long time MCServer plugins were plagued by poor documentation. The plugins worked, people who wrote them knew how to use them, but for anyone new to the plugin it was a terrible ordeal learning how to use it. Most of the times, the plugin authors only wrote what commands the plugin supported, sometimes not even that. Then, there was a call to action to put an end to this, to make documenting the plugins easy and at the same time centralized. Thus, the Info.lua file was born.</p>
|
||||
|
||||
<p>Most plugins have some parts that are the same across all the plugins. These are commands, console commands and their permissions. If a plugin implemented a command, it would practically copy & paste the same code over and over again. So it makes sense to extract only unique information, centralize it and automate all the parts around it. This was another reason for the Info.lua file - it is a central hub of commands, console commands and their permissions.</p>
|
||||
|
||||
<p>Last, but not least, we want to make a plugin repository on the web in the future, a repository that would store plugins, their descriptions, comments. It makes sense that the centralized information can be parsed by the repository automatically, so that advanced things, such as searching for a plugin based on a command, or determining whether two plugins collide command-wise, are possible.</p>
|
||||
|
||||
<p>After this file format has been devised, a tool has been written that allows for an easy generation of the documentation for the plugin in various formats. It outputs the documentation in a format that is perfect for pasting into the forum. It generates documentation in a Markup format to use in README.md on GitHub and similar sites. The clever thing is that you don't need to keep all those formats in sync manually - you edit the Info.lua file and this tool will re-generate the documentation for you.</p>
|
||||
|
||||
<p>So to sum up, the Info.lua file contains the plugins' commands, console commands, their permissions and possibly the overall plugin documentation, in a structured manner that can be parsed by a program, yet is human readable and editable.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="Overall"><h2>The overall structure</h2></a>
|
||||
|
||||
<p>The file consist of a declaration of a single Lua table, g_PluginInfo. This table contains all the information, structured, as its members. Each member can be a structure by itself. The entire file is a valid Lua source file, so any tool that syntax-checks Lua source can syntax-check this file. The file is somewhat forward- and backward- compatible, in the sense that it can be extended in any way without breaking.</p>
|
||||
<p>Here's a skeleton of the file:</p>
|
||||
<pre class="prettyprint lang-lua">
|
||||
g_PluginInfo =
|
||||
{
|
||||
Name = "Example Plugin",
|
||||
Date = "2014-06-12",
|
||||
Description = "This is an example plugin that shows how to use the Info.lua file",
|
||||
|
||||
-- The following members will be documented in greater detail later:
|
||||
AdditionalInformation = {},
|
||||
Commands = {},
|
||||
ConsoleCommands = {},
|
||||
Permissions = {},
|
||||
}
|
||||
</pre>
|
||||
<p>As you can see, the structure is pretty straightforward. Note that the order of the elements inside the table is not important (Lua property).</p>
|
||||
|
||||
<p>The first few elements are for book-keeping. They declare the plugin's name, the date in ISO-format, representing the version of the plugin, and the description. The idea is that the description sums up what the plugin is all about, within some two or three sentences.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="AdditionalInformation"><h2>AdditionalInformation table</h2></a>
|
||||
|
||||
<p>This table is used for more detailed description of the plugin. If there is any non-trivial setup process, dependencies, describe them here. This is where the description should get detailed. Don't worry about using several paragraphs of text here, if it makes the plugin easier to understand.</p>
|
||||
|
||||
<p>The table should have the following layout:</p>
|
||||
<pre class="prettyprint lang-lua">
|
||||
AdditionalInformation =
|
||||
{
|
||||
{
|
||||
Title = "Chapter 1",
|
||||
Contents = "Describe one big aspect of the plugin here",
|
||||
},
|
||||
{
|
||||
Title = "Chapter 2",
|
||||
Contents = "Describe another big topic",
|
||||
},
|
||||
}
|
||||
</pre>
|
||||
<p>The idea here is that the tool that is used to generate the documentation from the Info.lua file will create a linkified table of contents and then each of the information elements' contents. This information should be all that is needed to successfully configure, run and manage the plugin.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="Commands"><h2>Commands table</h2></a>
|
||||
|
||||
<p>The commands table lists all the commands that the plugin implements, together with their handler functions, required permissions, help strings and further information. The table supports recursion, which allows plugins to create multi-word commands easily (such as "//schematic load" and "//schematic save"), each having its own separate handler.</p>
|
||||
|
||||
<p>The table uses structure similar to the following:</p>
|
||||
<pre class="prettyprint lang-lua">
|
||||
Commands =
|
||||
{
|
||||
["/cmd1"] =
|
||||
{
|
||||
HelpString = "Performs the first action",
|
||||
Permission = "firstplugin.cmds.1",
|
||||
Alias = "/c1",
|
||||
Handler = HandleCmd1,
|
||||
ParameterCombinations =
|
||||
{
|
||||
{
|
||||
Params = "x y z",
|
||||
Help = "Performs the first action at the specified coordinates",
|
||||
},
|
||||
{
|
||||
Params = "-p",
|
||||
Help = "Performs the first action at the player's coordinates",
|
||||
}
|
||||
},
|
||||
},
|
||||
["/cmd2"] =
|
||||
{
|
||||
Alias = {"/c2", "//c2" },
|
||||
Subcommands =
|
||||
{
|
||||
sub1 = -- This declares a "/cmd2 sub1" command
|
||||
{
|
||||
HelpString = "Performs the second action's first subcommand",
|
||||
Permission = "firstplugin.cmds.2.1",
|
||||
Alias = "1",
|
||||
Handler = HandleCmd2Sub1,
|
||||
ParameterCombinations =
|
||||
{
|
||||
{
|
||||
Params = "x y z",
|
||||
Help = "Performs the second action's first subcommand at the specified coordinates",
|
||||
},
|
||||
{
|
||||
Params = "-p",
|
||||
Help = "Performs the second action's first subcommand at the player's coordinates",
|
||||
}
|
||||
},
|
||||
},
|
||||
sub2 = -- Declares a "/cmd2 sub2" command
|
||||
{
|
||||
HelpString = "Performs the second action's second subcommand",
|
||||
Permission = "firstplugin.cmds.2.2",
|
||||
Handler = HandleCmd2Sub2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>Although it may seem overwhelming at first, there is a "method to this madness". Each element of the Commands table defines one command. Most commands start with a slash, so the special Lua syntax for table elements with non-standard names needs to be applied (<code>["/cmd1"] =</code>). The command can either specify subcommands, or a handler function (specifying both is UndefinedBehavior). Subcommands uses the same structure as the entire Commands table, recursively.</p>
|
||||
|
||||
<p>The permission element specifies that the command is only available with the specified permission. Note that the permission for subcommand's parent isn't checked when the subcommand is called. This means that specifying the permission for a command that has subcommands has no effect whatsoever, but is discouraged because we may add processing for that in the future.</p>
|
||||
|
||||
<p>The ParameterCombinations table is used only for generating the documentation, it lists the various combinations of parameters that the command supports. It's worth specifying even if the command supports only one combination, because that combination will get documented this way.</p>
|
||||
|
||||
<p>The Alias member specifies any possible aliases for the command. Each alias is registered separately and if there is a subcommand table, it is applied to all aliases, just as one would expect. You can specify either a single string as the value (if there's only one alias), or a table of strings for multiple aliases. Commands with no aliases do not need to specify this member at all.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="ConsoleCommands"><h2>ConsoleCommands table</h2>
|
||||
|
||||
<p>This table serves a purpose similar to that of the Commands table, only these commands are provided for the server console. Therefore, there are no permissions specified for these commands. Since most console commands don't use a leading slash, the command names don't need the special syntax. Also, the handler function doesn't receive the Player parameter.</p>
|
||||
|
||||
<p>Here's an example of a ConsoleCommands table:</p>
|
||||
<pre class="prettyprint lang-lua">
|
||||
ConsoleCommands =
|
||||
{
|
||||
concmd =
|
||||
{
|
||||
HelpString = "Performs the console action",
|
||||
Subcommands =
|
||||
{
|
||||
sub1 =
|
||||
{
|
||||
HelpString = "Performs the console action's first subcommand",
|
||||
Handler = HandleConCmdSub1,
|
||||
ParameterCombinations =
|
||||
{
|
||||
{
|
||||
Params = "x y z",
|
||||
Help = "Performs the console action's first subcommand at the specified coordinates",
|
||||
},
|
||||
},
|
||||
},
|
||||
sub2 =
|
||||
{
|
||||
HelpString = "Performs the console action's second subcommand",
|
||||
Handler = HandleConCmdSub2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="Permissions"><h2>Permissions table</h2></a>
|
||||
|
||||
<p>The purpose of this table is to document permissions that the plugin uses. The documentation generator automatically collects the permissions specified in the Command table; the Permissions table adds a description for these permissions and may declare other permissions that aren't specifically included in the Command table.</p>
|
||||
|
||||
<pre class="prettyprint lang-lua">
|
||||
Permissions =
|
||||
{
|
||||
["firstplugin.cmd.1.1"] =
|
||||
{
|
||||
Description = "Allows the players to build high towers using the first action.",
|
||||
RecommendedGroups = "players",
|
||||
},
|
||||
["firstplugin.cmd.2.1"] =
|
||||
{
|
||||
Description = "Allows the players to kill entities using the second action. Note that this may be misused to kill other players, too.",
|
||||
RecommendedGroups = "admins, mods",
|
||||
},
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The RecommendedGroup element lists, in plain English, the intended groups for which the permission should be enabled on a typical server. Plugin authors are advised to create reasonable defaults, prefering security to openness, so that admins using these settings blindly don't expose their servers to malicious users.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="Using"><h2>Using the file in code</h2></a>
|
||||
|
||||
<p>Just writing the Info.lua file and saving it to the plugin folder is not enough for it to actually be used. Your plugin needs to include the following boilerplate code, preferably in its Initialize() function:</p>
|
||||
<pre class="prettyprint lang-lua">
|
||||
-- Use the InfoReg shared library to process the Info.lua file:
|
||||
dofile(cPluginManager:GetPluginsPath() .. "/InfoReg.lua")
|
||||
RegisterPluginInfoCommands()
|
||||
RegisterPluginInfoConsoleCommands()
|
||||
</pre>
|
||||
|
||||
<p>Of course, if your plugin doesn't have any console commands, it doesn't need to call the RegisterPluginInfoConsoleCommands() function, and similarly if it doesn't have any in-game commands, it doesn't need to call the RegisterPluginInfoCommands() function.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
<a name="Examples"><h2>Examples</h2></a>
|
||||
|
||||
<p>There are several plugins that already implement this approach. You can visit them for inspiration and to see what the generated documentation looks like:</p>
|
||||
<ul>
|
||||
<li>Gallery plugin: <a href="https://github.com/mc-server/Gallery/blob/master/Info.lua">Info.lua</a>, <a href="http://forum.mc-server.org/showthread.php?tid=1306">Forum</a> documentation</li>
|
||||
<li>WorldEdit plugin: <a href="https://github.com/mc-server/WorldEdit/blob/master/Info.lua">Info.lua</a>, <a href="http://forum.mc-server.org/showthread.php?tid=870">Forum</a> and <a href="https://github.com/mc-server/WorldEdit">MarkDown</a> documentation</li>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
prettyPrint();
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -39,7 +39,8 @@ pre
|
||||
|
||||
body
|
||||
{
|
||||
min-width: 800px;
|
||||
min-width: 400px;
|
||||
max-width: 1200px;
|
||||
width: 95%;
|
||||
margin: 10px auto;
|
||||
background-color: white;
|
||||
|
@ -27,10 +27,14 @@ local function LoadAPIFiles(a_Folder, a_DstTable)
|
||||
-- We only want .lua files from the folder:
|
||||
if (cFile:IsFile(FileName) and fnam:match(".*%.lua$")) then
|
||||
local TablesFn, Err = loadfile(FileName);
|
||||
if (TablesFn == nil) then
|
||||
if (type(TablesFn) ~= "function") then
|
||||
LOGWARNING("Cannot load API descriptions from " .. FileName .. ", Lua error '" .. Err .. "'.");
|
||||
else
|
||||
local Tables = TablesFn();
|
||||
if (type(Tables) ~= "table") then
|
||||
LOGWARNING("Cannot load API descriptions from " .. FileName .. ", returned object is not a table (" .. type(Tables) .. ").");
|
||||
break
|
||||
end
|
||||
for k, cls in pairs(Tables) do
|
||||
a_DstTable[k] = cls;
|
||||
end
|
||||
|
@ -43,7 +43,7 @@ function HandleRequest_Generation( Request )
|
||||
local Content = ""
|
||||
if (Request.PostParams["AGHRRRR"] ~= nil) then
|
||||
GENERATION_STATE = 0
|
||||
WW_instance:SaveAllChunks()
|
||||
WW_instance:QueueSaveAllChunks()
|
||||
WW_instance:QueueUnloadUnusedChunks()
|
||||
LOGERROR("" .. PLUGIN:GetName() .. " v" .. PLUGIN:GetVersion() .. ": works ABORTED by admin")
|
||||
end
|
||||
|
@ -29,7 +29,10 @@ function Initialize(Plugin)
|
||||
PM:AddHook(cPluginManager.HOOK_WORLD_TICK, OnWorldTick);
|
||||
PM:AddHook(cPluginManager.HOOK_PLUGINS_LOADED, OnPluginsLoaded);
|
||||
PM:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
|
||||
PM:AddHook(cPluginManager.HOOK_PLAYER_JOINED, OnPlayerJoined)
|
||||
PM:AddHook(cPluginManager.HOOK_PLAYER_JOINED, OnPlayerJoined);
|
||||
PM:AddHook(cPluginManager.HOOK_PROJECTILE_HIT_BLOCK, OnProjectileHitBlock);
|
||||
PM:AddHook(cPluginManager.HOOK_CHUNK_UNLOADING, OnChunkUnloading);
|
||||
PM:AddHook(cPluginManager.HOOK_WORLD_STARTED, OnWorldStarted);
|
||||
|
||||
-- _X: Disabled so that the normal operation doesn't interfere with anything
|
||||
-- PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
|
||||
@ -57,9 +60,10 @@ function Initialize(Plugin)
|
||||
PM:BindCommand("/ff", "debuggers", HandleFurnaceFuel, "- Shows how long the currently held item would burn in a furnace");
|
||||
PM:BindCommand("/sched", "debuggers", HandleSched, "- Schedules a simple countdown using cWorld:ScheduleTask()");
|
||||
PM:BindCommand("/cs", "debuggers", HandleChunkStay, "- Tests the ChunkStay Lua integration for the specified chunk coords");
|
||||
PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings")
|
||||
PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one")
|
||||
PM:BindCommand("/wesel", "debuggers", HandleWESel, "- Expands the current WE selection by 1 block in X/Z")
|
||||
PM:BindCommand("/compo", "debuggers", HandleCompo, "- Tests the cCompositeChat bindings");
|
||||
PM:BindCommand("/sb", "debuggers", HandleSetBiome, "- Sets the biome around you to the specified one");
|
||||
PM:BindCommand("/wesel", "debuggers", HandleWESel, "- Expands the current WE selection by 1 block in X/Z");
|
||||
PM:BindCommand("/rmitem", "debuggers", HandleRMItem, "- Remove the specified item from the inventory.");
|
||||
|
||||
Plugin:AddWebTab("Debuggers", HandleRequest_Debuggers)
|
||||
Plugin:AddWebTab("StressTest", HandleRequest_StressTest)
|
||||
@ -345,7 +349,7 @@ end
|
||||
|
||||
function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ)
|
||||
-- Magic rod of query: show block types and metas for both neighbors of the pointed face
|
||||
local Type, Meta, Valid = Player:GetWorld():GetBlockTypeMeta(BlockX, BlockY, BlockZ, Type, Meta);
|
||||
local Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(BlockX, BlockY, BlockZ);
|
||||
|
||||
if (Type == E_BLOCK_AIR) then
|
||||
Player:SendMessage(cChatColor.LightGray .. "Block {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}: air:" .. Meta);
|
||||
@ -355,7 +359,7 @@ function OnUsingBlazeRod(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cur
|
||||
end
|
||||
|
||||
local X, Y, Z = AddFaceDirection(BlockX, BlockY, BlockZ, BlockFace);
|
||||
Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z, Type, Meta);
|
||||
Valid, Type, Meta = Player:GetWorld():GetBlockTypeMeta(X, Y, Z);
|
||||
if (Type == E_BLOCK_AIR) then
|
||||
Player:SendMessage(cChatColor.LightGray .. "Block {" .. X .. ", " .. Y .. ", " .. Z .. "}: air:" .. Meta);
|
||||
else
|
||||
@ -530,7 +534,7 @@ function OnTakeDamage(Receiver, TDI)
|
||||
-- Receiver is cPawn
|
||||
-- TDI is TakeDamageInfo
|
||||
|
||||
LOG(Receiver:GetClass() .. " was dealt " .. DamageTypeToString(TDI.DamageType) .. " damage: Raw " .. TDI.RawDamage .. ", Final " .. TDI.FinalDamage .. " (" .. (TDI.RawDamage - TDI.FinalDamage) .. " covered by armor)");
|
||||
-- LOG(Receiver:GetClass() .. " was dealt " .. DamageTypeToString(TDI.DamageType) .. " damage: Raw " .. TDI.RawDamage .. ", Final " .. TDI.FinalDamage .. " (" .. (TDI.RawDamage - TDI.FinalDamage) .. " covered by armor)");
|
||||
return false;
|
||||
end
|
||||
|
||||
@ -1102,6 +1106,41 @@ end
|
||||
|
||||
|
||||
|
||||
function HandleRMItem(a_Split, a_Player)
|
||||
-- Check params:
|
||||
if (a_Split[2] == nil) then
|
||||
a_Player:SendMessage("Usage: /rmitem <Item> [Count]")
|
||||
return true
|
||||
end
|
||||
|
||||
-- Parse the item type:
|
||||
local Item = cItem()
|
||||
if (not StringToItem(a_Split[2], Item)) then
|
||||
a_Player:SendMessageFailure(a_Split[2] .. " isn't a valid item")
|
||||
return true
|
||||
end
|
||||
|
||||
-- Parse the optional item count
|
||||
if (a_Split[3] ~= nil) then
|
||||
local Count = tonumber(a_Split[3])
|
||||
if (Count == nil) then
|
||||
a_Player:SendMessageFailure(a_Split[3] .. " isn't a valid number")
|
||||
return true
|
||||
end
|
||||
|
||||
Item.m_ItemCount = Count
|
||||
end
|
||||
|
||||
-- Remove the item:
|
||||
local NumRemovedItems = a_Player:GetInventory():RemoveItem(Item)
|
||||
a_Player:SendMessageSuccess("Removed " .. NumRemovedItems .. " Items!")
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function HandleRequest_Debuggers(a_Request)
|
||||
local FolderContents = cFile:GetFolderContents("./");
|
||||
return "<p>The following objects have been returned by cFile:GetFolderContents():<ul><li>" .. table.concat(FolderContents, "</li><li>") .. "</li></ul></p>";
|
||||
@ -1379,3 +1418,40 @@ end
|
||||
|
||||
|
||||
|
||||
|
||||
function OnProjectileHitBlock(a_Projectile, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockHitPos)
|
||||
-- Test projectile hooks by setting the blocks they hit on fire:
|
||||
local BlockX, BlockY, BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace)
|
||||
local World = a_Projectile:GetWorld()
|
||||
|
||||
World:SetBlock(BlockX, BlockY, BlockZ, E_BLOCK_FIRE, 0)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function OnChunkUnloading(a_World, a_ChunkX, a_ChunkZ)
|
||||
-- Do not let chunk [0, 0] unload, so that it continues ticking [cWorld:SetChunkAlwaysTicked() test]
|
||||
if ((a_ChunkX == 0) and (a_ChunkZ == 0)) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function OnWorldStarted(a_World)
|
||||
-- Make the chunk [0, 0] in every world keep ticking [cWorld:SetChunkAlwaysTicked() test]
|
||||
a_World:ChunkStay({{0, 0}}, nil,
|
||||
function()
|
||||
-- The chunk is loaded, make it always tick:
|
||||
a_World:SetChunkAlwaysTicked(0, 0, true)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -22,6 +22,8 @@ function Initialize(Plugin)
|
||||
Plugin:SetVersion(1);
|
||||
|
||||
cPluginManager.AddHook(cPluginManager.HOOK_PLAYER_USED_ITEM, OnPlayerUsedItem);
|
||||
|
||||
LOG("Initialized " .. Plugin:GetName() .. " v." .. Plugin:GetVersion());
|
||||
return true;
|
||||
end
|
||||
|
||||
@ -36,8 +38,8 @@ function OnPlayerUsedItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cu
|
||||
return false;
|
||||
end;
|
||||
|
||||
if (Player:HasPermission("diamondmover.move") == false) then
|
||||
return true;
|
||||
if (not Player:HasPermission("diamondmover.move")) then
|
||||
return false;
|
||||
end;
|
||||
|
||||
-- Rclk with a diamond to push in the direction the player is facing
|
||||
@ -56,7 +58,7 @@ function OnPlayerUsedItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, Cu
|
||||
if (PlayerPitch > 70) then -- looking down
|
||||
BlockY = BlockY - 1;
|
||||
else
|
||||
local PlayerRot = Player:GetRotation() + 180; -- Convert [-180, 180] into [0, 360] for simpler conditions
|
||||
local PlayerRot = Player:GetYaw() + 180; -- Convert [-180, 180] into [0, 360] for simpler conditions
|
||||
if ((PlayerRot < 45) or (PlayerRot > 315)) then
|
||||
BlockZ = BlockZ - 1;
|
||||
else
|
||||
|
@ -6,7 +6,7 @@ function GetHandyVersion()
|
||||
return HANDY_VERSION
|
||||
end
|
||||
-- Checks if handy is in proper version
|
||||
function CheckForRequiedVersion( inVersion )
|
||||
function CheckForRequiredVersion( inVersion )
|
||||
if( inVersion > HANDY_VERSION ) then return false end
|
||||
return true
|
||||
end
|
||||
@ -213,4 +213,4 @@ end
|
||||
function BoolToString( inValue )
|
||||
if( inValue == true ) then return 1 end
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
@ -61,18 +61,31 @@
|
||||
#--------------------------
|
||||
# Fuels
|
||||
|
||||
! 263:1 = 1600 # 1 Coal -> 80 sec
|
||||
! 263:1:1 = 1600 # 1 Charcoal -> 80 sec
|
||||
! 42:126:1 = 150 # 1 Halfslab -> 7.5 seconds
|
||||
! 5:1 = 300 # 1 Planks -> 15 sec
|
||||
! 280:1 = 100 # 1 Stick -> 5 sec
|
||||
! 85:1 = 300 # 1 Fence -> 15 sec
|
||||
! 53:1 = 300 # 1 Wooden Stairs -> 15 sec
|
||||
! 58:1 = 300 # 1 Crafting Table -> 15 sec
|
||||
! 47:1 = 300 # 1 Bookshelf -> 15 sec
|
||||
! 54:1 = 300 # 1 Chest -> 15 sec
|
||||
! 84:1 = 300 # 1 Jukebox -> 15 sec
|
||||
! 327:1 = 200000 # 1 Lava Bucket -> 1000 sec
|
||||
! 17:1 = 300 # 1 Wood -> 15 sec
|
||||
! 6:1 = 100 # 1 Sapling -> 5 sec
|
||||
! 173:1 = 7400 # 1 Coal Block -> 370 sec, based on https://github.com/minetest/common/commit/e0f5a6fd6936052756e27a05a2bfdd6aa86b38e1 which is a clone of MC
|
||||
! 263:1 = 1600 # 1 Coal -> 80 sec
|
||||
! 263:1:1 = 1600 # 1 Charcoal -> 80 sec
|
||||
! 126:1 = 15 # 1 Halfslab -> 7.5 sec
|
||||
! 5:1 = 300 # 1 Planks -> 15 sec
|
||||
! 280:1 = 100 # 1 Stick -> 5 sec
|
||||
! 85:1 = 300 # 1 Fence -> 15 sec
|
||||
! 53:1 = 300 # 1 Wooden Stairs -> 15 sec
|
||||
! 58:1 = 300 # 1 Crafting Table -> 15 sec
|
||||
! 47:1 = 300 # 1 Bookshelf -> 15 sec
|
||||
! 54:1 = 300 # 1 Chest -> 15 sec
|
||||
! 84:1 = 300 # 1 Jukebox -> 15 sec
|
||||
! 327:1 = 20000 # 1 Lava Bucket -> 1000 sec
|
||||
! 17:1 = 300 # 1 Wood -> 15 sec
|
||||
! 6:1 = 100 # 1 Sapling -> 5 sec
|
||||
! 173:1 = 16000 # 1 Coal Block -> 800 sec
|
||||
! 369:1 = 2400 # 1 Blaze Rod -> 120 sec
|
||||
! 25:1 = 300 # 1 Note Block -> 15 sec
|
||||
! 151:1 = 300 # 1 Daylight Sensor -> 15 sec
|
||||
! 107:1 = 300 # 1 Fence Gate -> 15 sec
|
||||
! 167:1 = 300 # 1 Trapdoor -> 15 sec
|
||||
! 146:1 = 300 # 1 Trapped Chest -> 15 sec
|
||||
! 72:1 = 300 # 1 Pressure Plate -> 15 sec
|
||||
! 270:1 = 200 # 1 Wooden Pickaxe -> 10 sec
|
||||
! 271:1 = 200 # 1 Wooden Axe -> 10 sec
|
||||
! 269:1 = 200 # 1 Wooden Shovel -> 10 sec
|
||||
! 290:1 = 200 # 1 Wooden Hoe -> 10 sec
|
||||
! 268:1 = 200 # 1 Wooden Sword -> 10 sec
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
echo This script generates the certificate and private key for the https webadmin
|
||||
echo Note that the generated certificate is self-signed, and therefore not trusted by browsers
|
||||
echo Note that this script requires openssl to be installed and in PATH
|
||||
echo.
|
||||
echo When OpenSSL asks you for Common Name, you need to enter the fully qualified domain name of the server, that is, e. g. gallery.xoft.cz
|
||||
echo.
|
||||
echo If OpenSSL fails with an error, "WARNING: can't open config file: /usr/local/ssl/openssl.cnf", you need to run this script as an administrator
|
||||
echo.
|
||||
|
||||
openssl req -x509 -newkey rsa:2048 -keyout httpskey.pem -out httpscert.crt -days 3650 -nodes
|
||||
pause
|
10
MCServer/webadmin/GenerateSelfSignedHTTPSCertUsingOpenssl.sh
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "This script generates the certificate and private key for the https webadmin"
|
||||
echo "Note that the generated certificate is self-signed, and therefore not trusted by browsers"
|
||||
echo "Note that this script requires openssl to be installed and in PATH"
|
||||
echo ""
|
||||
echo "When OpenSSL asks you for Common Name, you need to enter the fully qualified domain name of the server, that is, e. g. gallery.xoft.cz"
|
||||
echo ""
|
||||
|
||||
openssl req -x509 -newkey rsa:2048 -keyout httpskey.pem -out httpscert.crt -days 3650 -nodes
|
29
README.md
@ -1,38 +1,39 @@
|
||||
MCServer
|
||||
MCServer [![Build Status](http://img.shields.io/travis/mc-server/MCServer.svg)](https://travis-ci.org/mc-server/MCServer) [![Coverity Scan Build Status](https://scan.coverity.com/projects/1930/badge.svg)](https://scan.coverity.com/projects/1930) [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
|
||||
========
|
||||
|
||||
**Current Protocol Supported:** Minecraft v1.2 -> v1.7
|
||||
|
||||
MCServer is a performant C++ Minecraft server designed for use in memory and cpu-limited places, or just to make regular server perform better.
|
||||
MCServer is a Minecraft server that is written in C++ and designed to be efficient with memory and CPU, as well as having a flexible Lua Plugin API.
|
||||
|
||||
MCServer can run on PCs, Macs, and *nix. This includes android phones and tablets as well as Raspberry Pis.
|
||||
|
||||
We currently support the protocol from Minecraft 1.2 all the way up to Minecraft 1.7.10.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
To install MCServer, you can either download the repository and compile it, or download a pre-compiled version.
|
||||
Normally, you will want to download a pre-compiled version of MCServer from one of the buildservers:
|
||||
|
||||
If you've cloned the repository using Git, you need to pull down the submodules (core plugins, some dependencies). This can be achieved with `git submodule init` and then on a regular basis (to keep up to date) `git submodule update`.
|
||||
* [Linux and Raspberry Pi](http://ci.bearbin.net) (Bearbin's CI Server)
|
||||
* [Windows](http://mc-server.xoft.cz) (xoft's nightly build service)
|
||||
|
||||
If you downloaded a ZIP file of the sources instead, you will need to download PolarSSL, too, from https://github.com/polarssl/polarssl , and unpack it into the `lib/polarssl` folder. You will also need to manually download all the plugins that you want included.
|
||||
You simply need to download and extract these files before you can use the server.
|
||||
|
||||
Compilation instructions are available in the COMPILING file.
|
||||
|
||||
Linux builds can be downloaded from [Bearbin's CI Service](http://ci.bearbin.net) and Windows builds from xoft's [nightly build service](http://mc-server.xoft.cz).
|
||||
|
||||
After you've extracted the files, simply run the MCServer executable.
|
||||
If you're a more advanced user, you may want to compile the server yourself for more performance. See the [COMPILING.md](https://github.com/mc-server/MCServer/blob/master/COMPILING.md) file for more details.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
MCServer is licensed under the Apache license V2, and we welcome anybody to fork and submit a Pull Request back with their changes, and if you want to join as a permanent member we can add you to the team.
|
||||
|
||||
Check out the [CONTRIBUTING.md](https://github.com/mc-server/MCServer/blob/master/CONTRIBUTING.md) file for more details.
|
||||
|
||||
Other Stuff
|
||||
-----------
|
||||
|
||||
For other stuff, including plugins and discussion, check the [forums](http://forum.mc-server.org) and [wiki](http://wiki.mc-server.org/).
|
||||
For other stuff, including plugins and discussion, check the [forums](http://forum.mc-server.org) and [Plugin API](http://mc-server.xoft.cz/LuaAPI/).
|
||||
|
||||
Earn bitcoins for commits or donate to reward the MCServer developers: [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
|
||||
|
||||
Travis CI: [![Build Status](https://travis-ci.org/mc-server/MCServer.png?branch=master)](https://travis-ci.org/mc-server/MCServer)
|
||||
Support Us on Gittip: [![Support via Gittip](http://img.shields.io/gittip/mcs_team.svg)](https://www.gittip.com/mcs_team)
|
||||
|
||||
Travis CI: [![Build Status](http://img.shields.io/travis/mc-server/MCServer.svg)](https://travis-ci.org/mc-server/MCServer)
|
||||
|
||||
|
121
SetFlags.cmake
@ -1,32 +1,49 @@
|
||||
macro (add_flags_lnk FLAGS)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "${CMAKE_EXE_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "${CMAKE_SHARED_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_COVERAGE "${CMAKE_MODULE_LINKER_FLAGS_COVERAGE} ${FLAGS}")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} ${FLAGS}")
|
||||
endmacro()
|
||||
|
||||
macro(add_flags_cxx FLAGS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE} ${FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${FLAGS}")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${FLAGS}")
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(set_flags)
|
||||
# Add coverage processing, if requested:
|
||||
if (NOT MSVC)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "COVERAGE")
|
||||
message("Including CodeCoverage")
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
|
||||
include(CodeCoverage)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -D_DEBUG")
|
||||
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE} -D_DEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
@ -42,9 +59,10 @@ macro(set_flags)
|
||||
elseif(APPLE)
|
||||
#on os x clang adds pthread for us but we need to add it for gcc
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
||||
add_flags_cxx("-stdlib=libc++")
|
||||
add_flags_lnk("-stdlib=libc++")
|
||||
else()
|
||||
@ -53,16 +71,21 @@ macro(set_flags)
|
||||
|
||||
else()
|
||||
# Let gcc / clang know that we're compiling a multi-threaded app:
|
||||
add_flags_cxx("-pthread")
|
||||
if (UNIX)
|
||||
add_flags_cxx("-pthread")
|
||||
endif()
|
||||
|
||||
# Make CLang use C++11, otherwise MSVC2008-supported extensions don't work ("override" keyword etc.):
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -std=c++11")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++11")
|
||||
endif()
|
||||
|
||||
# We use a signed char (fixes #640 on RasPi)
|
||||
add_flags_cxx("-fsigned-char")
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
@ -97,10 +120,12 @@ macro(set_lib_flags)
|
||||
string(REPLACE "/W3" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "/W3" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -w")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -w")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -w")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -w")
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -w")
|
||||
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE} -w")
|
||||
endif()
|
||||
|
||||
# On Unix we use two dynamic loading libraries dl and ltdl.
|
||||
@ -118,8 +143,8 @@ endmacro()
|
||||
macro(enable_profile)
|
||||
# Declare the flags used for profiling builds:
|
||||
if (MSVC)
|
||||
set (CXX_PROFILING "")
|
||||
set (LNK_PROFILING "/PROFILE")
|
||||
set (CXX_PROFILING "/Zi")
|
||||
set (LNK_PROFILING "/PROFILE /DEBUG")
|
||||
else()
|
||||
set (CXX_PROFILING "-pg")
|
||||
set (LNK_PROFILING "-pg")
|
||||
@ -128,7 +153,7 @@ macro(enable_profile)
|
||||
|
||||
# Declare the profiling configurations:
|
||||
SET(CMAKE_CXX_FLAGS_DEBUGPROFILE
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} ${PCXX_ROFILING}"
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} ${CXX_PROFILING}"
|
||||
CACHE STRING "Flags used by the C++ compiler during profile builds."
|
||||
FORCE )
|
||||
SET(CMAKE_C_FLAGS_DEBUGPROFILE
|
||||
@ -171,36 +196,42 @@ macro(enable_profile)
|
||||
CMAKE_EXE_LINKER_FLAGS_RELEASEPROFILE
|
||||
CMAKE_SHARED_LINKER_FLAGS_RELEASEPROFILE )
|
||||
# The configuration types need to be set after their respective c/cxx/linker flags and before the project directive
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
|
||||
if(MSVC)
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile" CACHE STRING "" FORCE)
|
||||
else()
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;DebugProfile;ReleaseProfile;Coverage" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
|
||||
macro(set_exe_flags)
|
||||
# Remove disabling the maximum warning level:
|
||||
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
|
||||
# We do not do that for MSVC since MSVC produces an awful lot of warnings for its own STL headers;
|
||||
# the important warnings are turned on using #pragma in Globals.h
|
||||
if (NOT MSVC)
|
||||
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
|
||||
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
|
||||
string(REPLACE "-w" "" CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE}")
|
||||
string(REPLACE "-w" "" CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_COVERAGE}")
|
||||
add_flags_cxx("-Wall -Wextra -Wno-unused-parameter -Wno-error=switch")
|
||||
|
||||
|
||||
# we support non-IEEE 754 fpus so can make no guarentees about error
|
||||
add_flags_cxx("-ffast-math")
|
||||
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# clang does not provide the __extern_always_inline macro and a part of libm depends on this when using fast-math
|
||||
add_flags_cxx("-D__extern_always_inline=inline")
|
||||
add_flags_cxx("-Werror -Weverything -Wno-c++98-compat-pedantic -Wno-string-conversion")
|
||||
add_flags_cxx("-Wno-extra-semi -Wno-error=switch-enum -Wno-documentation")
|
||||
add_flags_cxx("-Wno-error=switch-enum -Wno-documentation -Wno-exit-time-destructors")
|
||||
add_flags_cxx("-Wno-error=sign-conversion -Wno-error=conversion -Wno-padded")
|
||||
add_flags_cxx("-Wno-error=deprecated -Wno-error=weak-vtables -Wno-error=float-equal")
|
||||
add_flags_cxx("-Wno-error=missing-prototypes -Wno-error=non-virtual-dtor")
|
||||
add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=shadow")
|
||||
add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=shadow -Wno-error=old-style-cast")
|
||||
add_flags_cxx("-Wno-error=exit-time-destructors -Wno-error=missing-variable-declarations")
|
||||
add_flags_cxx("-Wno-error=global-constructors -Wno-implicit-fallthrough")
|
||||
add_flags_cxx("-Wno-weak-vtables -Wno-switch-enum -Wno-exit-time-destructors")
|
||||
add_flags_cxx("-Wno-error=extra-semi -Wno-weak-vtables -Wno-switch-enum")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -1,32 +1,53 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AnvilStats", "AnvilStats.vcproj", "{CF996A5E-0A86-4004-9710-682B06B5AEBA}"
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2013 for Windows Desktop
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AnvilStats", "AnvilStats.vcxproj", "{CF996A5E-0A86-4004-9710-682B06B5AEBA}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA} = {EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821} = {B61007AC-B557-4B67-A765-E468C0C3A821}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\VC2008\zlib.vcproj", "{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\lib\zlib\zlib.vcxproj", "{B61007AC-B557-4B67-A765-E468C0C3A821}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
DebugProfile|Win32 = DebugProfile|Win32
|
||||
MinSizeRel|Win32 = MinSizeRel|Win32
|
||||
Release profiled|Win32 = Release profiled|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
ReleaseProfile|Win32 = ReleaseProfile|Win32
|
||||
RelWithDebInfo|Win32 = RelWithDebInfo|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.DebugProfile|Win32.ActiveCfg = Debug|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.DebugProfile|Win32.Build.0 = Debug|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.MinSizeRel|Win32.ActiveCfg = Release|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.MinSizeRel|Win32.Build.0 = Release|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.Release profiled|Win32.ActiveCfg = Release profiled|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.Release profiled|Win32.Build.0 = Release profiled|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.Release|Win32.Build.0 = Release|Win32
|
||||
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release profiled|Win32.ActiveCfg = Release profiled|Win32
|
||||
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release profiled|Win32.Build.0 = Release profiled|Win32
|
||||
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EA9D50FD-937A-4EF5-8C37-5F4175AF4FEA}.Release|Win32.Build.0 = Release|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.ReleaseProfile|Win32.ActiveCfg = Release|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.ReleaseProfile|Win32.Build.0 = Release|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
|
||||
{CF996A5E-0A86-4004-9710-682B06B5AEBA}.RelWithDebInfo|Win32.Build.0 = Release|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.DebugProfile|Win32.ActiveCfg = DebugProfile|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.DebugProfile|Win32.Build.0 = DebugProfile|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.MinSizeRel|Win32.ActiveCfg = MinSizeRel|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.MinSizeRel|Win32.Build.0 = MinSizeRel|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.Release profiled|Win32.ActiveCfg = Release|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.Release profiled|Win32.Build.0 = Release|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.Release|Win32.Build.0 = Release|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.ReleaseProfile|Win32.ActiveCfg = ReleaseProfile|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.ReleaseProfile|Win32.Build.0 = ReleaseProfile|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.RelWithDebInfo|Win32.ActiveCfg = RelWithDebInfo|Win32
|
||||
{B61007AC-B557-4B67-A765-E468C0C3A821}.RelWithDebInfo|Win32.Build.0 = RelWithDebInfo|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -5,38 +5,7 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "BiomeMap.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const int g_BiomePalette[] =
|
||||
{
|
||||
// ARGB:
|
||||
0xff0000ff, /* Ocean */
|
||||
0xff00cf3f, /* Plains */
|
||||
0xffffff00, /* Desert */
|
||||
0xff7f7f7f, /* Extreme Hills */
|
||||
0xff00cf00, /* Forest */
|
||||
0xff007f3f, /* Taiga */
|
||||
0xff3f7f00, /* Swampland */
|
||||
0xff003fff, /* River */
|
||||
0xff7f0000, /* Hell */
|
||||
0xff007fff, /* Sky */
|
||||
0xff3f3fff, /* Frozen Ocean */
|
||||
0xff3f3fff, /* Frozen River */
|
||||
0xff7fffcf, /* Ice Plains */
|
||||
0xff3fcf7f, /* Ice Mountains */
|
||||
0xffcf00cf, /* Mushroom Island */
|
||||
0xff7f00ff, /* Mushroom Island Shore */
|
||||
0xffffff3f, /* Beach */
|
||||
0xffcfcf00, /* Desert Hills */
|
||||
0xff00cf3f, /* Forest Hills */
|
||||
0xff006f1f, /* Taiga Hills */
|
||||
0xff7f8f7f, /* Extreme Hills Edge */
|
||||
0xff004f00, /* Jungle */
|
||||
0xff003f00, /* Jungle Hills */
|
||||
} ;
|
||||
#include "../BiomeVisualiser/BiomeColors.h"
|
||||
|
||||
|
||||
|
||||
@ -139,7 +108,7 @@ void cBiomeMap::StartNewRegion(int a_RegionX, int a_RegionZ)
|
||||
unsigned char * BiomeRow = (unsigned char *)m_Biomes + z * 512;
|
||||
for (int x = 0; x < 512; x++)
|
||||
{
|
||||
RowData[x] = g_BiomePalette[BiomeRow[x]];
|
||||
RowData[x] = g_BiomeColors[BiomeRow[x]];
|
||||
}
|
||||
f.Write(RowData, sizeof(RowData));
|
||||
} // for z
|
||||
|
@ -41,7 +41,7 @@ protected:
|
||||
virtual bool OnDecompressedData(const char * a_DecompressedNBT, int a_DataSize) override { return false; }
|
||||
virtual bool OnRealCoords(int a_ChunkX, int a_ChunkZ) override { return false; }
|
||||
virtual bool OnLastUpdate(Int64 a_LastUpdate) override { return false; }
|
||||
virtual bool OnTerrainPopulated(bool a_Populated) override { return !a_Populated; } // If not populated, we don't want it!
|
||||
virtual bool OnTerrainPopulated(bool a_Populated) override { return false; } // We don't care about "populated", the biomes are the same
|
||||
virtual bool OnBiomes(const unsigned char * a_BiomeData) override;
|
||||
|
||||
void StartNewRegion(int a_RegionX, int a_RegionZ);
|
||||
|
@ -24,6 +24,15 @@
|
||||
#define ALIGN_8
|
||||
#define ALIGN_16
|
||||
|
||||
#define FORMATSTRING(formatIndex, va_argsIndex)
|
||||
|
||||
// MSVC has its own custom version of zu format
|
||||
#define SIZE_T_FMT "%Iu"
|
||||
#define SIZE_T_FMT_PRECISION(x) "%" #x "Iu"
|
||||
#define SIZE_T_FMT_HEX "%Ix"
|
||||
|
||||
#define NORETURN __declspec(noreturn)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
|
||||
@ -40,6 +49,14 @@
|
||||
// Some portability macros :)
|
||||
#define stricmp strcasecmp
|
||||
|
||||
#define FORMATSTRING(formatIndex, va_argsIndex) __attribute__((format (printf, formatIndex, va_argsIndex)))
|
||||
|
||||
#define SIZE_T_FMT "%zu"
|
||||
#define SIZE_T_FMT_PRECISION(x) "%" #x "zu"
|
||||
#define SIZE_T_FMT_HEX "%zx"
|
||||
|
||||
#define NORETURN __attribute((__noreturn__))
|
||||
|
||||
#else
|
||||
|
||||
#error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
|
||||
@ -194,6 +211,8 @@ typedef unsigned short UInt16;
|
||||
/// Faster than (int)floorf((float)x / (float)div)
|
||||
#define FAST_FLOOR_DIV( x, div ) ( (x) < 0 ? (((int)x / div) - 1) : ((int)x / div) )
|
||||
|
||||
#define TOLUA_TEMPLATE_BIND(...)
|
||||
|
||||
// Own version of assert() that writes failed assertions to the log for review
|
||||
#ifdef _DEBUG
|
||||
#define ASSERT( x ) ( !!(x) || ( LOGERROR("Assertion failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), assert(0), 0 ) )
|
||||
@ -204,6 +223,8 @@ typedef unsigned short UInt16;
|
||||
// Pretty much the same as ASSERT() but stays in Release builds
|
||||
#define VERIFY( x ) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), exit(1), 0 ) )
|
||||
|
||||
typedef unsigned char Byte;
|
||||
|
||||
|
||||
|
||||
|
||||
@ -227,3 +248,4 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -109,7 +109,7 @@ bool cSpringStats::OnSectionsFinished(void)
|
||||
int Base = BaseY + z * 16;
|
||||
for (int x = 1; x < 15; x++)
|
||||
{
|
||||
if (cChunkDef::GetNibble(m_BlockMetas, Base + x) != 0)
|
||||
if (cChunkDef::GetNibble(m_BlockMetas, x, y, z) != 0)
|
||||
{
|
||||
// Not a source block
|
||||
continue;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="windows-1250"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Version="9,00"
|
||||
Name="BiomeVisualiser"
|
||||
ProjectGUID="{6DF3D88B-AD47-45B6-B831-1BDE74F86B5C}"
|
||||
RootNamespace="BiomeVisualiser"
|
||||
@ -327,6 +327,14 @@
|
||||
<Filter
|
||||
Name="Shared"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\src\BiomeDef.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\BiomeDef.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\BlockID.cpp"
|
||||
>
|
||||
@ -355,6 +363,14 @@
|
||||
RelativePath="..\..\src\WorldStorage\FastNBT.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\FastRandom.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\FastRandom.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\Globals.cpp"
|
||||
>
|
||||
|
@ -22,6 +22,15 @@
|
||||
#define ALIGN_8
|
||||
#define ALIGN_16
|
||||
|
||||
#define FORMATSTRING(formatIndex, va_argsIndex)
|
||||
|
||||
// MSVC has its own custom version of zu format
|
||||
#define SIZE_T_FMT "%Iu"
|
||||
#define SIZE_T_FMT_PRECISION(x) "%" #x "Iu"
|
||||
#define SIZE_T_FMT_HEX "%Ix"
|
||||
|
||||
#define NORETURN __declspec(noreturn)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
// TODO: Can GCC explicitly mark classes as abstract (no instances can be created)?
|
||||
@ -39,6 +48,12 @@
|
||||
#define stricmp strcasecmp
|
||||
|
||||
#define FORMATSTRING(formatIndex,va_argsIndex)
|
||||
|
||||
#define SIZE_T_FMT "%zu"
|
||||
#define SIZE_T_FMT_PRECISION(x) "%" #x "zu"
|
||||
#define SIZE_T_FMT_HEX "%zx"
|
||||
|
||||
#define NORETURN __attribute((__noreturn__))
|
||||
#else
|
||||
|
||||
#error "You are using an unsupported compiler, you might need to #define some stuff here for your compiler"
|
||||
@ -225,6 +240,7 @@ template <typename Type> class cItemCallback
|
||||
public:
|
||||
/// Called for each item in the internal list; return true to stop the loop, or false to continue enumerating
|
||||
virtual bool Item(Type * a_Type) = 0;
|
||||
virtual ~cItemCallback() {}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -36,14 +36,24 @@ set(SHARED_SRC
|
||||
../../src/StringUtils.cpp
|
||||
../../src/Log.cpp
|
||||
../../src/MCLogger.cpp
|
||||
../../src/Crypto.cpp
|
||||
../../src/PolarSSL++/AesCfb128Decryptor.cpp
|
||||
../../src/PolarSSL++/AesCfb128Encryptor.cpp
|
||||
../../src/PolarSSL++/CryptoKey.cpp
|
||||
../../src/PolarSSL++/CtrDrbgContext.cpp
|
||||
../../src/PolarSSL++/EntropyContext.cpp
|
||||
../../src/PolarSSL++/RsaPrivateKey.cpp
|
||||
)
|
||||
set(SHARED_HDR
|
||||
../../src/ByteBuffer.h
|
||||
../../src/StringUtils.h
|
||||
../../src/Log.h
|
||||
../../src/MCLogger.h
|
||||
../../src/Crypto.h
|
||||
../../src/PolarSSL++/AesCfb128Decryptor.h
|
||||
../../src/PolarSSL++/AesCfb128Encryptor.h
|
||||
../../src/PolarSSL++/CryptoKey.h
|
||||
../../src/PolarSSL++/CtrDrbgContext.h
|
||||
../../src/PolarSSL++/EntropyContext.h
|
||||
../../src/PolarSSL++/RsaPrivateKey.h
|
||||
)
|
||||
set(SHARED_OSS_SRC
|
||||
../../src/OSSupport/CriticalSection.cpp
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "Connection.h"
|
||||
#include "Server.h"
|
||||
#include <iostream>
|
||||
#include "PolarSSL++/CryptoKey.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h> // For _mkdir()
|
||||
@ -471,7 +472,7 @@ bool cConnection::SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a
|
||||
|
||||
|
||||
|
||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer)
|
||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer)
|
||||
{
|
||||
DataLog(a_Data, a_Size, "Encrypting %d bytes to %s", a_Size, a_Peer);
|
||||
const Byte * Data = (const Byte *)a_Data;
|
||||
@ -495,7 +496,7 @@ bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryp
|
||||
|
||||
|
||||
|
||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
|
||||
bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer)
|
||||
{
|
||||
AString All;
|
||||
a_Data.ReadAll(All);
|
||||
@ -2899,7 +2900,7 @@ void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, c
|
||||
Byte SharedSecret[16];
|
||||
Byte EncryptedSecret[128];
|
||||
memset(SharedSecret, 0, sizeof(SharedSecret)); // Use all zeroes for the initial secret
|
||||
cPublicKey PubKey(a_ServerPublicKey);
|
||||
cCryptoKey PubKey(a_ServerPublicKey);
|
||||
int res = PubKey.Encrypt(SharedSecret, sizeof(SharedSecret), EncryptedSecret, sizeof(EncryptedSecret));
|
||||
if (res < 0)
|
||||
{
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "ByteBuffer.h"
|
||||
#include "OSSupport/Timer.h"
|
||||
#include "PolarSSL++/AesCfb128Decryptor.h"
|
||||
#include "PolarSSL++/AesCfb128Encryptor.h"
|
||||
|
||||
|
||||
|
||||
@ -66,8 +68,8 @@ protected:
|
||||
cByteBuffer m_ClientBuffer;
|
||||
cByteBuffer m_ServerBuffer;
|
||||
|
||||
cAESCFBDecryptor m_ServerDecryptor;
|
||||
cAESCFBEncryptor m_ServerEncryptor;
|
||||
cAesCfb128Decryptor m_ServerDecryptor;
|
||||
cAesCfb128Encryptor m_ServerEncryptor;
|
||||
|
||||
AString m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
|
||||
|
||||
@ -109,10 +111,10 @@ protected:
|
||||
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
|
||||
|
||||
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
||||
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer);
|
||||
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, const char * a_Data, size_t a_Size, const char * a_Peer);
|
||||
|
||||
/// Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false
|
||||
bool SendEncryptedData(SOCKET a_Socket, cAESCFBEncryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
|
||||
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
|
||||
|
||||
/// Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped
|
||||
bool DecodeClientsPackets(const char * a_Data, int a_Size);
|
||||
|
@ -216,6 +216,20 @@ typedef unsigned char Byte;
|
||||
// Pretty much the same as ASSERT() but stays in Release builds
|
||||
#define VERIFY( x ) ( !!(x) || ( LOGERROR("Verification failed: %s, file %s, line %i", #x, __FILE__, __LINE__ ), exit(1), 0 ) )
|
||||
|
||||
// Allow both Older versions of MSVC and newer versions of everything use a shared_ptr:
|
||||
// Note that we cannot typedef, because C++ doesn't allow (partial) templates to be typedeffed.
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||
// MSVC before 2010 doesn't have std::shared_ptr, but has std::tr1::shared_ptr, defined in <memory> included earlier
|
||||
#define SharedPtr std::tr1::shared_ptr
|
||||
#elif (defined(_MSC_VER) || (__cplusplus >= 201103L))
|
||||
// C++11 has std::shared_ptr in <memory>, included earlier
|
||||
#define SharedPtr std::shared_ptr
|
||||
#else
|
||||
// C++03 has std::tr1::shared_ptr in <tr1/memory>
|
||||
#include <tr1/memory>
|
||||
#define SharedPtr std::tr1::shared_ptr
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@ -232,12 +246,6 @@ public:
|
||||
|
||||
|
||||
|
||||
#include "../../src/Crypto.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define LOGERROR printf
|
||||
#define LOGINFO printf
|
||||
#define LOGWARNING printf
|
||||
|
@ -20,7 +20,7 @@ You need to set the server *not* to verify usernames ("online-mode=false" in ser
|
||||
|
||||
|
||||
ProtoProxy is not much dependent on the protocol - it will work with unknown packets, it just won't parse them into human-readable format.
|
||||
The latest protocol which has been tested is 1.6.1 (#73).
|
||||
The latest protocol which has been tested is 1.7.9 (#5).
|
||||
|
||||
|
||||
*/
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PolarSSL++/RsaPrivateKey.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@ -17,7 +19,7 @@
|
||||
class cServer
|
||||
{
|
||||
SOCKET m_ListenSocket;
|
||||
cRSAPrivateKey m_PrivateKey;
|
||||
cRsaPrivateKey m_PrivateKey;
|
||||
AString m_PublicKeyDER;
|
||||
short m_ConnectPort;
|
||||
|
||||
@ -27,7 +29,7 @@ public:
|
||||
int Init(short a_ListenPort, short a_ConnectPort);
|
||||
void Run(void);
|
||||
|
||||
cRSAPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
||||
cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
||||
const AString & GetPublicKeyDER (void) { return m_PublicKeyDER; }
|
||||
|
||||
short GetConnectPort(void) const { return m_ConnectPort; }
|
||||
|
529
docs/Generator.html
Normal file
@ -0,0 +1,529 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Generating terrain in MCServer</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Generating terrain in MCServer</h1>
|
||||
<p>This article explains the principles behind the terrain generator in MCServer. It is not strictly
|
||||
specific to MCServer, though, it can be viewed as a generic guide to various terrain-generating algorithms,
|
||||
with specific implementation notes regarding MCServer.</p>
|
||||
|
||||
<p>Contents:
|
||||
<ul>
|
||||
<li><a href="#preface">Preface: How it's done in real life</a></li>
|
||||
<li><a href="#expectedprops">Expected properties</a></li>
|
||||
<li><a href="#reversingflow">Reversing the flow</a></li>
|
||||
<li><a href="#composablegen">The ComposableGenerator pipeline</a></li>
|
||||
<li><a href="#coherentnoise">Using coherent noise</a></li>
|
||||
<li><a href="#biomegen">Generating biomes</a></li>
|
||||
<li><a href="#heightgen">Terrain height</a></li>
|
||||
<li><a href="#compositiongen">Terrain composition</a></li>
|
||||
<li><a href="#finishgen">Finishers</a></li>
|
||||
<li><a href="#makefaster">Making it all faster</a></li>
|
||||
<li><a href="#GPU">Executing on a GPU</a></li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="preface"><h2>Preface: How it's done in real life</h2></a>
|
||||
<p>The nature has many complicated geological, physical and biological processes working on all scales from
|
||||
microscopic to planet-wide scale, that have shaped the terrain into what we see today. The tectonic plates
|
||||
collide, push mountain ranges up and ocean trenches down. Erosion dulls the sharp shapes. Plantlife takes
|
||||
over to further change the overall look of the world.</p>
|
||||
|
||||
<p>Generally speaking, the processes take what's there and change it. Unlike computer generating, which
|
||||
usually creates a finished terrain from scratch, or maybe with only a few iterations. It would be unfeasible
|
||||
for software to emulate all the natural processes in enough detail to provide world generation for a game,
|
||||
mainly because in the nature everything interacts with everything. If a mountain range rises, it changes the
|
||||
way that the precipitation is carried by the wind to the lands beyond the mountains, thus changing the
|
||||
erosion rate there and the vegetation type. </p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="expectedprops"><h2>Expected properties</h2></a>
|
||||
<p>For a MineCraft-like game terrain generator we need the generator to have several properties:
|
||||
<ul>
|
||||
<li>The generator must be able to generate terrain in small chunks. This means it must be possible to
|
||||
generate each of the chunks separately, without dependencies on the neighboring chunks. Note that this
|
||||
doesn't mean chunks cannot coordinate together, it means that "a tree in one chunk cannot ask if there's
|
||||
a building in the neighbor chunk", simply because the neighbor chunk may not be generated yet.</li>
|
||||
<li>The generated chunk needs to be the same if re-generated. This property is not exactly required, but it
|
||||
makes available several techniques that wouldn't be possible otherwise.</li>
|
||||
<li>The generator needs to be reasonably fast. For a server application this means at least some 20 chunks
|
||||
per second for chunks close to each other, and 5 chunks per second for distant chunks. The reason for this
|
||||
distinction will be discussed later.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="reversingflow"><h2>Reversing the flow</h2></a>
|
||||
<p>As already mentioned, the nature works basically by generating raw terrain composition, then "applying"
|
||||
erosion, vegetation and finally this leads to biomes being formed. Let's now try a somewhat inverse
|
||||
approach: First generate biomes, then fit them with appropriate terrain, and finally cover in vegetation
|
||||
and all the other stuff.</p>
|
||||
|
||||
<p>Splitting the parts like this suddenly makes it possible to create a generator with the required
|
||||
properties. We can generate a reasonable biome map chunk-wise, independently of all the other data. Once we
|
||||
have the biomes, we can compose the terrain for the chunk by using the biome data for the chunk, and
|
||||
possibly even for neighboring chunks. Note that we're not breaking the first property, the biomes can be
|
||||
generated separately so a neighboring chunk's biome map can be generated without the need for the entire
|
||||
neighboring chunk to be present. Similarly, once we have the terrain composition for a chunk, we can
|
||||
generate all the vegetation and structures in it, and those can again use the terrain composition in
|
||||
neighboring chunks.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="composablegen"><h2>The ComposableGenerator pipeline</h2></a>
|
||||
<p>This leads us directly to the main pipeline that is used for generating terrain in MCServer. For
|
||||
technical reasons, the terrain composition step is further subdivided into Height generation and Composition
|
||||
generation, and the structures are really called Finishers. For each chunk the generator generates, in this
|
||||
sequence:
|
||||
<ul>
|
||||
<li>Biomes</li>
|
||||
<li>Terrain height</li>
|
||||
<li>Terrain composition</li>
|
||||
<li>Finishers</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<img src="img/biomes.jpg" />
|
||||
<img src="img/terrainheight.jpg" />
|
||||
<img src="img/terraincomposition.jpg" />
|
||||
<img src="img/finishers.jpg" />
|
||||
<p>The beautiful thing about this is that the individual components can be changed independently. You can
|
||||
have 5 biome generators and 3 height generators and you can let the users mix'n'match.
|
||||
</p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="coherentnoise"><h2>Using coherent noise for the generation</h2></a>
|
||||
<p>For a great tutorial on coherent noise, see the <a href="http://libnoise.sourceforge.net/">LibNoise
|
||||
documentation</a>.</p>
|
||||
<p>Coherent noise is a type of noise that has three important properties that we can use to our advantage:
|
||||
<ul>
|
||||
<li>The noise is smooth</li>
|
||||
<li>The noise is algorithmically generated, which means that the same data is generated when the same
|
||||
parameters are given to the noise functions.</li>
|
||||
<li>The noise can be seamlessly extended in any direction</li>
|
||||
</ul></p>
|
||||
|
||||
<p>We'll be mostly using Perlin noise in this article. It is the easiest one to visualise and use and is one
|
||||
of the most useful kinds of coherent noises. Here's an example of a Perlin noise generated in 2 dimensions:</p>
|
||||
<img src="img/perlin.jpg" />
|
||||
|
||||
<p>It comes only naturally that such a 2D noise can be used as a terrain height map directly:</p>
|
||||
<img src="img/perlinheightmap.jpg" />
|
||||
|
||||
<p>However, this is not the only use for this noise, and 2 dimensions is not the limit - this noise can be
|
||||
generated for any number of dimensions.</p>
|
||||
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="biomegen"><h2>Generating biomes</h2></a>
|
||||
<p>The easiest way to generate biomes is to not generate them at all - simply assign a single constant biome
|
||||
to everywhere. And indeed there are times when this kind of "generator" is useful - for the MineCraft's Flat
|
||||
world type, or for testing purposes, or for tematic maps. In MCServer, this is exactly what the Constant
|
||||
biome generator does.</p>
|
||||
|
||||
<p>Of course, there are more interesting test scenarios for which multiple biomes must be generated as easy
|
||||
as possible. For these special needs, there's a CheckerBoard biome generator. As the name suggests, it
|
||||
generates a grid of alternating biomes.</p>
|
||||
|
||||
<h3>Voronoi diagram</h3>
|
||||
<p>Those two generators were more of a technicality, we need to make something more interesting if we're
|
||||
going for a natural look. The Voronoi generator is the first step towards such a change. Recall that a
|
||||
<a href="http://en.wikipedia.org/wiki/Voronoi_diagram">Voronoi diagram</a> is a construct that creates a
|
||||
set of areas where each point in an area is closer to the appropriate seed of the area than the seeds of any
|
||||
other area:</p>
|
||||
<img src="img/voronoi.png" />
|
||||
|
||||
<p>To generate biomes using this approach, you select random "seeds", assign a biome to each one, and then
|
||||
for each "column" of the world you find the seed that is the nearest to that column, and use that seed's
|
||||
biome.</p>
|
||||
|
||||
<p>The overall shape of a Voronoi diagram is governed by the placement of the seeds. In extreme cases, a
|
||||
seed could affect the entire diagram, which is what we don't want - we need our locality, so that we can
|
||||
generate a chunk's worth of biome data. We also don't want the too much irregular diagrams that are produced
|
||||
when the seeds are in small clusters. We need our seeds to come in random, yet somewhat uniform fashion.</p>
|
||||
|
||||
<p>Luckily, we have just the tool: Grid with jitter. Originally used in antialiasing techniques, they can be
|
||||
successfully applied as a source of the seeds for a Voronoi diagram. Simply take a regular 2D grid of seeds
|
||||
with the grid distance being N, and move each seed along the X and Y axis by a random distance, usually in
|
||||
the range [-N / 2, +N / 2]:</p>
|
||||
<img src="img/jittergrid.jpg" />
|
||||
|
||||
<p>Such a grid is the ideal seed source for a Voronoi biome generator, because not
|
||||
only are the Voronoi cells "reasonable", but the seed placement's effect on the diagram is localized - each
|
||||
pixel in the diagram depends on at most 4 x 4 seeds around it. In the following picture, the seed for the
|
||||
requested point (blue) must be within the indicated circle. Even the second-nearest seed, which we will need
|
||||
later, is inside that circle.</p>
|
||||
<img src="img/jittergridlocality.jpg" />
|
||||
|
||||
<p>Calculating the jitter for each cell can be done easily by using a 2D Perlin noise for each coord. We
|
||||
calculate the noise's value at [X, Z], which gives us a number in the range [-1; 1]. We then multiply the
|
||||
number by N / 2, this gives us the required range of [-N / 2, +N / 2]. Adding this number to the X coord
|
||||
gives us the seed's X position. We use another Perlin noise and the same calculation for the Z coord of the
|
||||
seed.</p>
|
||||
|
||||
<p>Here's an example of a biome map generated using the Voronoi + jitter grid, as implemented by the Voronoi
|
||||
biome generator in MCServer:</p>
|
||||
<img src="img/voronoijitterbiomes.png" />
|
||||
|
||||
<h3>Distorted Voronoi</h3>
|
||||
<p>The biomes are starting to look interesting, but now they have straight-line borders, which looks rather
|
||||
weird and the players will most likely notice very soon. We need to somehow distort the borders to make them
|
||||
look more natural. By far the easiest way to achieve that is to use a little trick: When the generator is
|
||||
asked for the biome at column [X, Z], instead of calculating the Voronoi biome for column [X, Z], we first
|
||||
calculate a random offset for each coord, and add it to the coordinates. So the generator actually responds
|
||||
with the biome for [X + rndX, Z + rndZ].</p>
|
||||
|
||||
<p>In order to keep the property that generating for the second time gives us the same result, we need the
|
||||
"random offset" to be replicatable - same output for the same input. This is where we use yet another Perlin
|
||||
noise - just like with the jitter for the Voronoi grid, we add a value from a separate noise to each
|
||||
coordinate before sending the coordinates down to the Voronoi generator:</p>
|
||||
<code>
|
||||
DistortedVoronoiBiome(X, Z) := VoronoiBiome(X + PerlinX(X, Z), Z + PerlinZ(X, Z))
|
||||
</code>
|
||||
|
||||
<p>The following image shows the effects of the change, as generated by MCServer's DistortedVoronoi biome
|
||||
generator. It is actually using the very same Voronoi map as the previous image, the only change has been
|
||||
the addition of the distortion:</p>
|
||||
<img src="img/distortedvoronoibiomes.png" />
|
||||
|
||||
<p>As you can see, this already looks reasonable enough, it could be considered natural biomes, if it
|
||||
weren't for several drawbacks:
|
||||
<ul>
|
||||
<li>There's no way to limit the neighbors. A desert biome can neighbor a tundra biome. </li>
|
||||
<li>All the biomes are considered equal. There's no way to make oceans larger. A mushroom biome is
|
||||
generated right next to other land biomes.</li>
|
||||
</ul></p>
|
||||
|
||||
<h3>Adding relativity</h3>
|
||||
<p>Our next goal is to remove the first defect of the distorted Voronoi generator: unrelated biomes
|
||||
generating next to each other. It is highly unlikely to find a jungle biome next to a desert biome, so we
|
||||
want to have as few of those borders as possible. We could further improve on the selection of
|
||||
biome-to-seed in the Voronoi generator. Or we can try a completely different idea altogether.</p>
|
||||
|
||||
<p>Recall how we talked about the nature, where the biomes are formed by the specific conditions of a place.
|
||||
What if we could make a similar dependency, but without the terrain? It turns out this is possible rather
|
||||
easily - instead of depending on the terrain, we choose two completely artificial measures. Let's call them
|
||||
Temperature and Humidity. If we knew the temperature of the place, we know what set of biomes are possible
|
||||
for such temperatures - we won't place deserts in the cold and tundra in the hot anymore. Similarly, the
|
||||
humidity will help us sort out the desert vs jungle issue. But how do we get a temperature and humidity?
|
||||
Once again, the Perlin noise comes to the rescue. We can use a simple 2D Perlin noise as the temperature
|
||||
map, and another one as the humidity map.</p>
|
||||
|
||||
<p>What we need next is a decision of what biome to generate in certain temperature and humidity
|
||||
combinations. The fastest way for a computer is to have a 2D array, where the temperature is one dimension
|
||||
and humidity the other, and the values in the array specify the biome to generate:</p>
|
||||
<img src="img/temperaturehumiditydecisionsimple.jpg" />
|
||||
|
||||
<p>We can even "misuse" the above diagram to include the hill variants of the biomes and have those hills
|
||||
neighbor each other properly, simply by declaring some of the decision diagram's parts as hills:</p>
|
||||
<img src="img/temperaturehumiditydecisionhills.jpg" />
|
||||
|
||||
<p>The problem with this approach is that there are biomes that should not depend on temperature or
|
||||
humidity, they generate across all of their values. Biomes like Oceans, Rivers and Mushroom. We could
|
||||
either add them somewhere into the decision diagram, or we can make the generator use a multi-step decision:
|
||||
<ul>
|
||||
<li>Decide whether the point is in the ocean, land or mushroom</li>
|
||||
<li>If it's land, decide if it's real land or river.</li>
|
||||
<li>If it's real land, use a TemperatureHumidity approach to generate land-biomes</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>This is the approach implemented in MCServer's MultiStepMap biome generator. It generates biome maps like
|
||||
this:</p>
|
||||
<img src="img/multistepmapbiomes.png" />
|
||||
|
||||
<p>To decide whether the point is in the ocean, land or mushroom, the generator first chooses seeds in a grid
|
||||
that will be later fed to a DistortedVoronoi algorithm, the seeds get the "ocean" and "land" values. Then it
|
||||
considers all the "ocean" seeds that are surrounded by 8 other "ocean" seeds and turns a random few of them
|
||||
into "mushroom". This special seed processing makes the mushroom biomes mostly surrounded by ocean. The
|
||||
following image shows an example seeds grid that the generator might consider, only the two framed cells are
|
||||
allowed to change into mushroom. L = land, O = ocean:</p>
|
||||
<img src="img/multistepmapgrid.jpg" />
|
||||
|
||||
<p>Next, the generator calculates the DistortedVoronoi for the seeds. For the areas that are calculated as
|
||||
mushroom, the distance to the nearest-seed is used to further shrink the mushroom biome and then to
|
||||
distinguish between mushroom and mushroom-shore (image depicts a Voronoi cell for illustration purposes, it
|
||||
works similarly with DistortedVoronoi). O = ocean, M = mushroom, MS = mushroom shore:</p>
|
||||
<img src="img/multistepmapdistance.jpg" />
|
||||
|
||||
<a name="perlinrivers">
|
||||
<p>The rivers are added only to the areas that have been previously marked as land. A simple 2D Perlin noise
|
||||
is used as the base, where its value is between 0 and a configured threshold value, a river is created. This
|
||||
creates the rivers in a closed-loop-like shapes, occasionally splitting two branches off:</p>
|
||||
<img src="img/perlinrivers1.jpg" />
|
||||
<img src="img/perlinrivers2.jpg" />
|
||||
<img src="img/perlinrivers3.jpg" />
|
||||
</a>
|
||||
|
||||
<p>For the leftover land biomes, the two Perlin noises, representing temperature and humidity, are used to
|
||||
generate the biomes, as described earlier. Additionally, the temperature map is used to turn the Ocean biome
|
||||
into FrozenOcean, and the River biome into FrozenRiver, wherever the temperature drops below a threshold.</p>
|
||||
|
||||
<h3>Two-level Voronoi</h3>
|
||||
<p>The 1.7 MineCraft update brought a completely new terrain generation, which has sparked renewed interest
|
||||
in the biome generation. A new, potentially simpler way of generating biomes was found, the two-level
|
||||
DistortedVoronoi generator.</p>
|
||||
|
||||
<p>The main idea behind it all is that we create large areas of similar biomes. There are several groups of
|
||||
related biomes that can be generated near each other: Desert biomes, Ice biomes, Forest biomes, Mesa biomes.
|
||||
Technically, the Ocean biomes were added as yet another group, so that the oceans will generate in
|
||||
approximately the size of the larger areas, too.</p>
|
||||
|
||||
<p>For each column a DistortedVoronoi is used to select, which large area to use. This in turn results in
|
||||
the list of biomes from which to choose. Another DistortedVoronoi, this time with a smaller grid size, is
|
||||
used to select one biome out of that list. Additionally, the smaller DistortedVoronoi calculates not only
|
||||
the nearest seed's distance, but also the distance to the second-nearest seed; the ratio between these two
|
||||
is used as an indicator whether the column is in the "inside" or on the "outskirt" of the smaller Voronoi
|
||||
cell. This allows us to give certain biomes an "edge" biome - the Mushroom biome has a MushroomShore edge,
|
||||
the ExtremeHills biome have an ExtremeHillsEdge biome on the edge, etc.</p>
|
||||
|
||||
<p>The images below illustrate the process with regular Voronoi diagrams, for clarity purposes. The real
|
||||
generator uses distortion before querying the small areas.</p>
|
||||
<img src="img/twolevellargeareas.jpg" /><br />
|
||||
<img src="img/twolevelsmallgrid.jpg" /><br />
|
||||
<img src="img/twolevelsmallareas.jpg" /><br />
|
||||
|
||||
<p>The following image shows an example output of a TwoLevel biome generator in MCServer:</p>
|
||||
<img src="img/twolevelbiomes.png" />
|
||||
|
||||
<p>Note that rivers are currently not implemented in this generator in MCServer, but they could be added
|
||||
using the same approach as in MultiStepMap - by using a thresholded 2D Perlin noise.</p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="heightgen"><h2>Terrain height</h2></a>
|
||||
<p>As with biomes, the easiest way to generate terrain height is not generating at all - assigning a constant
|
||||
height value to all columns. This is again useful either for internal tests, and for worlds like MineCraft's
|
||||
Flat world.</p>
|
||||
|
||||
<p>For a somewhat more realistic landscape, we will employ the good old 2D Perlin noise. We can use it
|
||||
directly as a heightmap - each value we get from the noise is stretched into the desired range (usually from
|
||||
40 to 120 blocks for regular MineCraft worlds) and used as the height value. However, this doesn't play too
|
||||
well with the biomes we've just generated. If the biome says "ocean" and the Perlin noise says "mountain",
|
||||
the end result will be unpleasant.</p>
|
||||
|
||||
<p>So we want a height generator that is biome-aware. The easiest way of doing this is to have a separate
|
||||
generator for each biome. Simply use the biome map to select which generator to use, then ask the appropriate
|
||||
generator for the height value. Again, this doesn't work too well - imagine an ExtremeHills biome right next
|
||||
to an Ocean biome. If no extra care is taken, the border between these two will be a high wall. The following
|
||||
image shows a 2D representation (for simplification purposes) of the problem:</p>
|
||||
<img src="img/biomeheights.jpg" />
|
||||
|
||||
<p>This requires some further processing. What we need is for the terrain height to be dependent not only on
|
||||
the immediate biome for that column, but also on the close surroundings of the column. This is exactly the
|
||||
kind of task that averaging is designed for. If we take the area of 9x9 biomes centered around the queried
|
||||
column, generate height for each of the biomes therein, sum them up and divide by 81 (the number of biomes
|
||||
summed), we will be effectively making a 9-long running average over the terrain, and all the borders will
|
||||
suddenly become smooth. The following image shows the situation from the previous paragraph after applying
|
||||
the averaging process: </p>
|
||||
<img src="img/biomeheightsavg.jpg" />
|
||||
|
||||
<p>The approach used in MCServer's Biomal generator is based on this idea, with two slight modifications.
|
||||
Instead of using a separate generator for each biome, one generator is used with a different set of input
|
||||
parameters for each biomes. These input parameters modify the overall amplitude and frequency of the Perlin
|
||||
noise that the generator produces, thus modifying the final terrain with regards to biomes. Additionally, the
|
||||
averaging process is weighted - columns closer to the queried column get a more powerful weight in the sum
|
||||
than the columns further away. The following image shows the output of MCServer's Biomal terrain height
|
||||
generator (each block type represents a different biome - ocean in the front (stone), plains and ice plains
|
||||
behind it (lapis, whitewool), extreme hills back right (soulsand), desert hills back left (mossy
|
||||
cobble)):</p>
|
||||
<a name="biomalheights"><img src="img/biomalheights.jpg" /></a>
|
||||
|
||||
<p>One key observation about this whole approach is that in order for it to work, the biomes must be
|
||||
available for columns outside the currently generated chunk, otherwise the columns at the chunk's edge would
|
||||
not be able to properly average their height. This requirement can be fulfilled only by biome generators that
|
||||
adhere to the second <a href="#expectedproperties">Expected property</a> - that re-generating will produce
|
||||
the same data. If the biome generator returned different data for the same chunk each time it was invoked, it
|
||||
would become impossible to apply the averaging.</p>
|
||||
|
||||
<p>(TODO: height with variations (N/A in MCS yet)</p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="compositiongen"><h2>Terrain composition</h2></a>
|
||||
<p>As with the other generators, the composition generator category has its easy and debugging items, too.
|
||||
There's the "special" composition of "all the blocks are the same type", which fills the entire column, from
|
||||
the bottom to the height, with a single blocktype. This generator is useful when testing the generators in
|
||||
the other categories, to speed up the generation by leaving out unnecessary calculations. Another special
|
||||
compositor is a similar one, that fills all blocks with the same type, but the type varies for each biome.
|
||||
This way it's easy to see the generated biomes and possibly the heights for those biomes, as shown in the
|
||||
previous section on the <a href="#biomalheights">height averaging screenshot</a>.</p>
|
||||
|
||||
<p>For a natural look, we need to put together a more complicated algorithm. The standard set forth in
|
||||
MineCraft is that the top of the world is covered in grass, then there are a few blocks of dirt and finally
|
||||
stone. This basic layout is then varied for different biomes - deserts have sand and sandstone instead of the
|
||||
grass and dirt layer. Mushroom biomes have mycelium in place of the grass. This per-biome dependency is
|
||||
trivial to implement - when compositing, simply use the appropriate layout for the column's biome.</p>
|
||||
|
||||
<p>The next change concerns oceans. The generated heightmap doesn't include any waterlevel indication
|
||||
whatsoever. So it's up to the terrain compositor to actually decide where to place water. We do this by
|
||||
configuration - simply have a value in the config file specifying the sealevel height. The compositor then
|
||||
has to add water above any column which has a height lower than that. Additionally, the water needs to
|
||||
override per-biome layout selection - we don't want grass blocks to generate under water when the terrain
|
||||
height in the plains biome drops below the sealevel accidentally.</p>
|
||||
|
||||
<p>The final feature in the compositor is the decision between multiple composition layouts within a single
|
||||
biome. A megataiga biome contains patches of non-grass dirt and podzol blocks, and the ocean floor can be
|
||||
made of dirt, gravel, sand or clay. A simple 2D Perlin noise can be used to select the layout to use for a
|
||||
specific column - simply threshold the noise's value by as many thresholds as there are layout variations,
|
||||
and use the layout corresponding to the threshold:</p>
|
||||
<img src="img/perlincompositor1.jpg" />
|
||||
<img src="img/perlincompositor2.jpg" />
|
||||
<img src="img/perlincompositor3.jpg" />
|
||||
|
||||
<h3>Nether composition</h3>
|
||||
<p>So far we've been discussing only the Overworld generator. But MineCraft contains more than that. The
|
||||
Nether has a completely different look and feel, and quite different processes are required to generate that.
|
||||
Recall that MineCraft's Nether is 128 blocks high, with bedrock both at the top and the bottom. Between these
|
||||
two, the terrain looks more like a cavern than a surface. Not surprisingly, the Nether doesn't need a
|
||||
complicated height generator, it can use the flat height. However, the terrain composition must take an
|
||||
altogether different approach.</p>
|
||||
|
||||
<p>The very first idea is to use the Perlin noise, but generate it in 3D, rather than 2D. Then, for each
|
||||
block, evaluate the noise value, if below 0, make it air, if not, make it netherrack.
|
||||
|
||||
<p>To make it so that the bedrock at the top and at the bottom is never revealed, we can add a value
|
||||
increasing the more the Y coord gets towards the bottom or the top. This way the thresholding then guarantees
|
||||
that there will be no air anywhere near the bedrock.</p>
|
||||
|
||||
<p>(TODO)</p>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="finishgen"><h2>Finishers</h2></a>
|
||||
<p>Finishers are a vast category of various additions to the terrain generator. They range from very easy
|
||||
ones, such as generating snow on top of the terrain in cold biomes, through medium ones, such as growing
|
||||
patches of flowers, complicated ones, such as placing trees and generating caves, all the way to very
|
||||
complicated ones such as villages and nether fortresses. There is no formal distinction between all these
|
||||
"categories", the only thing they have in common is that they take a chunk of blocks and modify it in some
|
||||
way.</p>
|
||||
|
||||
<h3>Snow</h3>
|
||||
<p>Snow is probably the easiest of the finishers. It generates a block of snow on top of each block that is
|
||||
on top of the terrain and is not marked as non-snowable. It checks the chunk's heightmap to determine the top
|
||||
block, then checks whether the block supports snow on its top. Rails, levers and tall grass don't support
|
||||
snow, for example.</p>
|
||||
|
||||
<h3>Ice</h3>
|
||||
<p>Another example of an easy finisher. This scans through the world and turn each water block on the surface
|
||||
into an ice block if the biome is cold. This means that any water block that is under any kind of other
|
||||
block, such as under a tree's leaves, will still stay water. Thus an additional improvement could be made by
|
||||
scanning down from the surface block through blocks that we deem as non-surface, such as leaves, torches,
|
||||
ladders, fences etc. Note that MCServer currently implements only the easy solution.</p>
|
||||
|
||||
<h3>Bottom lava</h3>
|
||||
<p>Most worlds in MineCraft have lava lakes at their bottom. Generating these is pretty straightforward: Use
|
||||
the user-configured depth and replace all the air blocks below this depth with lava blocks. Note however,
|
||||
that this makes this generator dependent on the order in which the finishers are applied. If the mineshafts
|
||||
generate before bottom lava, the mineshafts that are below the lava level will get filled with lava. On the
|
||||
other hand, if bottom lava is generated before the mineshafts, it is possible for a mineshaft to "drill
|
||||
through" a lake of lava. MCServer doesn't try to solve this and instead lets the admin choose whichever they
|
||||
prefer.</p>
|
||||
|
||||
<h3>Specific foliage</h3>
|
||||
<p>There are generators for specific kinds of foliage. The dead bushes in the desert biome and lilypads in
|
||||
the swamp biome both share the same generating pattern. They are both specific to a single biome and they
|
||||
both require a specific block underneath them in order to generate. Their implementation is simple: pick
|
||||
several random columns in the chunk. If the column is of the correct biome and has the correct top block,
|
||||
add the foliage block on top.</p>
|
||||
|
||||
<p>In order to generate the same set of coordinates when the chunk is re-generated, we use the Perlin noise's
|
||||
basis functions (the ones providing the random values for Perlin cell vertices). These basically work as a
|
||||
hash function for the coorinates - the same input coordinates generate the same output value. We use the
|
||||
chunk's coordinates as two of the coords, and the iteration number as the third coordinate, to generate a
|
||||
random number. We then check the biome and the top block at those coordinates, if they allow, we generate the
|
||||
foliage block on top.</p>
|
||||
|
||||
<p>Another example of specific foliage is the tall grass in the plains biome. There are quite a lot of these
|
||||
tall grass blocks, it would be inefficient to generate them using the random-coords approach described above.
|
||||
Instead, we will use a 2D Perlin noise again, with a threshold defining where to put the grass and where
|
||||
not.</p>
|
||||
|
||||
<h3>Small foliage</h3>
|
||||
<p>For the flowers, grass, mushrooms in caves etc. we want to use a slightly different algorithm. These
|
||||
foliage blocks are customarily generated in small "clumps" - there are several blocks of the same type near
|
||||
together. To generate these, we first select random coords, using the coord hash functions, for a center of a
|
||||
clump. Then we select the type of block to generate. Finally, we loop over adding a random (coord hash)
|
||||
number to the clump center coords to get the block where to generate the foliage block:</p>
|
||||
<img src="img/smallfoliageclumps.jpg" />
|
||||
|
||||
<p>In order to make the clump more "round" and "centered", we want the offsets to be closer to the clump
|
||||
center more often. This is done using a thing called Gaussian function distribution. Instead of having each
|
||||
random number generate with the same probability, we want higher probability for the numbers around zero,
|
||||
like this:</p>
|
||||
<img src="img/gaussprobability.jpg" />
|
||||
|
||||
<p>Instead of doing complicated calculations to match this shape exactly, we will use a much easier shape.
|
||||
By adding together two random numbers in the same range, we get the probability distribution that has a
|
||||
"roof" shape, enough for our needs:</p>
|
||||
<img src="img/roofprobability.jpg" />
|
||||
|
||||
<p>(For the curious, there is a proof that adding together infinitely many uniform-distributed random numbers
|
||||
produces random numbers with the Gaussian distribution.)</p>
|
||||
|
||||
<p>This scheme can be used to produce clumps of flowers, when we select the 2D coords of the clump center on
|
||||
the top surface of the terrain. We simply generate the 2D coords of the foliage blocks and use the terrain
|
||||
height to find the third coord. If we want to generate clumps of mushrooms in the caves, however, we need to
|
||||
generate the clump center coords in 3D and either use 3 offsets for the mushrooms, or use 2 offsets plus
|
||||
searching for the closest opening Y-wise in the terrain.</p>
|
||||
|
||||
<p>Note that the clumps generated by this scheme may overlap several chunks. Therefore it's crucial to
|
||||
actually check the surrounding chunks if their clumps overlap into the currently generated chunk, and apply
|
||||
those as well, otherwise there will be visible cuts in the foliage along the chunks borders.</p>
|
||||
|
||||
<h3>Springs</h3>
|
||||
<p>Water and lava springs are essential for making the underground quite a lot more interesting. They are
|
||||
rather easy to generate, but a bit more difficult to get right. Generating simply means that a few random
|
||||
locations (obtained by our familiar coord hashing) are checked and if the block type in there is stone. Then
|
||||
we see all the horizontal neighbors of the block, plus the block underneath. If all of them except one are
|
||||
stone, and the one left is air, our block is suitable for turning into a spring. If there were more air
|
||||
neighbors, the spring would look somewhat unnatural; if there were no air neighbors, the spring won't flow
|
||||
anywhere, so it would be rather useless.</p>
|
||||
|
||||
<p>The difficult part about springs is the amount of them to generate. There should be a few springs on the
|
||||
surface, perhaps a bit more in the mountaineous biomes. There should be quite a few more springs underground,
|
||||
but there should definitely be more water springs than lava springs in the upper levels of the terrain, while
|
||||
there should be more lava springs and almost no water springs near the bottom. To accomodate this, the
|
||||
MCServer team has made a tool that scanned through MineCraft's terrain and counted the amount of both types
|
||||
of springs in relation to their height. Two curves have been found for the distribution of each type of the
|
||||
spring:</p>
|
||||
<img src="http://mc-server.xoft.cz/img/vanilla_springs_huge.png" />
|
||||
|
||||
<p>MCServer uses an approximation of the above curves to choose the height at which to generate the
|
||||
spring.</p>
|
||||
|
||||
<!--
|
||||
<h3>Caves</h3>
|
||||
<p>Caves are definitely one of the main things people notice about MineCraft terrain. There are quite a lot
|
||||
of different algorithms available to generate terrain with caves.
|
||||
-->
|
||||
|
||||
<hr />
|
||||
|
||||
<a name="makefaster"><h2>Making it all faster</h2></a>
|
||||
<p>(TODO)</p>
|
||||
|
||||
<a name="GPU"><h2>Executing on a GPU</h2></a>
|
||||
<p>Much of the terain generation consists of doing the same thing for every single column or block in a chunk. This
|
||||
sort of computation is much faster on a GPU as GPUs are massively parallel. High end GPUs can execute up to 30,000
|
||||
threads simultaneously, which would allow them to generate every block in half a chunk in parallel or every column
|
||||
in over 100 chunks in parallel. A naive comparison suggests that a 800MHz GPU with 15,000 threads can execute parallel
|
||||
code 250 times faster than a 3GHz CPU with 128 bit SIMD. Obviously we want to harness that power.</p>
|
||||
</body>
|
||||
</html>
|
BIN
docs/img/biomalheights.jpg
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
docs/img/biomeheights.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/img/biomeheightsavg.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/img/biomes.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
docs/img/distortedvoronoibiomes.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
docs/img/finishers.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
docs/img/gaussprobability.jpg
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
docs/img/jittergrid.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/img/jittergridlocality.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/img/multistepmapbiomes.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/img/multistepmapdistance.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/img/multistepmapgrid.jpg
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
docs/img/perlin.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/perlincompositor1.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/img/perlincompositor2.jpg
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
docs/img/perlincompositor3.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
docs/img/perlinheightmap.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
docs/img/perlinrivers1.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
docs/img/perlinrivers2.jpg
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
docs/img/perlinrivers3.jpg
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
docs/img/roofprobability.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/img/smallfoliageclumps.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
docs/img/temperaturehumiditydecisionhills.jpg
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
docs/img/temperaturehumiditydecisionsimple.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/img/terraincomposition.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/img/terrainheight.jpg
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/img/twolevelbiomes.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
docs/img/twolevellargeareas.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
docs/img/twolevelsmallareas.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
docs/img/twolevelsmallgrid.jpg
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
docs/img/voronoi.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
docs/img/voronoijitterbiomes.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
160
lib/cmake-coverage/CodeCoverage.cmake
Normal file
@ -0,0 +1,160 @@
|
||||
#
|
||||
# 2012-01-31, Lars Bilke
|
||||
# - Enable Code Coverage
|
||||
#
|
||||
# 2013-09-17, Joakim Söderberg
|
||||
# - Added support for Clang.
|
||||
# - Some additional usage instructions.
|
||||
#
|
||||
# USAGE:
|
||||
# 1. Copy this file into your cmake modules path.
|
||||
#
|
||||
# 2. Add the following line to your CMakeLists.txt:
|
||||
# INCLUDE(CodeCoverage)
|
||||
#
|
||||
# 3. Set compiler flags to turn off optimization and enable coverage:
|
||||
# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
|
||||
#
|
||||
# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target
|
||||
# which runs your test executable and produces a lcov code coverage report:
|
||||
# Example:
|
||||
# SETUP_TARGET_FOR_COVERAGE(
|
||||
# my_coverage_target # Name for custom target.
|
||||
# test_driver # Name of the test driver executable that runs the tests.
|
||||
# # NOTE! This should always have a ZERO as exit code
|
||||
# # otherwise the coverage generation will not complete.
|
||||
# coverage # Name of output directory.
|
||||
# )
|
||||
#
|
||||
# 4. Build a Debug build:
|
||||
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
# make
|
||||
# make my_coverage_target
|
||||
#
|
||||
#
|
||||
|
||||
# Check prereqs
|
||||
FIND_PROGRAM( GCOV_PATH gcov )
|
||||
FIND_PROGRAM( LCOV_PATH lcov )
|
||||
FIND_PROGRAM( GENHTML_PATH genhtml )
|
||||
FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests)
|
||||
|
||||
IF(NOT GCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "gcov not found! Aborting...")
|
||||
ENDIF() # NOT GCOV_PATH
|
||||
|
||||
IF(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||
# Clang version 3.0.0 and greater now supports gcov as well.
|
||||
MESSAGE(WARNING "Compiler is not GNU gcc! Clang Version 3.0.0 and greater supports gcov as well, but older versions don't.")
|
||||
|
||||
IF(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
|
||||
ENDIF()
|
||||
ENDIF() # NOT CMAKE_COMPILER_IS_GNUCXX
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_COVERAGE
|
||||
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||
FORCE )
|
||||
SET(CMAKE_C_FLAGS_COVERAGE
|
||||
"-g -O0 --coverage -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||
FORCE )
|
||||
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||
FORCE )
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||
""
|
||||
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||
FORCE )
|
||||
MARK_AS_ADVANCED(
|
||||
CMAKE_CXX_FLAGS_COVERAGE
|
||||
CMAKE_C_FLAGS_COVERAGE
|
||||
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||
|
||||
IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage"))
|
||||
MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" )
|
||||
ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug"
|
||||
|
||||
|
||||
# Param _targetname The name of new the custom make target
|
||||
# Param _testrunner The name of the target which runs the tests.
|
||||
# MUST return ZERO always, even on errors.
|
||||
# If not, no coverage report will be created!
|
||||
# Param _outputname lcov output is generated as _outputname.info
|
||||
# HTML report is generated in _outputname/index.html
|
||||
# Optional fourth parameter is passed as arguments to _testrunner
|
||||
# Pass them in list form, e.g.: "-j;2" for -j 2
|
||||
FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)
|
||||
|
||||
IF(NOT LCOV_PATH)
|
||||
MESSAGE(FATAL_ERROR "lcov not found! Aborting...")
|
||||
ENDIF() # NOT LCOV_PATH
|
||||
|
||||
IF(NOT GENHTML_PATH)
|
||||
MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
|
||||
ENDIF() # NOT GENHTML_PATH
|
||||
|
||||
# Setup target
|
||||
ADD_CUSTOM_TARGET(${_targetname}
|
||||
|
||||
# Cleanup lcov
|
||||
${LCOV_PATH} --directory . --zerocounters
|
||||
|
||||
# Run tests
|
||||
COMMAND ${_testrunner} ${ARGV3}
|
||||
|
||||
# Capturing lcov counters and generating report
|
||||
COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info
|
||||
COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'tests/*' '/usr/*' --output-file ${_outputname}.info.cleaned
|
||||
COMMAND ${GENHTML_PATH} -o ${_outputname} ${_outputname}.info.cleaned
|
||||
COMMAND ${CMAKE_COMMAND} -E remove ${_outputname}.info ${_outputname}.info.cleaned
|
||||
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report."
|
||||
)
|
||||
|
||||
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE
|
||||
|
||||
# Param _targetname The name of new the custom make target
|
||||
# Param _testrunner The name of the target which runs the tests
|
||||
# Param _outputname cobertura output is generated as _outputname.xml
|
||||
# Optional fourth parameter is passed as arguments to _testrunner
|
||||
# Pass them in list form, e.g.: "-j;2" for -j 2
|
||||
FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname)
|
||||
|
||||
IF(NOT PYTHON_EXECUTABLE)
|
||||
MESSAGE(FATAL_ERROR "Python not found! Aborting...")
|
||||
ENDIF() # NOT PYTHON_EXECUTABLE
|
||||
|
||||
IF(NOT GCOVR_PATH)
|
||||
MESSAGE(FATAL_ERROR "gcovr not found! Aborting...")
|
||||
ENDIF() # NOT GCOVR_PATH
|
||||
|
||||
ADD_CUSTOM_TARGET(${_targetname}
|
||||
|
||||
# Run tests
|
||||
${_testrunner} ${ARGV3}
|
||||
|
||||
# Running gcovr
|
||||
COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||
)
|
||||
|
||||
# Show info where to find the report
|
||||
ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD
|
||||
COMMAND ;
|
||||
COMMENT "Cobertura code coverage report saved in ${_outputname}.xml."
|
||||
)
|
||||
|
||||
ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA
|
23
lib/cmake-coverage/LICENSE
Normal file
@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
@ -243,7 +243,7 @@ int cIniFile::FindKey(const AString & a_KeyName) const
|
||||
{
|
||||
if (CheckCase(names[keyID]) == CaseKeyName)
|
||||
{
|
||||
return keyID;
|
||||
return (int)keyID;
|
||||
}
|
||||
}
|
||||
return noID;
|
||||
@ -279,7 +279,7 @@ int cIniFile::AddKeyName(const AString & keyname)
|
||||
{
|
||||
names.resize(names.size() + 1, keyname);
|
||||
keys.resize(keys.size() + 1);
|
||||
return names.size() - 1;
|
||||
return (int)names.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -447,6 +447,15 @@ bool cIniFile::SetValueI(const AString & a_KeyName, const AString & a_ValueName,
|
||||
|
||||
|
||||
|
||||
bool cIniFile::SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists)
|
||||
{
|
||||
return SetValue(a_Keyname, a_ValueName, Printf("%lld", a_Value), a_CreateIfNotExists);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cIniFile::SetValueF(const AString & a_KeyName, const AString & a_ValueName, double const a_Value, const bool a_CreateIfNotExists)
|
||||
{
|
||||
return SetValue(a_KeyName, a_ValueName, Printf("%f", a_Value), a_CreateIfNotExists);
|
||||
@ -571,6 +580,24 @@ int cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, c
|
||||
|
||||
|
||||
|
||||
Int64 cIniFile::GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue)
|
||||
{
|
||||
AString Data;
|
||||
Printf(Data, "%lld", defValue);
|
||||
AString resultstring = GetValueSet(keyname, valuename, Data);
|
||||
Int64 result = defValue;
|
||||
#ifdef _WIN32
|
||||
sscanf_s(resultstring.c_str(), "%lld", &result);
|
||||
#else
|
||||
sscanf(resultstring.c_str(), "%lld", &result);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cIniFile::DeleteValueByID(const int keyID, const int valueID)
|
||||
{
|
||||
if ((keyID < (int)keys.size()) && (valueID < (int)keys[keyID].names.size()))
|
||||
@ -683,7 +710,7 @@ int cIniFile::GetNumKeyComments(const int keyID) const
|
||||
{
|
||||
if (keyID < (int)keys.size())
|
||||
{
|
||||
return keys[keyID].comments.size();
|
||||
return (int)keys[keyID].comments.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ public:
|
||||
AString GetValueSet (const AString & keyname, const AString & valuename, const AString & defValue = "");
|
||||
double GetValueSetF(const AString & keyname, const AString & valuename, const double defValue = 0.0);
|
||||
int GetValueSetI(const AString & keyname, const AString & valuename, const int defValue = 0);
|
||||
Int64 GetValueSetI(const AString & keyname, const AString & valuename, const Int64 defValue = 0);
|
||||
bool GetValueSetB(const AString & keyname, const AString & valuename, const bool defValue = false)
|
||||
{
|
||||
return (GetValueSetI(keyname, valuename, defValue ? 1 : 0) != 0);
|
||||
@ -141,6 +142,7 @@ public:
|
||||
bool SetValue (const int keyID, const int valueID, const AString & value);
|
||||
bool SetValue (const AString & a_KeyName, const AString & a_ValueName, const AString & a_Value, const bool a_CreateIfNotExists = true);
|
||||
bool SetValueI(const AString & a_KeyName, const AString & a_ValueName, const int a_Value, const bool a_CreateIfNotExists = true);
|
||||
bool SetValueI(const AString & a_Keyname, const AString & a_ValueName, const Int64 a_Value, const bool a_CreateIfNotExists = true);
|
||||
bool SetValueB(const AString & a_KeyName, const AString & a_ValueName, const bool a_Value, const bool a_CreateIfNotExists = true)
|
||||
{
|
||||
return SetValueI(a_KeyName, a_ValueName, int(a_Value), a_CreateIfNotExists);
|
||||
|
@ -623,7 +623,7 @@ Reader::decodeDouble( Token &token )
|
||||
const int bufferSize = 32;
|
||||
int count;
|
||||
int length = int(token.end_ - token.start_);
|
||||
if ( length <= bufferSize )
|
||||
if ( length < bufferSize )
|
||||
{
|
||||
Char buffer[bufferSize];
|
||||
memcpy( buffer, token.start_, length );
|
||||
|
@ -11,13 +11,14 @@ file(GLOB SOURCE
|
||||
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.c" "${PROJECT_SOURCE_DIR}/src/luac.c")
|
||||
|
||||
# add headers to MSVC project files:
|
||||
if (WIN32)
|
||||
if (MSVC)
|
||||
file(GLOB HEADERS "src/*.h")
|
||||
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.h" "${PROJECT_SOURCE_DIR}/src/luac.h")
|
||||
set(SOURCE ${SOURCE} ${HEADERS})
|
||||
source_group("Sources" FILES ${SOURCE})
|
||||
endif()
|
||||
|
||||
|
||||
# Lua needs to be linked dynamically on Windows and statically on *nix, so that LuaRocks work
|
||||
if (WIN32)
|
||||
add_library(lua SHARED ${SOURCE})
|
||||
@ -47,7 +48,7 @@ if (WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(lua PROPERTIES OUTPUT_NAME "lua51")
|
||||
set_target_properties(lua PROPERTIES OUTPUT_NAME "lua51" PREFIX "")
|
||||
|
||||
# NOTE: The DLL for each configuration is stored at the same place, thus overwriting each other.
|
||||
# This is known, however such behavior is needed for LuaRocks - they always load "lua5.1.dll" or "lua51.dll"
|
||||
@ -57,6 +58,7 @@ else()
|
||||
add_library(lua ${SOURCE})
|
||||
endif()
|
||||
|
||||
|
||||
# Tell Lua what dynamic loader to use (for LuaRocks):
|
||||
if (UNIX)
|
||||
add_definitions(-DLUA_USE_DLOPEN)
|
||||
|
61
lib/luaproxy/CMakeLists.txt
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
# This project adds a Lua Proxy DLL on Windows
|
||||
# By an unfortunate choice in the popular LuaBinaries distribution, there are two names for the Lua DLL on Windows: lua51.dll and lua5.1.dll.
|
||||
# Some binary Lua packages are built for one, the others for the other. Messy!
|
||||
# In order to support both package flavors, we create a "proxy DLL":
|
||||
# Basically the lua5.1.dll has its PE Exports section manipulated so that it points each exported function to its lua51.dll implementation.
|
||||
# Effectively, this forwards all calls from lua5.1.dll to lua51.dll without any performance costs (the forwarding is done in the Windows PE loader on app start).
|
||||
|
||||
# This project creates the proxy DLL by using a specially crafted .DEF file that is used to link the Proxy DLL.
|
||||
# Note that it has been tested only on MSVC, it might not work with other compilers.
|
||||
# The initial implementation was taken from http://lua-users.org/wiki/LuaProxyDllFour , but adapted to MSVC
|
||||
|
||||
|
||||
|
||||
|
||||
if (WIN32)
|
||||
|
||||
if (MSVC)
|
||||
# Tell the linker to use the DEF file to generate the proxy:
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /NOENTRY /DEF:lua5.1.def /MANIFEST:NO")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /NOENTRY /DEF:lua5.1.def /MANIFEST:NO")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /NOENTRY /DEF:lua5.1.def /MANIFEST:NO")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /NOENTRY /DEF:lua5.1.def /MANIFEST:NO")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NOENTRY /DEF:lua5.1.def /MANIFEST:NO")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} /NOENTRY /DEF:lua5.1.def /MANIFEST:NO")
|
||||
elseif (MINGW)
|
||||
# MinGW requires no further flags and has been tested
|
||||
else()
|
||||
message ("LuaProxy: This cmake code has not been tested on your compiler. Please report your success or failure in the forum.")
|
||||
endif()
|
||||
|
||||
add_library(luaproxy SHARED "lua5.1.def" "Dummy.c")
|
||||
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
||||
set_target_properties(luaproxy PROPERTIES
|
||||
OUTPUT_NAME "lua5.1"
|
||||
PREFIX ""
|
||||
)
|
||||
target_link_libraries(luaproxy lua)
|
||||
|
||||
# Output the executable into the $/MCServer folder, so that MCServer can find it:
|
||||
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
||||
SET_TARGET_PROPERTIES(luaproxy PROPERTIES
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
ARCHIVE_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
ARCHIVE_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
LIBRARY_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
LIBRARY_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_SOURCE_DIR}/MCServer
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
RUNTIME_OUTPUT_DIRECTORY_DEBUGPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
RUNTIME_OUTPUT_DIRECTORY_RELEASEPROFILE ${CMAKE_SOURCE_DIR}/MCServer
|
||||
)
|
||||
|
||||
else()
|
||||
|
||||
message (FATAL_ERROR "This project is needed only for Windows, modify your cmake file not to include it on Linux")
|
||||
|
||||
endif()
|
4
lib/luaproxy/Dummy.c
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
// Dummy.c
|
||||
|
||||
// Because the MSVC compiler needs at least one C file to compile the project
|
115
lib/luaproxy/lua5.1.def
Normal file
@ -0,0 +1,115 @@
|
||||
EXPORTS
|
||||
luaL_addlstring=lua51.luaL_addlstring
|
||||
luaL_addstring=lua51.luaL_addstring
|
||||
luaL_addvalue=lua51.luaL_addvalue
|
||||
luaL_argerror=lua51.luaL_argerror
|
||||
luaL_buffinit=lua51.luaL_buffinit
|
||||
luaL_callmeta=lua51.luaL_callmeta
|
||||
luaL_checkany=lua51.luaL_checkany
|
||||
luaL_checkinteger=lua51.luaL_checkinteger
|
||||
luaL_checklstring=lua51.luaL_checklstring
|
||||
luaL_checknumber=lua51.luaL_checknumber
|
||||
luaL_checkoption=lua51.luaL_checkoption
|
||||
luaL_checkstack=lua51.luaL_checkstack
|
||||
luaL_checktype=lua51.luaL_checktype
|
||||
luaL_checkudata=lua51.luaL_checkudata
|
||||
luaL_error=lua51.luaL_error
|
||||
luaL_findtable=lua51.luaL_findtable
|
||||
luaL_getmetafield=lua51.luaL_getmetafield
|
||||
luaL_gsub=lua51.luaL_gsub
|
||||
luaL_loadbuffer=lua51.luaL_loadbuffer
|
||||
luaL_loadfile=lua51.luaL_loadfile
|
||||
luaL_loadstring=lua51.luaL_loadstring
|
||||
luaL_newmetatable=lua51.luaL_newmetatable
|
||||
luaL_newstate=lua51.luaL_newstate
|
||||
luaL_openlib=lua51.luaL_openlib
|
||||
luaL_openlibs=lua51.luaL_openlibs
|
||||
luaL_optinteger=lua51.luaL_optinteger
|
||||
luaL_optlstring=lua51.luaL_optlstring
|
||||
luaL_optnumber=lua51.luaL_optnumber
|
||||
luaL_prepbuffer=lua51.luaL_prepbuffer
|
||||
luaL_pushresult=lua51.luaL_pushresult
|
||||
luaL_ref=lua51.luaL_ref
|
||||
luaL_register=lua51.luaL_register
|
||||
luaL_typerror=lua51.luaL_typerror
|
||||
luaL_unref=lua51.luaL_unref
|
||||
luaL_where=lua51.luaL_where
|
||||
lua_atpanic=lua51.lua_atpanic
|
||||
lua_call=lua51.lua_call
|
||||
lua_checkstack=lua51.lua_checkstack
|
||||
lua_close=lua51.lua_close
|
||||
lua_concat=lua51.lua_concat
|
||||
lua_cpcall=lua51.lua_cpcall
|
||||
lua_createtable=lua51.lua_createtable
|
||||
lua_dump=lua51.lua_dump
|
||||
lua_equal=lua51.lua_equal
|
||||
lua_error=lua51.lua_error
|
||||
lua_gc=lua51.lua_gc
|
||||
lua_getallocf=lua51.lua_getallocf
|
||||
lua_getfenv=lua51.lua_getfenv
|
||||
lua_getfield=lua51.lua_getfield
|
||||
lua_gethook=lua51.lua_gethook
|
||||
lua_gethookcount=lua51.lua_gethookcount
|
||||
lua_gethookmask=lua51.lua_gethookmask
|
||||
lua_getinfo=lua51.lua_getinfo
|
||||
lua_getlocal=lua51.lua_getlocal
|
||||
lua_getmetatable=lua51.lua_getmetatable
|
||||
lua_getstack=lua51.lua_getstack
|
||||
lua_gettable=lua51.lua_gettable
|
||||
lua_gettop=lua51.lua_gettop
|
||||
lua_getupvalue=lua51.lua_getupvalue
|
||||
lua_insert=lua51.lua_insert
|
||||
lua_iscfunction=lua51.lua_iscfunction
|
||||
lua_isnumber=lua51.lua_isnumber
|
||||
lua_isstring=lua51.lua_isstring
|
||||
lua_isuserdata=lua51.lua_isuserdata
|
||||
lua_lessthan=lua51.lua_lessthan
|
||||
lua_load=lua51.lua_load
|
||||
lua_newstate=lua51.lua_newstate
|
||||
lua_newthread=lua51.lua_newthread
|
||||
lua_newuserdata=lua51.lua_newuserdata
|
||||
lua_next=lua51.lua_next
|
||||
lua_objlen=lua51.lua_objlen
|
||||
lua_pcall=lua51.lua_pcall
|
||||
lua_pushboolean=lua51.lua_pushboolean
|
||||
lua_pushcclosure=lua51.lua_pushcclosure
|
||||
lua_pushfstring=lua51.lua_pushfstring
|
||||
lua_pushinteger=lua51.lua_pushinteger
|
||||
lua_pushlightuserdata=lua51.lua_pushlightuserdata
|
||||
lua_pushlstring=lua51.lua_pushlstring
|
||||
lua_pushnil=lua51.lua_pushnil
|
||||
lua_pushnumber=lua51.lua_pushnumber
|
||||
lua_pushstring=lua51.lua_pushstring
|
||||
lua_pushthread=lua51.lua_pushthread
|
||||
lua_pushvalue=lua51.lua_pushvalue
|
||||
lua_pushvfstring=lua51.lua_pushvfstring
|
||||
lua_rawequal=lua51.lua_rawequal
|
||||
lua_rawget=lua51.lua_rawget
|
||||
lua_rawgeti=lua51.lua_rawgeti
|
||||
lua_rawset=lua51.lua_rawset
|
||||
lua_rawseti=lua51.lua_rawseti
|
||||
lua_remove=lua51.lua_remove
|
||||
lua_replace=lua51.lua_replace
|
||||
lua_resume=lua51.lua_resume
|
||||
lua_setallocf=lua51.lua_setallocf
|
||||
lua_setfenv=lua51.lua_setfenv
|
||||
lua_setfield=lua51.lua_setfield
|
||||
lua_sethook=lua51.lua_sethook
|
||||
lua_setlocal=lua51.lua_setlocal
|
||||
lua_setmetatable=lua51.lua_setmetatable
|
||||
lua_settable=lua51.lua_settable
|
||||
lua_settop=lua51.lua_settop
|
||||
lua_setupvalue=lua51.lua_setupvalue
|
||||
lua_status=lua51.lua_status
|
||||
lua_toboolean=lua51.lua_toboolean
|
||||
lua_tocfunction=lua51.lua_tocfunction
|
||||
lua_tointeger=lua51.lua_tointeger
|
||||
lua_tolstring=lua51.lua_tolstring
|
||||
lua_tonumber=lua51.lua_tonumber
|
||||
lua_topointer=lua51.lua_topointer
|
||||
lua_tothread=lua51.lua_tothread
|
||||
lua_touserdata=lua51.lua_touserdata
|
||||
lua_type=lua51.lua_type
|
||||
lua_typename=lua51.lua_typename
|
||||
lua_xmove=lua51.lua_xmove
|
||||
lua_yield=lua51.lua_yield
|
140
lib/luaproxy/lua5.1.lua
Normal file
@ -0,0 +1,140 @@
|
||||
|
||||
-- lua5.1.lua
|
||||
-- Generates the lua5.1.def file from the list of Lua symbols below
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
local symbols =
|
||||
{
|
||||
"luaL_addlstring",
|
||||
"luaL_addstring",
|
||||
"luaL_addvalue",
|
||||
"luaL_argerror",
|
||||
"luaL_buffinit",
|
||||
"luaL_callmeta",
|
||||
"luaL_checkany",
|
||||
"luaL_checkinteger",
|
||||
"luaL_checklstring",
|
||||
"luaL_checknumber",
|
||||
"luaL_checkoption",
|
||||
"luaL_checkstack",
|
||||
"luaL_checktype",
|
||||
"luaL_checkudata",
|
||||
"luaL_error",
|
||||
"luaL_findtable",
|
||||
"luaL_getmetafield",
|
||||
"luaL_gsub",
|
||||
"luaL_loadbuffer",
|
||||
"luaL_loadfile",
|
||||
"luaL_loadstring",
|
||||
"luaL_newmetatable",
|
||||
"luaL_newstate",
|
||||
"luaL_openlib",
|
||||
"luaL_openlibs",
|
||||
"luaL_optinteger",
|
||||
"luaL_optlstring",
|
||||
"luaL_optnumber",
|
||||
"luaL_prepbuffer",
|
||||
"luaL_pushresult",
|
||||
"luaL_ref",
|
||||
"luaL_register",
|
||||
"luaL_typerror",
|
||||
"luaL_unref",
|
||||
"luaL_where",
|
||||
"lua_atpanic",
|
||||
"lua_call",
|
||||
"lua_checkstack",
|
||||
"lua_close",
|
||||
"lua_concat",
|
||||
"lua_cpcall",
|
||||
"lua_createtable",
|
||||
"lua_dump",
|
||||
"lua_equal",
|
||||
"lua_error",
|
||||
"lua_gc",
|
||||
"lua_getallocf",
|
||||
"lua_getfenv",
|
||||
"lua_getfield",
|
||||
"lua_gethook",
|
||||
"lua_gethookcount",
|
||||
"lua_gethookmask",
|
||||
"lua_getinfo",
|
||||
"lua_getlocal",
|
||||
"lua_getmetatable",
|
||||
"lua_getstack",
|
||||
"lua_gettable",
|
||||
"lua_gettop",
|
||||
"lua_getupvalue",
|
||||
"lua_insert",
|
||||
"lua_iscfunction",
|
||||
"lua_isnumber",
|
||||
"lua_isstring",
|
||||
"lua_isuserdata",
|
||||
"lua_lessthan",
|
||||
"lua_load",
|
||||
"lua_newstate",
|
||||
"lua_newthread",
|
||||
"lua_newuserdata",
|
||||
"lua_next",
|
||||
"lua_objlen",
|
||||
"lua_pcall",
|
||||
"lua_pushboolean",
|
||||
"lua_pushcclosure",
|
||||
"lua_pushfstring",
|
||||
"lua_pushinteger",
|
||||
"lua_pushlightuserdata",
|
||||
"lua_pushlstring",
|
||||
"lua_pushnil",
|
||||
"lua_pushnumber",
|
||||
"lua_pushstring",
|
||||
"lua_pushthread",
|
||||
"lua_pushvalue",
|
||||
"lua_pushvfstring",
|
||||
"lua_rawequal",
|
||||
"lua_rawget",
|
||||
"lua_rawgeti",
|
||||
"lua_rawset",
|
||||
"lua_rawseti",
|
||||
"lua_remove",
|
||||
"lua_replace",
|
||||
"lua_resume",
|
||||
"lua_setallocf",
|
||||
"lua_setfenv",
|
||||
"lua_setfield",
|
||||
"lua_sethook",
|
||||
"lua_setlocal",
|
||||
"lua_setmetatable",
|
||||
"lua_settable",
|
||||
"lua_settop",
|
||||
"lua_setupvalue",
|
||||
"lua_status",
|
||||
"lua_toboolean",
|
||||
"lua_tocfunction",
|
||||
"lua_tointeger",
|
||||
"lua_tolstring",
|
||||
"lua_tonumber",
|
||||
"lua_topointer",
|
||||
"lua_tothread",
|
||||
"lua_touserdata",
|
||||
"lua_type",
|
||||
"lua_typename",
|
||||
"lua_xmove",
|
||||
"lua_yield",
|
||||
-- "luaopen_base",
|
||||
-- "luaopen_debug",
|
||||
-- "luaopen_io",
|
||||
-- "luaopen_math",
|
||||
-- "luaopen_os",
|
||||
-- "luaopen_package",
|
||||
-- "luaopen_string",
|
||||
-- "luaopen_table",
|
||||
}
|
||||
|
||||
local def = io.open("lua5.1.def", "w")
|
||||
def:write("EXPORTS\n")
|
||||
for _,symbol in ipairs(symbols) do
|
||||
def:write("\t" .. symbol .. "=lua51." .. symbol .. "\n")
|
||||
end
|
||||
def:close()
|
@ -1,12 +0,0 @@
|
||||
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
project (md5)
|
||||
|
||||
include_directories ("${PROJECT_SOURCE_DIR}/../../src/")
|
||||
|
||||
file(GLOB SOURCE
|
||||
"*.cpp"
|
||||
"*.h"
|
||||
)
|
||||
|
||||
add_library(md5 ${SOURCE})
|
369
lib/md5/md5.cpp
@ -1,369 +0,0 @@
|
||||
/* MD5
|
||||
converted to C++ class by Frank Thilo (thilo@unix-ag.org)
|
||||
for bzflag (http://www.bzflag.org)
|
||||
|
||||
based on:
|
||||
|
||||
md5.h and md5.c
|
||||
reference implemantion of RFC 1321
|
||||
|
||||
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
|
||||
*/
|
||||
|
||||
/* interface header */
|
||||
#include "md5.h"
|
||||
|
||||
/* system implementation headers */
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Constants for MD5Transform routine.
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
// F, G, H and I are basic MD5 functions.
|
||||
inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) {
|
||||
return x&y | ~x&z;
|
||||
}
|
||||
|
||||
inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) {
|
||||
return x&z | y&~z;
|
||||
}
|
||||
|
||||
inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) {
|
||||
return x^y^z;
|
||||
}
|
||||
|
||||
inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) {
|
||||
return y ^ (x | ~z);
|
||||
}
|
||||
|
||||
// rotate_left rotates x left n bits.
|
||||
inline MD5::uint4 MD5::rotate_left(uint4 x, int n) {
|
||||
return (x << n) | (x >> (32-n));
|
||||
}
|
||||
|
||||
// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
// Rotation is separate from addition to prevent recomputation.
|
||||
inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||
a = rotate_left(a+ F(b,c,d) + x + ac, s) + b;
|
||||
}
|
||||
|
||||
inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||
a = rotate_left(a + G(b,c,d) + x + ac, s) + b;
|
||||
}
|
||||
|
||||
inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||
a = rotate_left(a + H(b,c,d) + x + ac, s) + b;
|
||||
}
|
||||
|
||||
inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) {
|
||||
a = rotate_left(a + I(b,c,d) + x + ac, s) + b;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
// default ctor, just initailize
|
||||
MD5::MD5()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
// nifty shortcut ctor, compute MD5 for string and finalize it right away
|
||||
MD5::MD5(const std::string &text)
|
||||
{
|
||||
init();
|
||||
update(text.c_str(), text.length());
|
||||
finalize();
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
void MD5::init()
|
||||
{
|
||||
finalized=false;
|
||||
|
||||
count[0] = 0;
|
||||
count[1] = 0;
|
||||
|
||||
// load magic initialization constants.
|
||||
state[0] = 0x67452301;
|
||||
state[1] = 0xefcdab89;
|
||||
state[2] = 0x98badcfe;
|
||||
state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4.
|
||||
void MD5::decode(uint4 output[], const uint1 input[], size_type len)
|
||||
{
|
||||
for (unsigned int i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) |
|
||||
(((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
// encodes input (uint4) into output (unsigned char). Assumes len is
|
||||
// a multiple of 4.
|
||||
void MD5::encode(uint1 output[], const uint4 input[], size_type len)
|
||||
{
|
||||
for (size_type i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = input[i] & 0xff;
|
||||
output[j+1] = (input[i] >> 8) & 0xff;
|
||||
output[j+2] = (input[i] >> 16) & 0xff;
|
||||
output[j+3] = (input[i] >> 24) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
// apply MD5 algo on a block
|
||||
void MD5::transform(const uint1 block[blocksize])
|
||||
{
|
||||
uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
decode (x, block, blocksize);
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
// Zeroize sensitive information.
|
||||
memset(x, 0, sizeof x);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
// MD5 block update operation. Continues an MD5 message-digest
|
||||
// operation, processing another message block
|
||||
void MD5::update(const unsigned char input[], size_type length)
|
||||
{
|
||||
// compute number of bytes mod 64
|
||||
size_type index = count[0] / 8 % blocksize;
|
||||
|
||||
// Update number of bits
|
||||
if ((count[0] += (length << 3)) < (length << 3))
|
||||
count[1]++;
|
||||
count[1] += (length >> 29);
|
||||
|
||||
// number of bytes we need to fill in buffer
|
||||
size_type firstpart = 64 - index;
|
||||
|
||||
size_type i;
|
||||
|
||||
// transform as many times as possible.
|
||||
if (length >= firstpart)
|
||||
{
|
||||
// fill buffer first, transform
|
||||
memcpy(&buffer[index], input, firstpart);
|
||||
transform(buffer);
|
||||
|
||||
// transform chunks of blocksize (64 bytes)
|
||||
for (i = firstpart; i + blocksize <= length; i += blocksize)
|
||||
transform(&input[i]);
|
||||
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
i = 0;
|
||||
|
||||
// buffer remaining input
|
||||
memcpy(&buffer[index], &input[i], length-i);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
// for convenience provide a verson with signed char
|
||||
void MD5::update(const char input[], size_type length)
|
||||
{
|
||||
update((const unsigned char*)input, length);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
// MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||
// the message digest and zeroizing the context.
|
||||
MD5& MD5::finalize()
|
||||
{
|
||||
static unsigned char padding[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
if (!finalized) {
|
||||
// Save number of bits
|
||||
unsigned char bits[8];
|
||||
encode(bits, count, 8);
|
||||
|
||||
// pad out to 56 mod 64.
|
||||
size_type index = count[0] / 8 % 64;
|
||||
size_type padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
update(padding, padLen);
|
||||
|
||||
// Append length (before padding)
|
||||
update(bits, 8);
|
||||
|
||||
// Store state in digest
|
||||
encode(digest, state, 16);
|
||||
|
||||
// Zeroize sensitive information.
|
||||
memset(buffer, 0, sizeof buffer);
|
||||
memset(count, 0, sizeof count);
|
||||
|
||||
finalized=true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
// return hex representation of digest as string
|
||||
std::string MD5::hexdigest() const
|
||||
{
|
||||
if (!finalized)
|
||||
return "";
|
||||
|
||||
char buf[33];
|
||||
for (int i=0; i<16; i++)
|
||||
sprintf(buf+i*2, "%02x", digest[i]);
|
||||
buf[32]=0;
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, MD5 md5)
|
||||
{
|
||||
return out << md5.hexdigest();
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
std::string md5(const std::string & str)
|
||||
{
|
||||
MD5 md5 = MD5(str);
|
||||
|
||||
return md5.hexdigest();
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/* MD5
|
||||
converted to C++ class by Frank Thilo (thilo@unix-ag.org)
|
||||
for bzflag (http://www.bzflag.org)
|
||||
|
||||
based on:
|
||||
|
||||
md5.h and md5.c
|
||||
reference implementation of RFC 1321
|
||||
|
||||
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
|
||||
rights reserved.
|
||||
|
||||
License to copy and use this software is granted provided that it
|
||||
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software
|
||||
or this function.
|
||||
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is"
|
||||
without express or implied warranty of any kind.
|
||||
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BZF_MD5_H
|
||||
#define BZF_MD5_H
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
// a small class for calculating MD5 hashes of strings or byte arrays
|
||||
// it is not meant to be fast or secure
|
||||
//
|
||||
// usage: 1) feed it blocks of uchars with update()
|
||||
// 2) finalize()
|
||||
// 3) get hexdigest() string
|
||||
// or
|
||||
// MD5(std::string).hexdigest()
|
||||
//
|
||||
// assumes that char is 8 bit and int is 32 bit
|
||||
class MD5
|
||||
{
|
||||
public:
|
||||
typedef unsigned int size_type; // must be 32bit
|
||||
|
||||
MD5();
|
||||
MD5(const std::string& text);
|
||||
void update(const unsigned char *buf, size_type length);
|
||||
void update(const char *buf, size_type length);
|
||||
MD5& finalize();
|
||||
std::string hexdigest() const;
|
||||
friend std::ostream& operator<<(std::ostream&, MD5 md5);
|
||||
|
||||
private:
|
||||
void init();
|
||||
typedef unsigned char uint1; // 8bit
|
||||
typedef unsigned int uint4; // 32bit
|
||||
enum {blocksize = 64}; // VC6 won't eat a const static int here
|
||||
|
||||
void transform(const uint1 block[blocksize]);
|
||||
static void decode(uint4 output[], const uint1 input[], size_type len);
|
||||
static void encode(uint1 output[], const uint4 input[], size_type len);
|
||||
|
||||
bool finalized;
|
||||
uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk
|
||||
uint4 count[2]; // 64bit counter for number of bits (lo, hi)
|
||||
uint4 state[4]; // digest so far
|
||||
uint1 digest[16]; // the result
|
||||
|
||||
// low level logic operations
|
||||
static inline uint4 F(uint4 x, uint4 y, uint4 z);
|
||||
static inline uint4 G(uint4 x, uint4 y, uint4 z);
|
||||
static inline uint4 H(uint4 x, uint4 y, uint4 z);
|
||||
static inline uint4 I(uint4 x, uint4 y, uint4 z);
|
||||
static inline uint4 rotate_left(uint4 x, int n);
|
||||
static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||
static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||
static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||
static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac);
|
||||
};
|
||||
|
||||
std::string md5(const std::string & str);
|
||||
|
||||
#endif
|
@ -1,5 +1,11 @@
|
||||
|
||||
if(NOT TARGET polarssl)
|
||||
message("including polarssl")
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL )
|
||||
set(ENABLE_TESTING OFF CACHE BOOL "Disable tests")
|
||||
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable programs")
|
||||
if (SELF_TEST)
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl)
|
||||
else()
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -9,16 +9,27 @@ file(GLOB SOURCE
|
||||
)
|
||||
|
||||
|
||||
# add headers to MSVC project files:
|
||||
# Lua is required as a DLL for LuaSQLite:
|
||||
if (WIN32)
|
||||
add_definitions(-DLUA_BUILD_AS_DLL)
|
||||
endif()
|
||||
|
||||
|
||||
# add headers to MSVC project files:
|
||||
if (MSVC)
|
||||
file(GLOB HEADERS "src/*.h")
|
||||
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.h" "${PROJECT_SOURCE_DIR}/src/luac.h")
|
||||
set(SOURCE ${SOURCE} ${HEADERS})
|
||||
source_group("Sources" FILES ${SOURCE})
|
||||
endif()
|
||||
|
||||
# FreeBSD requires us to define this to get POSIX 2001 standard
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
add_flags_cxx(-D__POSIX_VISIBLE=200112)
|
||||
endif()
|
||||
|
||||
add_library(sqlite ${SOURCE})
|
||||
target_link_libraries(sqlite lua)
|
||||
|
||||
if (UNIX)
|
||||
target_link_libraries(sqlite ${DYNAMIC_LOADER})
|
||||
|
@ -44,14 +44,13 @@ file(GLOB BIN_SOURCE
|
||||
"src/bin/*.c"
|
||||
)
|
||||
|
||||
|
||||
|
||||
add_executable(tolua ${BIN_SOURCE})
|
||||
add_library(tolualib ${LIB_SOURCE})
|
||||
target_link_libraries(tolualib lua)
|
||||
|
||||
#m is the standard math librarys
|
||||
if(UNIX)
|
||||
target_link_libraries(tolua m ${DYNAMIC_LOADER})
|
||||
endif()
|
||||
|
||||
target_link_libraries(tolua lua tolualib)
|
||||
target_link_libraries(tolua tolualib lua)
|
||||
|
@ -688,73 +688,80 @@ static const unsigned char lua_basic_lua[] = {
|
||||
0x74, 0x70, 0x75, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x68,
|
||||
0x6f, 0x6f, 0x6b, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x0a, 0x09, 0x72, 0x65,
|
||||
0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e,
|
||||
0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x0a,
|
||||
0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x63, 0x75, 0x73, 0x74,
|
||||
0x6f, 0x6d, 0x20, 0x70, 0x75, 0x73, 0x68, 0x65, 0x72, 0x73, 0x0a, 0x0a,
|
||||
0x5f, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x69, 0x73,
|
||||
0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0x20,
|
||||
0x20, 0x2d, 0x2d, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x61,
|
||||
0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20,
|
||||
0x6d, 0x75, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x64,
|
||||
0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x69, 0x70,
|
||||
0x6c, 0x65, 0x2d, 0x64, 0x6f, 0x74, 0x2d, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||
0x74, 0x68, 0x65, 0x73, 0x69, 0x73, 0x20, 0x64, 0x75, 0x65, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x70, 0x72, 0x65, 0x2d, 0x70, 0x61, 0x72, 0x73, 0x69, 0x6e,
|
||||
0x67, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x63, 0x75,
|
||||
0x73, 0x74, 0x6f, 0x6d, 0x20, 0x70, 0x75, 0x73, 0x68, 0x65, 0x72, 0x73,
|
||||
0x0a, 0x0a, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a, 0x5f,
|
||||
0x69, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x73,
|
||||
0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x74, 0x6f, 0x5f, 0x66, 0x75,
|
||||
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d,
|
||||
0x0a, 0x0a, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x75, 0x73, 0x68,
|
||||
0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d,
|
||||
0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x20, 0x3d,
|
||||
0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x74, 0x6f, 0x5f, 0x66, 0x75, 0x6e, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x0a, 0x0a,
|
||||
0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x7b,
|
||||
0x7d, 0x0a, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x73, 0x5f, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x7b,
|
||||
0x7d, 0x0a, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d, 0x20, 0x7b,
|
||||
0x7d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
|
||||
0x5f, 0x62, 0x61, 0x73, 0x65, 0x28, 0x74, 0x2c, 0x20, 0x66, 0x75, 0x6e,
|
||||
0x63, 0x73, 0x29, 0x0a, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,
|
||||
0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x67, 0x6c, 0x6f,
|
||||
0x62, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x5b,
|
||||
0x74, 0x5d, 0x0a, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x63,
|
||||
0x6c, 0x61, 0x73, 0x73, 0x20, 0x64, 0x6f, 0x0a, 0x09, 0x09, 0x69, 0x66,
|
||||
0x20, 0x66, 0x75, 0x6e, 0x63, 0x73, 0x5b, 0x63, 0x6c, 0x61, 0x73, 0x73,
|
||||
0x2e, 0x74, 0x79, 0x70, 0x65, 0x5d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
|
||||
0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75,
|
||||
0x6e, 0x63, 0x73, 0x5b, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x74, 0x79,
|
||||
0x70, 0x65, 0x5d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x09,
|
||||
0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x67, 0x6c, 0x6f,
|
||||
0x62, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x5b,
|
||||
0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x62, 0x74, 0x79, 0x70, 0x65, 0x5d,
|
||||
0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
|
||||
0x6e, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x5f,
|
||||
0x70, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x28, 0x74, 0x29, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
|
||||
0x20, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x6f, 0x72, 0x20, 0x73,
|
||||
0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x28, 0x74,
|
||||
0x2c, 0x20, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x75, 0x73, 0x68,
|
||||
0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0x20,
|
||||
0x6f, 0x72, 0x20, 0x22, 0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f, 0x70, 0x75,
|
||||
0x73, 0x68, 0x75, 0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x22, 0x0a,
|
||||
0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x66, 0x75, 0x6e,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x0a, 0x09, 0x72, 0x65,
|
||||
0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x74, 0x6f, 0x5f, 0x66, 0x75, 0x6e,
|
||||
0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x73,
|
||||
0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d,
|
||||
0x20, 0x7b, 0x7d, 0x0a, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x6f,
|
||||
0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x3d,
|
||||
0x20, 0x7b, 0x7d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x65, 0x61, 0x72,
|
||||
0x63, 0x68, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x28, 0x74, 0x2c, 0x20, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x73, 0x29, 0x0a, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x67,
|
||||
0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65,
|
||||
0x73, 0x5b, 0x74, 0x5d, 0x0a, 0x0a, 0x09, 0x77, 0x68, 0x69, 0x6c, 0x65,
|
||||
0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x64, 0x6f, 0x0a, 0x09, 0x09,
|
||||
0x69, 0x66, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x73, 0x5b, 0x63, 0x6c, 0x61,
|
||||
0x73, 0x73, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x5d, 0x20, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x0a, 0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
|
||||
0x66, 0x75, 0x6e, 0x63, 0x73, 0x5b, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e,
|
||||
0x74, 0x79, 0x70, 0x65, 0x5d, 0x0a, 0x09, 0x09, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x09, 0x09, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x67,
|
||||
0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65,
|
||||
0x73, 0x5b, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x62, 0x74, 0x79, 0x70,
|
||||
0x65, 0x5d, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x72, 0x65, 0x74,
|
||||
0x75, 0x72, 0x6e, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x65, 0x6e, 0x64, 0x0a,
|
||||
0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65,
|
||||
0x74, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75,
|
||||
0x72, 0x6e, 0x20, 0x5f, 0x70, 0x75, 0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x6f, 0x72,
|
||||
0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x62, 0x61, 0x73, 0x65,
|
||||
0x28, 0x74, 0x2c, 0x20, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x6f,
|
||||
0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0x20,
|
||||
0x6f, 0x72, 0x20, 0x22, 0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f, 0x74, 0x6f,
|
||||
0x75, 0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x22, 0x0a, 0x65, 0x6e,
|
||||
0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x67, 0x65, 0x74, 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x5f,
|
||||
0x65, 0x6e, 0x75, 0x6d, 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x22,
|
||||
0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f, 0x69, 0x73, 0x22, 0x20, 0x2e, 0x2e,
|
||||
0x20, 0x74, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x72, 0x65, 0x74,
|
||||
0x75, 0x72, 0x6e, 0x20, 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x6f, 0x72, 0x20,
|
||||
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x28,
|
||||
0x74, 0x2c, 0x20, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69, 0x73, 0x5f,
|
||||
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0x20, 0x6f,
|
||||
0x72, 0x20, 0x22, 0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f, 0x69, 0x73, 0x75,
|
||||
0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x22, 0x0a, 0x65, 0x6e, 0x64,
|
||||
0x0a
|
||||
0x28, 0x74, 0x2c, 0x20, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x75,
|
||||
0x73, 0x68, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x29, 0x20, 0x6f, 0x72, 0x20, 0x22, 0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f,
|
||||
0x70, 0x75, 0x73, 0x68, 0x75, 0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65,
|
||||
0x22, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x6f, 0x5f, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x0a, 0x09,
|
||||
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x74, 0x6f, 0x5f, 0x66,
|
||||
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5b, 0x74, 0x5d, 0x20,
|
||||
0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x62, 0x61,
|
||||
0x73, 0x65, 0x28, 0x74, 0x2c, 0x20, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f,
|
||||
0x74, 0x6f, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x29, 0x20, 0x6f, 0x72, 0x20, 0x22, 0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f,
|
||||
0x74, 0x6f, 0x75, 0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x22, 0x0a,
|
||||
0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x75, 0x6e,
|
||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x29, 0x0a, 0x09, 0x69, 0x66,
|
||||
0x20, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x74,
|
||||
0x68, 0x65, 0x6e, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
|
||||
0x20, 0x22, 0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f, 0x69, 0x73, 0x22, 0x20,
|
||||
0x2e, 0x2e, 0x20, 0x74, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x0a, 0x09, 0x72,
|
||||
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x69, 0x73, 0x5f, 0x66, 0x75,
|
||||
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5b, 0x74, 0x5d, 0x20, 0x6f,
|
||||
0x72, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x62, 0x61, 0x73,
|
||||
0x65, 0x28, 0x74, 0x2c, 0x20, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x69,
|
||||
0x73, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29,
|
||||
0x20, 0x6f, 0x72, 0x20, 0x22, 0x74, 0x6f, 0x6c, 0x75, 0x61, 0x5f, 0x69,
|
||||
0x73, 0x75, 0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x22, 0x0a, 0x65,
|
||||
0x6e, 0x64, 0x0a
|
||||
};
|
||||
unsigned int lua_basic_lua_len = 9073;
|
||||
unsigned int lua_basic_lua_len = 9159;
|
||||
|
@ -1154,7 +1154,7 @@ static const unsigned char lua_declaration_lua[] = {
|
||||
0x72, 0x6d, 0x3a, 0x20, 0x6d, 0x6f, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65,
|
||||
0x2a, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0x20, 0x6c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x20, 0x73, 0x31, 0x20, 0x3d, 0x20, 0x67, 0x73, 0x75, 0x62, 0x28,
|
||||
0x73, 0x2c, 0x22, 0x28, 0x25, 0x62, 0x5c, 0x5b, 0x5c, 0x5d, 0x29, 0x22,
|
||||
0x73, 0x2c, 0x22, 0x28, 0x25, 0x62, 0x25, 0x5b, 0x25, 0x5d, 0x29, 0x22,
|
||||
0x2c, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x6e,
|
||||
0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, 0x73, 0x75,
|
||||
0x62, 0x28, 0x6e, 0x2c, 0x27, 0x25, 0x2a, 0x27, 0x2c, 0x27, 0x5c, 0x31,
|
||||
|
93
lib/tolua++/src/bin/lua/_driver.lua
Normal file
@ -0,0 +1,93 @@
|
||||
|
||||
-- Allow debugging by ZBS, if run under the IDE:
|
||||
local mobdebugfound, mobdebug = pcall(require, "mobdebug")
|
||||
if mobdebugfound then mobdebug.start() end
|
||||
|
||||
-- The list of valid arguments that the ToLua scripts can process:
|
||||
local KnownArgs = {
|
||||
['v'] = true,
|
||||
['h'] = true,
|
||||
['p'] = true,
|
||||
['P'] = true,
|
||||
['o'] = true,
|
||||
['n'] = true,
|
||||
['H'] = true,
|
||||
['S'] = true,
|
||||
['1'] = true,
|
||||
['L'] = true,
|
||||
['D'] = true,
|
||||
['W'] = true,
|
||||
['C'] = true,
|
||||
['E'] = true,
|
||||
['t'] = true,
|
||||
['q'] = true,
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- The flags table used by ToLua scripts, to be filled from the cmdline params:
|
||||
flags = {}
|
||||
|
||||
-- Te extra parameters used by ToLua scripts:
|
||||
_extra_parameters = {}
|
||||
|
||||
-- ToLua version required by the scripts:
|
||||
TOLUA_VERSION = "tolua++-1.0.92"
|
||||
|
||||
-- Lua version used by ToLua, required by the scripts:
|
||||
TOLUA_LUA_VERSION = "Lua 5.1"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- Process the cmdline params into the flags table:
|
||||
local args = arg or {}
|
||||
local argc = #args
|
||||
local i = 1
|
||||
while (i <= argc) do
|
||||
local argv = args[i]
|
||||
if (argv:sub(1, 1) == "-") then
|
||||
if (KnownArgs[argv:sub(2)]) then
|
||||
print("Setting flag \"" .. argv:sub(2) .. "\" to \"" .. args[i + 1] .. "\".")
|
||||
flags[argv:sub(2)] = args[i + 1]
|
||||
i = i + 1
|
||||
else
|
||||
print("Unknown option (" .. i .. "): " .. argv)
|
||||
print("Aborting.")
|
||||
os.exit(1)
|
||||
end
|
||||
else
|
||||
print("Setting flag \"f\" to \"" .. argv .. "\".")
|
||||
flags['f'] = argv
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
-- Get the path where the scripts are located:
|
||||
path = args[0] or ""
|
||||
local index = path:find("/[^/]*$")
|
||||
if (index == nil) then
|
||||
index = path:find("\\[^\\]*$")
|
||||
end
|
||||
if (index ~= nil) then
|
||||
path = path:sub(1, index)
|
||||
end
|
||||
|
||||
print("path is set to \"" .. path .. "\".")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- Call the ToLua processor:
|
||||
dofile(path .. "all.lua")
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -383,7 +383,7 @@ end
|
||||
|
||||
-- called to output an error message
|
||||
function output_error_hook(...)
|
||||
return string.format(...)
|
||||
return string.format(...) -- Note that this line must not end in the triple-dot-parenthesis due to pre-parsing
|
||||
end
|
||||
|
||||
-- custom pushers
|
||||
|
@ -18,17 +18,16 @@ local function pp_dofile(path)
|
||||
local ret = file:read("*a")
|
||||
file:close()
|
||||
|
||||
ret = string.gsub(ret, "%.%.%.%s*%)", "...) local arg = {n=select('#', ...), ...};")
|
||||
|
||||
ret = string.gsub(ret, "%.%.%.%s*%)$", "...) local arg = {n=select('#', ...), ...};")
|
||||
|
||||
loaded = true
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
local f = load(getfile, path)
|
||||
local f, err = load(getfile, path)
|
||||
if not f then
|
||||
|
||||
error("error loading file "..path)
|
||||
error("error loading file " .. path .. ": " .. err)
|
||||
end
|
||||
return f()
|
||||
end
|
||||
|
@ -524,7 +524,7 @@ function Declaration (s,kind,is_parameter)
|
||||
end
|
||||
|
||||
-- check the form: mod type* name
|
||||
local s1 = gsub(s,"(%b\[\])",function (n) return gsub(n,'%*','\1') end)
|
||||
local s1 = gsub(s,"(%b%[%])",function (n) return gsub(n,'%*','\1') end)
|
||||
t = split_c_tokens(s1,'%*')
|
||||
if t.n == 2 then
|
||||
t[2] = gsub(t[2],'\1','%*') -- restore * in dimension expression
|
||||
|
@ -132,7 +132,7 @@ function classFeature:cfuncname (n)
|
||||
if not fname or fname == '' then
|
||||
fname = self.name
|
||||
end
|
||||
n = string.gsub(n..'_'.. (fname), "[<>:, \.%*&]", "_")
|
||||
n = string.gsub(n..'_'.. (fname), "[<>:, %.%*&]", "_")
|
||||
|
||||
return n
|
||||
end
|
||||
|
113
src/AllocationPool.h
Normal file
@ -0,0 +1,113 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
template<class T>
|
||||
class cAllocationPool
|
||||
{
|
||||
public:
|
||||
class cStarvationCallbacks
|
||||
{
|
||||
public:
|
||||
virtual ~cStarvationCallbacks() {}
|
||||
|
||||
/** Is called when the reserve buffer starts to be used **/
|
||||
virtual void OnStartUsingReserve() = 0;
|
||||
|
||||
/** Is called once the reserve buffer has returned to normal size **/
|
||||
virtual void OnEndUsingReserve() = 0;
|
||||
|
||||
/** Is called when the allocation pool is unable to allocate memory. Will be repeatedly
|
||||
called if it does not free sufficient memory **/
|
||||
virtual void OnOutOfReserve() = 0;
|
||||
};
|
||||
|
||||
virtual ~cAllocationPool() {}
|
||||
|
||||
/** Allocates a pointer to T **/
|
||||
virtual T * Allocate() = 0;
|
||||
|
||||
/** Frees the pointer passed in a_ptr, invalidating it **/
|
||||
virtual void Free(T * a_ptr) = 0;
|
||||
};
|
||||
|
||||
/** Allocates memory storing unused elements in a linked list. Keeps at least NumElementsInReserve
|
||||
elements in the list unless malloc fails so that the program has a reserve to handle OOM.**/
|
||||
template<class T, size_t NumElementsInReserve>
|
||||
class cListAllocationPool : public cAllocationPool<T>
|
||||
{
|
||||
public:
|
||||
|
||||
cListAllocationPool(std::auto_ptr<typename cAllocationPool<T>::cStarvationCallbacks> a_Callbacks) :
|
||||
m_Callbacks(a_Callbacks)
|
||||
{
|
||||
for (size_t i = 0; i < NumElementsInReserve; i++)
|
||||
{
|
||||
void * space = malloc(sizeof(T));
|
||||
if (space == NULL)
|
||||
{
|
||||
m_Callbacks->OnStartUsingReserve();
|
||||
break;
|
||||
}
|
||||
m_FreeList.push_front(space);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~cListAllocationPool()
|
||||
{
|
||||
while (!m_FreeList.empty())
|
||||
{
|
||||
free (m_FreeList.front());
|
||||
m_FreeList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
virtual T * Allocate() override
|
||||
{
|
||||
if (m_FreeList.size() <= NumElementsInReserve)
|
||||
{
|
||||
void * space = malloc(sizeof(T));
|
||||
if (space != NULL)
|
||||
{
|
||||
return new(space) T;
|
||||
}
|
||||
else if (m_FreeList.size() == NumElementsInReserve)
|
||||
{
|
||||
m_Callbacks->OnStartUsingReserve();
|
||||
}
|
||||
else if (m_FreeList.empty())
|
||||
{
|
||||
m_Callbacks->OnOutOfReserve();
|
||||
// Try again until the memory is avalable
|
||||
return Allocate();
|
||||
}
|
||||
}
|
||||
// placement new, used to initalize the object
|
||||
T * ret = new (m_FreeList.front()) T;
|
||||
m_FreeList.pop_front();
|
||||
return ret;
|
||||
}
|
||||
virtual void Free(T * a_ptr) override
|
||||
{
|
||||
if (a_ptr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// placement destruct.
|
||||
a_ptr->~T();
|
||||
m_FreeList.push_front(a_ptr);
|
||||
if (m_FreeList.size() == NumElementsInReserve)
|
||||
{
|
||||
m_Callbacks->OnEndUsingReserve();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<void *> m_FreeList;
|
||||
std::auto_ptr<typename cAllocationPool<T>::cStarvationCallbacks> m_Callbacks;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|