Merge branch 'master' into Sheep
This commit is contained in:
commit
4b093972ea
1
.gitignore
vendored
1
.gitignore
vendored
@ -26,6 +26,7 @@ cloc.xsl
|
|||||||
## Eclipse
|
## Eclipse
|
||||||
.cproject
|
.cproject
|
||||||
.project
|
.project
|
||||||
|
*.cbp
|
||||||
|
|
||||||
# world inside source
|
# world inside source
|
||||||
ChunkWorx.ini
|
ChunkWorx.ini
|
||||||
|
@ -62,7 +62,10 @@ add_subdirectory(lib/tolua++/)
|
|||||||
add_subdirectory(lib/sqlite/)
|
add_subdirectory(lib/sqlite/)
|
||||||
add_subdirectory(lib/expat/)
|
add_subdirectory(lib/expat/)
|
||||||
add_subdirectory(lib/luaexpat/)
|
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
|
# We use EXCLUDE_FROM_ALL so that only the explicit dependencies are used
|
||||||
|
@ -1875,9 +1875,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." },
|
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." },
|
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)" },
|
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." },
|
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." },
|
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" },
|
Get = { Params = "", Return = "cPluginManager", Notes = "(STATIC) Returns the single instance of the plugin manager" },
|
||||||
@ -1893,8 +1893,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." },
|
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" },
|
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 =
|
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_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_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" },
|
HOOK_CHAT = { Notes = "Called when a client sends a chat message that is not a command. The plugin may modify the chat message" },
|
||||||
@ -2325,6 +2340,7 @@ end
|
|||||||
{ Params = "BlockX, BlockY, BlockZ, BlockMeta", Return = "", Notes = "Sets the meta for the block at the specified coords." },
|
{ 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." },
|
{ 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." },
|
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." },
|
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." },
|
SetCommandBlocksEnabled = { Params = "IsEnabled (bool)", Return = "", Notes = "Sets whether command blocks should be enabled on the (entire) server." },
|
||||||
|
27
MCServer/Plugins/APIDump/Hooks/OnPlayerFoodLevelChange.lua
Normal file
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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ return
|
|||||||
DefaultFnName = "OnWeatherChanging", -- also used as pagename
|
DefaultFnName = "OnWeatherChanging", -- also used as pagename
|
||||||
Desc = [[
|
Desc = [[
|
||||||
This hook is called when the current weather has expired and a new weather is selected. Plugins may
|
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>
|
<p>
|
||||||
The new weather setting is sent to the clients only after this hook has been processed.</p>
|
The new weather setting is sent to the clients only after this hook has been processed.</p>
|
||||||
<p>
|
<p>
|
||||||
@ -19,9 +19,12 @@ return
|
|||||||
{ Name = "Weather", Type = "number", Notes = "The newly selected weather. One of wSunny, wRain, wStorm" },
|
{ Name = "Weather", Type = "number", Notes = "The newly selected weather. One of wSunny, wRain, wStorm" },
|
||||||
},
|
},
|
||||||
Returns = [[
|
Returns = [[
|
||||||
If the function returns false or no value, the server calls other plugins' callbacks and finally
|
The hook handler can return up to two values. If the first value is false or not present, the server
|
||||||
sets the weather. If the function returns true, the server takes the second returned value (wSunny
|
calls other plugins' callbacks and finally sets the weather. If it is true, the server doesn't call any
|
||||||
by default) and sets it as the new weather. No other plugins' callbacks are called in this case.
|
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
|
}, -- HOOK_WEATHER_CHANGING
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ function Initialize(Plugin)
|
|||||||
PM:AddHook(cPluginManager.HOOK_PLUGIN_MESSAGE, OnPluginMessage);
|
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_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
|
-- _X: Disabled so that the normal operation doesn't interfere with anything
|
||||||
-- PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
|
-- PM:AddHook(cPluginManager.HOOK_CHUNK_GENERATED, OnChunkGenerated);
|
||||||
@ -1382,6 +1384,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
function OnProjectileHitBlock(a_Projectile, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockHitPos)
|
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 BlockX, BlockY, BlockZ = AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace)
|
||||||
local World = a_Projectile:GetWorld()
|
local World = a_Projectile:GetWorld()
|
||||||
|
|
||||||
@ -1391,3 +1394,28 @@ 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Binary file not shown.
@ -28,7 +28,8 @@ endmacro()
|
|||||||
macro(set_flags)
|
macro(set_flags)
|
||||||
# Add coverage processing, if requested:
|
# Add coverage processing, if requested:
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
if (${CMAKE_BUILD_TYPE} STREQUAL "COVERAGE")
|
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "COVERAGE")
|
||||||
message("Including CodeCoverage")
|
message("Including CodeCoverage")
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
|
||||||
include(CodeCoverage)
|
include(CodeCoverage)
|
||||||
|
@ -11,21 +11,16 @@ file(GLOB SOURCE
|
|||||||
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.c" "${PROJECT_SOURCE_DIR}/src/luac.c")
|
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.c" "${PROJECT_SOURCE_DIR}/src/luac.c")
|
||||||
|
|
||||||
# add headers to MSVC project files:
|
# add headers to MSVC project files:
|
||||||
if (WIN32)
|
if (MSVC)
|
||||||
file(GLOB HEADERS "src/*.h")
|
file(GLOB HEADERS "src/*.h")
|
||||||
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.h" "${PROJECT_SOURCE_DIR}/src/luac.h")
|
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.h" "${PROJECT_SOURCE_DIR}/src/luac.h")
|
||||||
set(SOURCE ${SOURCE} ${HEADERS})
|
set(SOURCE ${SOURCE} ${HEADERS})
|
||||||
source_group("Sources" FILES ${SOURCE})
|
source_group("Sources" FILES ${SOURCE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Lua needs to be linked dynamically on Windows and statically on *nix, so that LuaRocks work
|
# Lua needs to be linked dynamically on Windows and statically on *nix, so that LuaRocks work
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|
||||||
#for compiliers other than msvc we need to tell lua that its building as a dll
|
|
||||||
if (NOT MSVC)
|
|
||||||
add_flags_cxx(-DLUA_BUILD_AS_DLL=1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(lua SHARED ${SOURCE})
|
add_library(lua SHARED ${SOURCE})
|
||||||
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
set(LIBRARY_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/MCServer)
|
||||||
|
|
||||||
@ -53,7 +48,7 @@ if (WIN32)
|
|||||||
)
|
)
|
||||||
endif()
|
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.
|
# 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"
|
# This is known, however such behavior is needed for LuaRocks - they always load "lua5.1.dll" or "lua51.dll"
|
||||||
@ -63,6 +58,7 @@ else()
|
|||||||
add_library(lua ${SOURCE})
|
add_library(lua ${SOURCE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Tell Lua what dynamic loader to use (for LuaRocks):
|
# Tell Lua what dynamic loader to use (for LuaRocks):
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
add_definitions(-DLUA_USE_DLOPEN)
|
add_definitions(-DLUA_USE_DLOPEN)
|
||||||
|
61
lib/luaproxy/CMakeLists.txt
Normal file
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
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
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
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
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,9 +1,9 @@
|
|||||||
|
|
||||||
if(NOT TARGET polarssl)
|
if(NOT TARGET polarssl)
|
||||||
message("including polarssl")
|
message("including polarssl")
|
||||||
|
set(ENABLE_TESTING OFF CACHE BOOL "Disable tests")
|
||||||
|
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable programs")
|
||||||
if (SELF_TEST)
|
if (SELF_TEST)
|
||||||
set(ENABLE_TESTING OFF CACHE BOOL "Disable tests")
|
|
||||||
set(ENABLE_PROGRAMS OFF CACHE BOOL "Disable programs")
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl)
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl)
|
||||||
else()
|
else()
|
||||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL)
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/polarssl/ ${CMAKE_CURRENT_BINARY_DIR}/lib/polarssl EXCLUDE_FROM_ALL)
|
||||||
|
@ -9,8 +9,14 @@ file(GLOB SOURCE
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# add headers to MSVC project files:
|
# Lua is required as a DLL for LuaSQLite:
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
add_definitions(-DLUA_BUILD_AS_DLL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# add headers to MSVC project files:
|
||||||
|
if (MSVC)
|
||||||
file(GLOB HEADERS "src/*.h")
|
file(GLOB HEADERS "src/*.h")
|
||||||
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.h" "${PROJECT_SOURCE_DIR}/src/luac.h")
|
list(REMOVE_ITEM SOURCE "${PROJECT_SOURCE_DIR}/src/lua.h" "${PROJECT_SOURCE_DIR}/src/luac.h")
|
||||||
set(SOURCE ${SOURCE} ${HEADERS})
|
set(SOURCE ${SOURCE} ${HEADERS})
|
||||||
@ -23,6 +29,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(sqlite ${SOURCE})
|
add_library(sqlite ${SOURCE})
|
||||||
|
target_link_libraries(sqlite lua)
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
target_link_libraries(sqlite ${DYNAMIC_LOADER})
|
target_link_libraries(sqlite ${DYNAMIC_LOADER})
|
||||||
|
@ -44,14 +44,13 @@ file(GLOB BIN_SOURCE
|
|||||||
"src/bin/*.c"
|
"src/bin/*.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add_executable(tolua ${BIN_SOURCE})
|
add_executable(tolua ${BIN_SOURCE})
|
||||||
add_library(tolualib ${LIB_SOURCE})
|
add_library(tolualib ${LIB_SOURCE})
|
||||||
|
target_link_libraries(tolualib lua)
|
||||||
|
|
||||||
#m is the standard math librarys
|
#m is the standard math librarys
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
target_link_libraries(tolua m ${DYNAMIC_LOADER})
|
target_link_libraries(tolua m ${DYNAMIC_LOADER})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(tolua lua tolualib)
|
target_link_libraries(tolua tolualib lua)
|
||||||
|
1
src/Bindings/.gitignore
vendored
1
src/Bindings/.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
lua51.dll
|
lua51.dll
|
||||||
|
LuaState_Call.inc
|
||||||
|
@ -811,6 +811,18 @@ void cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
|
||||||
|
{
|
||||||
|
if (lua_isnumber(m_LuaState, a_StackPos))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = (eWeather)Clamp((int)tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal), (int)wSunny, (int)wThunderstorm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cLuaState::CallFunction(int a_NumResults)
|
bool cLuaState::CallFunction(int a_NumResults)
|
||||||
{
|
{
|
||||||
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
|
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
|
||||||
|
@ -9,10 +9,11 @@ Owned lua_State is created by calling Create() and the cLuaState automatically c
|
|||||||
Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state
|
Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state
|
||||||
Attaching a state will automatically close an owned state.
|
Attaching a state will automatically close an owned state.
|
||||||
|
|
||||||
Calling a Lua function is done by pushing the function, either by PushFunction() or PushFunctionFromRegistry(),
|
Calling a Lua function is done internally by pushing the function using PushFunction(), then pushing the
|
||||||
then pushing the arguments (PushString(), PushNumber(), PushUserData() etc.) and finally
|
arguments and finally executing CallFunction(). cLuaState automatically keeps track of the number of
|
||||||
executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the
|
arguments and the name of the function (for logging purposes). After the call the return values are read from
|
||||||
function (for logging purposes), which makes the call less error-prone.
|
the stack using GetStackValue(). All of this is wrapped in a templated function overloads cLuaState::Call(),
|
||||||
|
which is generated automatically by gen_LuaState_Call.lua script file into the LuaState_Call.inc file.
|
||||||
|
|
||||||
Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to
|
Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to
|
||||||
any Lua object across several function calls; usually this is used for callbacks. The class is RAII-like, with
|
any Lua object across several function calls; usually this is used for callbacks. The class is RAII-like, with
|
||||||
@ -30,6 +31,7 @@ extern "C"
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "../Vector3.h"
|
#include "../Vector3.h"
|
||||||
|
#include "../Defines.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -222,625 +224,13 @@ public:
|
|||||||
/** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
|
/** Retrieve value at a_StackPos, if it is a valid number. If not, a_Value is unchanged */
|
||||||
void GetStackValue(int a_StackPos, double & a_Value);
|
void GetStackValue(int a_StackPos, double & a_Value);
|
||||||
|
|
||||||
|
/** Retrieve value at a_StackPos, if it is a valid number, converting and clamping it to eWeather.
|
||||||
/** Call any 0-param 0-return Lua function in a single line: */
|
If not, a_Value is unchanged. */
|
||||||
template <typename FnT>
|
void GetStackValue(int a_StackPos, eWeather & a_Value);
|
||||||
bool Call(FnT a_FnName)
|
|
||||||
{
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return CallFunction(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 1-param 0-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT,
|
|
||||||
typename ArgT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1)
|
|
||||||
{
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
return CallFunction(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 2-param 0-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2)
|
|
||||||
{
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
return CallFunction(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 3-param 0-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3)
|
|
||||||
{
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
return CallFunction(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 0-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 1-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
int InitialTop = lua_gettop(m_LuaState);
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
ASSERT(InitialTop == lua_gettop(m_LuaState));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 2-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 3-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 4-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 5-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 6-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
|
|
||||||
typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 7-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
|
|
||||||
typename ArgT7, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 8-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
|
|
||||||
typename ArgT7, typename ArgT8, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
Push(a_Arg8);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 9-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
|
|
||||||
typename ArgT7, typename ArgT8, typename ArgT9, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
Push(a_Arg8);
|
|
||||||
Push(a_Arg9);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 10-param 1-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5, typename ArgT6,
|
|
||||||
typename ArgT7, typename ArgT8, typename ArgT9, typename ArgT10, typename RetT1
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, ArgT10 a_Arg10, const cRet & a_Mark, RetT1 & a_Ret1)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
Push(a_Arg8);
|
|
||||||
Push(a_Arg9);
|
|
||||||
Push(a_Arg10);
|
|
||||||
if (!CallFunction(1))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-1, a_Ret1);
|
|
||||||
lua_pop(m_LuaState, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 1-param 2-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename RetT1, typename RetT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
if (!CallFunction(2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-2, a_Ret1);
|
|
||||||
GetStackValue(-1, a_Ret2);
|
|
||||||
lua_pop(m_LuaState, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 2-param 2-return Lua function in a single line: */
|
// Include the cLuaState::Call() overload implementation that is generated by the gen_LuaState_Call.lua script:
|
||||||
template<
|
#include "LuaState_Call.inc"
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename RetT1, typename RetT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
if (!CallFunction(2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-2, a_Ret1);
|
|
||||||
GetStackValue(-1, a_Ret2);
|
|
||||||
lua_pop(m_LuaState, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 3-param 2-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3,
|
|
||||||
typename RetT1, typename RetT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
if (!CallFunction(2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-2, a_Ret1);
|
|
||||||
GetStackValue(-1, a_Ret2);
|
|
||||||
lua_pop(m_LuaState, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 4-param 2-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4,
|
|
||||||
typename RetT1, typename RetT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
if (!CallFunction(2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-2, a_Ret1);
|
|
||||||
GetStackValue(-1, a_Ret2);
|
|
||||||
lua_pop(m_LuaState, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 5-param 2-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
|
|
||||||
typename RetT1, typename RetT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
if (!CallFunction(2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-2, a_Ret1);
|
|
||||||
GetStackValue(-1, a_Ret2);
|
|
||||||
lua_pop(m_LuaState, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 6-param 2-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
|
|
||||||
typename ArgT6,
|
|
||||||
typename RetT1, typename RetT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
if (!CallFunction(2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-2, a_Ret1);
|
|
||||||
GetStackValue(-1, a_Ret2);
|
|
||||||
lua_pop(m_LuaState, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 7-param 2-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
|
|
||||||
typename ArgT6, typename ArgT7,
|
|
||||||
typename RetT1, typename RetT2
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
if (!CallFunction(2))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-2, a_Ret1);
|
|
||||||
GetStackValue(-1, a_Ret2);
|
|
||||||
lua_pop(m_LuaState, 2);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 7-param 3-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
|
|
||||||
typename ArgT6, typename ArgT7,
|
|
||||||
typename RetT1, typename RetT2, typename RetT3
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
if (!CallFunction(3))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-3, a_Ret1);
|
|
||||||
GetStackValue(-2, a_Ret2);
|
|
||||||
GetStackValue(-1, a_Ret3);
|
|
||||||
lua_pop(m_LuaState, 3);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 8-param 3-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
|
|
||||||
typename ArgT6, typename ArgT7, typename ArgT8,
|
|
||||||
typename RetT1, typename RetT2, typename RetT3
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
Push(a_Arg8);
|
|
||||||
if (!CallFunction(3))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-3, a_Ret1);
|
|
||||||
GetStackValue(-2, a_Ret2);
|
|
||||||
GetStackValue(-1, a_Ret3);
|
|
||||||
lua_pop(m_LuaState, 3);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Call any 9-param 5-return Lua function in a single line: */
|
|
||||||
template<
|
|
||||||
typename FnT, typename ArgT1, typename ArgT2, typename ArgT3, typename ArgT4, typename ArgT5,
|
|
||||||
typename ArgT6, typename ArgT7, typename ArgT8, typename ArgT9,
|
|
||||||
typename RetT1, typename RetT2, typename RetT3, typename RetT4, typename RetT5
|
|
||||||
>
|
|
||||||
bool Call(FnT a_FnName, ArgT1 a_Arg1, ArgT2 a_Arg2, ArgT3 a_Arg3, ArgT4 a_Arg4, ArgT5 a_Arg5, ArgT6 a_Arg6, ArgT7 a_Arg7, ArgT8 a_Arg8, ArgT9 a_Arg9, const cRet & a_Mark, RetT1 & a_Ret1, RetT2 & a_Ret2, RetT3 & a_Ret3, RetT4 & a_Ret4, RetT5 & a_Ret5)
|
|
||||||
{
|
|
||||||
UNUSED(a_Mark);
|
|
||||||
if (!PushFunction(a_FnName))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Push(a_Arg1);
|
|
||||||
Push(a_Arg2);
|
|
||||||
Push(a_Arg3);
|
|
||||||
Push(a_Arg4);
|
|
||||||
Push(a_Arg5);
|
|
||||||
Push(a_Arg6);
|
|
||||||
Push(a_Arg7);
|
|
||||||
Push(a_Arg8);
|
|
||||||
Push(a_Arg9);
|
|
||||||
if (!CallFunction(5))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
GetStackValue(-5, a_Ret1);
|
|
||||||
GetStackValue(-4, a_Ret2);
|
|
||||||
GetStackValue(-3, a_Ret3);
|
|
||||||
GetStackValue(-2, a_Ret4);
|
|
||||||
GetStackValue(-1, a_Ret5);
|
|
||||||
lua_pop(m_LuaState, 5);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions */
|
/** Returns true if the specified parameters on the stack are of the specified usertable type; also logs warning if not. Used for static functions */
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "ManualBindings.h"
|
#include "ManualBindings.h"
|
||||||
#undef TOLUA_TEMPLATE_BIND
|
#undef TOLUA_TEMPLATE_BIND
|
||||||
#include "tolua++/include/tolua++.h"
|
#include "tolua++/include/tolua++.h"
|
||||||
|
#include "polarssl/md5.h"
|
||||||
#include "Plugin.h"
|
#include "Plugin.h"
|
||||||
#include "PluginLua.h"
|
#include "PluginLua.h"
|
||||||
#include "PluginManager.h"
|
#include "PluginManager.h"
|
||||||
@ -25,7 +25,6 @@
|
|||||||
#include "../BlockEntities/NoteEntity.h"
|
#include "../BlockEntities/NoteEntity.h"
|
||||||
#include "../BlockEntities/MobHeadEntity.h"
|
#include "../BlockEntities/MobHeadEntity.h"
|
||||||
#include "../BlockEntities/FlowerPotEntity.h"
|
#include "../BlockEntities/FlowerPotEntity.h"
|
||||||
#include "md5/md5.h"
|
|
||||||
#include "../LineBlockTracer.h"
|
#include "../LineBlockTracer.h"
|
||||||
#include "../WorldStorage/SchematicFileSerializer.h"
|
#include "../WorldStorage/SchematicFileSerializer.h"
|
||||||
#include "../CompositeChat.h"
|
#include "../CompositeChat.h"
|
||||||
@ -2001,9 +2000,11 @@ static int tolua_cPlugin_Call(lua_State * tolua_S)
|
|||||||
|
|
||||||
static int tolua_md5(lua_State* tolua_S)
|
static int tolua_md5(lua_State* tolua_S)
|
||||||
{
|
{
|
||||||
std::string SourceString = tolua_tostring(tolua_S, 1, 0);
|
unsigned char Output[16];
|
||||||
std::string CryptedString = md5( SourceString );
|
size_t len = 0;
|
||||||
tolua_pushstring( tolua_S, CryptedString.c_str() );
|
const unsigned char * SourceString = (const unsigned char *)lua_tolstring(tolua_S, 1, &len);
|
||||||
|
md5(SourceString, len, Output);
|
||||||
|
lua_pushlstring(tolua_S, (const char *)Output, ARRAYCOUNT(Output));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@ public:
|
|||||||
virtual bool OnPlayerEating (cPlayer & a_Player) = 0;
|
virtual bool OnPlayerEating (cPlayer & a_Player) = 0;
|
||||||
virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) = 0;
|
virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) = 0;
|
||||||
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) = 0;
|
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) = 0;
|
||||||
|
virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) = 0;
|
||||||
virtual bool OnPlayerJoined (cPlayer & a_Player) = 0;
|
virtual bool OnPlayerJoined (cPlayer & a_Player) = 0;
|
||||||
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) = 0;
|
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) = 0;
|
||||||
virtual bool OnPlayerMoved (cPlayer & a_Player) = 0;
|
virtual bool OnPlayerMoved (cPlayer & a_Player) = 0;
|
||||||
|
@ -715,6 +715,26 @@ bool cPluginLua::OnPlayerEating(cPlayer & a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginLua::OnPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CriticalSection);
|
||||||
|
bool res = false;
|
||||||
|
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_FOOD_LEVEL_CHANGE];
|
||||||
|
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
m_LuaState.Call((int)(**itr), &a_Player, a_NewFoodLevel, cLuaState::Return, res);
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginLua::OnPlayerFished(cPlayer & a_Player, const cItems & a_Reward)
|
bool cPluginLua::OnPlayerFished(cPlayer & a_Player, const cItems & a_Reward)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
@ -1327,18 +1347,15 @@ bool cPluginLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather)
|
|||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
bool res = false;
|
bool res = false;
|
||||||
int NewWeather = a_NewWeather;
|
|
||||||
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGING];
|
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WEATHER_CHANGING];
|
||||||
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
|
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
|
||||||
{
|
{
|
||||||
m_LuaState.Call((int)(**itr), &a_World, NewWeather, cLuaState::Return, res, NewWeather);
|
m_LuaState.Call((int)(**itr), &a_World, a_NewWeather, cLuaState::Return, res, a_NewWeather);
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
a_NewWeather = (eWeather)NewWeather;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a_NewWeather = (eWeather)NewWeather;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1714,7 +1731,7 @@ bool cPluginLua::CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPlayer
|
|||||||
ASSERT(a_FnRef != LUA_REFNIL);
|
ASSERT(a_FnRef != LUA_REFNIL);
|
||||||
|
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
bool res;
|
bool res = false;
|
||||||
m_LuaState.Call(a_FnRef, &a_Window, &a_Player, a_CanRefuse, cLuaState::Return, res);
|
m_LuaState.Call(a_FnRef, &a_Window, &a_Player, a_CanRefuse, cLuaState::Return, res);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,7 @@ public:
|
|||||||
virtual bool OnPlayerEating (cPlayer & a_Player) override;
|
virtual bool OnPlayerEating (cPlayer & a_Player) override;
|
||||||
virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) override;
|
virtual bool OnPlayerFished (cPlayer & a_Player, const cItems & a_Reward) override;
|
||||||
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) override;
|
virtual bool OnPlayerFishing (cPlayer & a_Player, cItems & a_Reward) override;
|
||||||
|
virtual bool OnPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel) override;
|
||||||
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
|
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
|
||||||
virtual bool OnPlayerMoved (cPlayer & a_Player) override;
|
virtual bool OnPlayerMoved (cPlayer & a_Player) override;
|
||||||
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) override;
|
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) override;
|
||||||
|
@ -257,18 +257,44 @@ bool cPluginManager::CallHookBlockToPickups(
|
|||||||
|
|
||||||
bool cPluginManager::CallHookChat(cPlayer * a_Player, AString & a_Message)
|
bool cPluginManager::CallHookChat(cPlayer * a_Player, AString & a_Message)
|
||||||
{
|
{
|
||||||
bool WasCommandForbidden = false;
|
// Check if the message contains a command, execute it:
|
||||||
if (HandleCommand(a_Player, a_Message, true, WasCommandForbidden)) // We use HandleCommand as opposed to ExecuteCommand to accomodate the need to the WasCommandForbidden bool
|
switch (HandleCommand(a_Player, a_Message, true))
|
||||||
{
|
{
|
||||||
return true; // Chat message was handled as command
|
case crExecuted:
|
||||||
}
|
{
|
||||||
else if (WasCommandForbidden) // Couldn't be handled as command, was it because of insufficient permissions?
|
// The command has executed successfully
|
||||||
{
|
return true;
|
||||||
return true; // Yes - message was sent in HandleCommand, abort
|
}
|
||||||
|
|
||||||
|
case crBlocked:
|
||||||
|
{
|
||||||
|
// The command was blocked by a plugin using HOOK_EXECUTE_COMMAND
|
||||||
|
// The plugin has most likely sent a message to the player already
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case crError:
|
||||||
|
{
|
||||||
|
// An error in the plugin has prevented the command from executing. Report the error to the player:
|
||||||
|
a_Player->SendMessageFailure(Printf("Something went wrong while executing command \"%s\"", a_Message.c_str()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case crNoPermission:
|
||||||
|
{
|
||||||
|
// The player is not allowed to execute this command
|
||||||
|
a_Player->SendMessageFailure(Printf("Forbidden command; insufficient privileges: \"%s\"", a_Message.c_str()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case crUnknownCommand:
|
||||||
|
{
|
||||||
|
// This was not a known command, keep processing as a message
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it was a standard command (starts with a slash)
|
// Check if the message is a command (starts with a slash). If it is, we know that it wasn't recognised:
|
||||||
// If it was, we know that it was completely unrecognised (WasCommandForbidden == false)
|
|
||||||
if (!a_Message.empty() && (a_Message[0] == '/'))
|
if (!a_Message.empty() && (a_Message[0] == '/'))
|
||||||
{
|
{
|
||||||
AStringVector Split(StringSplit(a_Message, " "));
|
AStringVector Split(StringSplit(a_Message, " "));
|
||||||
@ -695,6 +721,25 @@ bool cPluginManager::CallHookPlayerEating(cPlayer & a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPluginManager::CallHookPlayerFoodLevelChange(cPlayer & a_Player, int a_NewFoodLevel)
|
||||||
|
{
|
||||||
|
FIND_HOOK(HOOK_PLAYER_FOOD_LEVEL_CHANGE);
|
||||||
|
VERIFY_HOOK;
|
||||||
|
|
||||||
|
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
||||||
|
{
|
||||||
|
if ((*itr)->OnPlayerFoodLevelChange(a_Player, a_NewFoodLevel))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::CallHookPlayerFished(cPlayer & a_Player, const cItems a_Reward)
|
bool cPluginManager::CallHookPlayerFished(cPlayer & a_Player, const cItems a_Reward)
|
||||||
{
|
{
|
||||||
FIND_HOOK(HOOK_PLAYER_FISHED);
|
FIND_HOOK(HOOK_PLAYER_FISHED);
|
||||||
@ -1318,28 +1363,28 @@ bool cPluginManager::CallHookWorldTick(cWorld & a_World, float a_Dt, int a_LastT
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions, bool & a_WasCommandForbidden)
|
cPluginManager::CommandResult cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions)
|
||||||
{
|
{
|
||||||
ASSERT(a_Player != NULL);
|
ASSERT(a_Player != NULL);
|
||||||
|
|
||||||
AStringVector Split(StringSplit(a_Command, " "));
|
AStringVector Split(StringSplit(a_Command, " "));
|
||||||
if (Split.empty())
|
if (Split.empty())
|
||||||
{
|
{
|
||||||
return false;
|
return crUnknownCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandMap::iterator cmd = m_Commands.find(Split[0]);
|
CommandMap::iterator cmd = m_Commands.find(Split[0]);
|
||||||
if (cmd == m_Commands.end())
|
if (cmd == m_Commands.end())
|
||||||
{
|
{
|
||||||
// Command not found
|
// Command not found
|
||||||
return false;
|
return crUnknownCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask plugins first if a command is okay to execute the command:
|
// Ask plugins first if a command is okay to execute the command:
|
||||||
if (CallHookExecuteCommand(a_Player, Split))
|
if (CallHookExecuteCommand(a_Player, Split))
|
||||||
{
|
{
|
||||||
LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player->GetName().c_str(), Split[0].c_str());
|
LOGINFO("Player %s tried executing command \"%s\" that was stopped by the HOOK_EXECUTE_COMMAND hook", a_Player->GetName().c_str(), Split[0].c_str());
|
||||||
return false;
|
return crBlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -1348,15 +1393,18 @@ bool cPluginManager::HandleCommand(cPlayer * a_Player, const AString & a_Command
|
|||||||
!a_Player->HasPermission(cmd->second.m_Permission)
|
!a_Player->HasPermission(cmd->second.m_Permission)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
a_Player->SendMessageFailure(Printf("Forbidden command; insufficient privileges: \"%s\"", Split[0].c_str()));
|
|
||||||
LOGINFO("Player %s tried to execute forbidden command: \"%s\"", a_Player->GetName().c_str(), Split[0].c_str());
|
LOGINFO("Player %s tried to execute forbidden command: \"%s\"", a_Player->GetName().c_str(), Split[0].c_str());
|
||||||
a_WasCommandForbidden = true;
|
return crNoPermission;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(cmd->second.m_Plugin != NULL);
|
ASSERT(cmd->second.m_Plugin != NULL);
|
||||||
|
|
||||||
return cmd->second.m_Plugin->HandleCommand(Split, a_Player);
|
if (!cmd->second.m_Plugin->HandleCommand(Split, a_Player))
|
||||||
|
{
|
||||||
|
return crError;
|
||||||
|
}
|
||||||
|
|
||||||
|
return crExecuted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1554,7 +1602,7 @@ AString cPluginManager::GetCommandPermission(const AString & a_Command)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Command)
|
cPluginManager::CommandResult cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Command)
|
||||||
{
|
{
|
||||||
return HandleCommand(a_Player, a_Command, true);
|
return HandleCommand(a_Player, a_Command, true);
|
||||||
}
|
}
|
||||||
@ -1563,7 +1611,7 @@ bool cPluginManager::ExecuteCommand(cPlayer * a_Player, const AString & a_Comman
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command)
|
cPluginManager::CommandResult cPluginManager::ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command)
|
||||||
{
|
{
|
||||||
return HandleCommand(a_Player, a_Command, false);
|
return HandleCommand(a_Player, a_Command, false);
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,17 @@ public: // tolua_export
|
|||||||
|
|
||||||
// Called each tick
|
// Called each tick
|
||||||
virtual void Tick(float a_Dt);
|
virtual void Tick(float a_Dt);
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
enum CommandResult
|
||||||
|
{
|
||||||
|
crExecuted,
|
||||||
|
crUnknownCommand,
|
||||||
|
crError,
|
||||||
|
crBlocked,
|
||||||
|
crNoPermission,
|
||||||
|
} ;
|
||||||
|
|
||||||
enum PluginHook
|
enum PluginHook
|
||||||
{
|
{
|
||||||
HOOK_BLOCK_SPREAD,
|
HOOK_BLOCK_SPREAD,
|
||||||
@ -87,6 +96,7 @@ public: // tolua_export
|
|||||||
HOOK_PLAYER_EATING,
|
HOOK_PLAYER_EATING,
|
||||||
HOOK_PLAYER_FISHED,
|
HOOK_PLAYER_FISHED,
|
||||||
HOOK_PLAYER_FISHING,
|
HOOK_PLAYER_FISHING,
|
||||||
|
HOOK_PLAYER_FOOD_LEVEL_CHANGE,
|
||||||
HOOK_PLAYER_JOINED,
|
HOOK_PLAYER_JOINED,
|
||||||
HOOK_PLAYER_LEFT_CLICK,
|
HOOK_PLAYER_LEFT_CLICK,
|
||||||
HOOK_PLAYER_MOVING,
|
HOOK_PLAYER_MOVING,
|
||||||
@ -188,6 +198,7 @@ public: // tolua_export
|
|||||||
bool CallHookPlayerEating (cPlayer & a_Player);
|
bool CallHookPlayerEating (cPlayer & a_Player);
|
||||||
bool CallHookPlayerFished (cPlayer & a_Player, const cItems a_Reward);
|
bool CallHookPlayerFished (cPlayer & a_Player, const cItems a_Reward);
|
||||||
bool CallHookPlayerFishing (cPlayer & a_Player, cItems a_Reward);
|
bool CallHookPlayerFishing (cPlayer & a_Player, cItems a_Reward);
|
||||||
|
bool CallHookPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel);
|
||||||
bool CallHookPlayerJoined (cPlayer & a_Player);
|
bool CallHookPlayerJoined (cPlayer & a_Player);
|
||||||
bool CallHookPlayerMoving (cPlayer & a_Player);
|
bool CallHookPlayerMoving (cPlayer & a_Player);
|
||||||
bool CallHookPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
|
bool CallHookPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
|
||||||
@ -244,11 +255,11 @@ public: // tolua_export
|
|||||||
/** Returns the permission needed for the specified command; empty string if command not found */
|
/** Returns the permission needed for the specified command; empty string if command not found */
|
||||||
AString GetCommandPermission(const AString & a_Command); // tolua_export
|
AString GetCommandPermission(const AString & a_Command); // tolua_export
|
||||||
|
|
||||||
/** Executes the command, as if it was requested by a_Player. Checks permissions first. Returns true if executed. */
|
/** Executes the command, as if it was requested by a_Player. Checks permissions first. Returns crExecuted if executed. */
|
||||||
bool ExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
|
CommandResult ExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
|
||||||
|
|
||||||
/** Executes the command, as if it was requested by a_Player. Permisssions are not checked. Returns true if executed (false if not found) */
|
/** Executes the command, as if it was requested by a_Player. Permisssions are not checked. Returns crExecuted if executed. */
|
||||||
bool ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
|
CommandResult ForceExecuteCommand(cPlayer * a_Player, const AString & a_Command); // tolua_export
|
||||||
|
|
||||||
/** Removes all console command bindings that the specified plugin has made */
|
/** Removes all console command bindings that the specified plugin has made */
|
||||||
void RemovePluginConsoleCommands(cPlugin * a_Plugin);
|
void RemovePluginConsoleCommands(cPlugin * a_Plugin);
|
||||||
@ -321,13 +332,8 @@ private:
|
|||||||
/** Adds the plugin into the internal list of plugins and initializes it. If initialization fails, the plugin is removed again. */
|
/** Adds the plugin into the internal list of plugins and initializes it. If initialization fails, the plugin is removed again. */
|
||||||
bool AddPlugin(cPlugin * a_Plugin);
|
bool AddPlugin(cPlugin * a_Plugin);
|
||||||
|
|
||||||
/** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns true if the command is handled. */
|
/** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding plugin is called. Returns crExecuted if the command is executed. */
|
||||||
bool HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions, bool & a_WasCommandForbidden);
|
cPluginManager::CommandResult HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
|
||||||
bool HandleCommand(cPlayer * a_Player, const AString & a_Command, bool a_ShouldCheckPermissions)
|
|
||||||
{
|
|
||||||
bool DummyBoolean = false;
|
|
||||||
return HandleCommand(a_Player, a_Command, a_ShouldCheckPermissions, DummyBoolean);
|
|
||||||
}
|
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
196
src/Bindings/gen_LuaState_Call.lua
Normal file
196
src/Bindings/gen_LuaState_Call.lua
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
|
||||||
|
-- gen_LuaState_Call.lua
|
||||||
|
|
||||||
|
-- Generates the cLuaState::Call() function templates that are included from LuaState.h
|
||||||
|
|
||||||
|
--[[
|
||||||
|
The cLuaState::Call() family of functions provides a template-based system for calling any Lua function
|
||||||
|
either by name or by reference with almost any number of parameters and return values. This is done by
|
||||||
|
providing a number of overloads of the same name with variable number of template-type parameters. To
|
||||||
|
separate the arguments from the return values, a special type of cLuaState::cRet is used.
|
||||||
|
--]]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print("Generating LuaState_Call.inc...")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- List of combinations (# params, # returns) to generate:
|
||||||
|
local Combinations =
|
||||||
|
{
|
||||||
|
-- no return values:
|
||||||
|
{0, 0},
|
||||||
|
{1, 0},
|
||||||
|
{2, 0},
|
||||||
|
{3, 0},
|
||||||
|
{4, 0},
|
||||||
|
|
||||||
|
-- 1 return value:
|
||||||
|
{0, 1},
|
||||||
|
{1, 1},
|
||||||
|
{2, 1},
|
||||||
|
{3, 1},
|
||||||
|
{4, 1},
|
||||||
|
{5, 1},
|
||||||
|
{6, 1},
|
||||||
|
{7, 1},
|
||||||
|
{8, 1},
|
||||||
|
{9, 1},
|
||||||
|
{10, 1},
|
||||||
|
|
||||||
|
-- 2 return values:
|
||||||
|
{0, 2},
|
||||||
|
{1, 2},
|
||||||
|
{2, 2},
|
||||||
|
{3, 2},
|
||||||
|
{4, 2},
|
||||||
|
{5, 2},
|
||||||
|
{6, 2},
|
||||||
|
{7, 2},
|
||||||
|
{8, 2},
|
||||||
|
{9, 2},
|
||||||
|
|
||||||
|
-- Special combinations:
|
||||||
|
{7, 3},
|
||||||
|
{8, 3},
|
||||||
|
{9, 5},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- Writes a single overloaded function definition for the specified number of params and returns into f
|
||||||
|
--[[
|
||||||
|
The format for the generated function is this:
|
||||||
|
/** Call the specified 3-param 2-return Lua function:
|
||||||
|
Returns true if call succeeded, false if there was an error. */
|
||||||
|
template <typename FnT, typename ParamT1, typename ParamT2, typename ParamT3, typename RetT1, typename RetT2>
|
||||||
|
bool Call(FnT a_Function, ParamT1 a_Param1, ParamT2 a_Param2, ParamT3 a_Param3, const cLuaState::cRet & a_RetMark, RetT1 & a_Ret1, RetT2 & a_Ret2)
|
||||||
|
{
|
||||||
|
UNUSED(a_RetMark);
|
||||||
|
if (!PushFunction(a_Function))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Push(a_Param1);
|
||||||
|
Push(a_Param2);
|
||||||
|
Push(a_Param3);
|
||||||
|
if (!CallFunction(2))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GetStackValue(-2, a_Ret1);
|
||||||
|
GetStackValue(-1, a_Ret2);
|
||||||
|
lua_pop(m_LuaState, 2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Note especially the negative numbers in GetStackValue() calls.
|
||||||
|
--]]
|
||||||
|
local function WriteOverload(f, a_NumParams, a_NumReturns)
|
||||||
|
-- Write the function doxy-comments:
|
||||||
|
f:write("/** Call the specified ", a_NumParams, "-param ", a_NumReturns, "-return Lua function:\n")
|
||||||
|
f:write("Returns true if call succeeded, false if there was an error. */\n")
|
||||||
|
|
||||||
|
-- Write the template <...> line:
|
||||||
|
f:write("template <typename FnT")
|
||||||
|
for i = 1, a_NumParams do
|
||||||
|
f:write(", typename ParamT", i)
|
||||||
|
end
|
||||||
|
if (a_NumReturns > 0) then
|
||||||
|
for i = 1, a_NumReturns do
|
||||||
|
f:write(", typename RetT", i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:write(">\n")
|
||||||
|
|
||||||
|
-- Write the function signature:
|
||||||
|
f:write("bool Call(")
|
||||||
|
f:write("FnT a_Function")
|
||||||
|
for i = 1, a_NumParams do
|
||||||
|
f:write(", ParamT", i, " a_Param", i)
|
||||||
|
end
|
||||||
|
if (a_NumReturns > 0) then
|
||||||
|
f:write(", const cLuaState::cRet & a_RetMark")
|
||||||
|
for i = 1, a_NumReturns do
|
||||||
|
f:write(", RetT", i, " & a_Ret", i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
f:write(")\n")
|
||||||
|
|
||||||
|
-- Common code:
|
||||||
|
f:write("{\n")
|
||||||
|
if (a_NumReturns > 0) then
|
||||||
|
f:write("\tUNUSED(a_RetMark);\n")
|
||||||
|
end
|
||||||
|
f:write("\tif (!PushFunction(a_Function))\n")
|
||||||
|
f:write("\t{\n")
|
||||||
|
f:write("\t\treturn false;\n")
|
||||||
|
f:write("\t}\n")
|
||||||
|
|
||||||
|
-- Push the params:
|
||||||
|
for i = 1, a_NumParams do
|
||||||
|
f:write("\tPush(a_Param", i, ");\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call the function:
|
||||||
|
f:write("\tif (!CallFunction(", a_NumReturns, "))\n")
|
||||||
|
f:write("\t{\n")
|
||||||
|
f:write("\t\treturn false;\n")
|
||||||
|
f:write("\t}\n")
|
||||||
|
|
||||||
|
-- Get the return values:
|
||||||
|
for i = 1, a_NumReturns do
|
||||||
|
f:write("\tGetStackValue(", -1 - a_NumReturns + i, ", a_Ret", i, ");\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pop the returns off the stack, if needed:
|
||||||
|
if (a_NumReturns > 0) then
|
||||||
|
f:write("\tlua_pop(m_LuaState, ", a_NumReturns, ");\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Everything ok:
|
||||||
|
f:write("\treturn true;\n")
|
||||||
|
f:write("}\n")
|
||||||
|
|
||||||
|
-- Separate from the next function:
|
||||||
|
f:write("\n\n\n\n\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local f = assert(io.open("LuaState_Call.inc", "w"))
|
||||||
|
|
||||||
|
-- Write file header:
|
||||||
|
f:write([[
|
||||||
|
// LuaState_Call.inc
|
||||||
|
|
||||||
|
// This file is auto-generated by gen_LuaState_Call.lua
|
||||||
|
// Make changes to the generator instead of to this file!
|
||||||
|
|
||||||
|
// This file contains the various overloads for the cLuaState::Call() function
|
||||||
|
// Each overload handles a different number of parameters / return values
|
||||||
|
]])
|
||||||
|
f:write("\n\n\n\n\n")
|
||||||
|
|
||||||
|
-- Write out a template function for each overload:
|
||||||
|
for _, combination in ipairs(Combinations) do
|
||||||
|
WriteOverload(f, combination[1], combination[2])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Close the generated file
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print("LuaState_Call.inc generated")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3,6 +3,20 @@ local disable_virtual_hooks = true
|
|||||||
local enable_pure_virtual = true
|
local enable_pure_virtual = true
|
||||||
local default_private_access = false
|
local default_private_access = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Code generators used by the build
|
||||||
|
-- Note that these are not exactly needed for the bindings, but rather we
|
||||||
|
-- misuse tolua's Lua engine to process files for us
|
||||||
|
dofile("gen_LuaState_Call.lua")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local access = {public = 0, protected = 1, private = 2}
|
local access = {public = 0, protected = 1, private = 2}
|
||||||
|
|
||||||
function preparse_hook(p)
|
function preparse_hook(p)
|
||||||
|
@ -28,24 +28,26 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
|
|||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_BEACON: return new cBeaconEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_BEACON: return new cBeaconEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
|
||||||
case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_COMMAND_BLOCK: return new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_DISPENSER: return new cDispenserEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_DROPPER: return new cDropperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
|
||||||
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
|
||||||
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||||
|
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
|
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
|
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||||
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
|
case E_BLOCK_TRAPPED_CHEST: return new cChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World, a_BlockType);
|
||||||
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_WALLSIGN: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
case E_BLOCK_NOTE_BLOCK: return new cNoteEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||||
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
|
||||||
}
|
}
|
||||||
LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
|
LOGD("%s: Requesting creation of an unknown block entity - block type %d (%s)",
|
||||||
__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
|
__FUNCTION__, a_BlockType, ItemTypeToString(a_BlockType).c_str()
|
||||||
);
|
);
|
||||||
|
ASSERT(!"Requesting creation of an unknown block entity");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
|
cChestEntity::cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type) :
|
||||||
super(E_BLOCK_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World)
|
super(a_Type, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
|
||||||
|
m_NumActivePlayers(0)
|
||||||
{
|
{
|
||||||
cBlockEntityWindowOwner::SetBlockEntity(this);
|
cBlockEntityWindowOwner::SetBlockEntity(this);
|
||||||
}
|
}
|
||||||
@ -113,7 +114,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
|
|||||||
// The few false positives aren't much to worry about
|
// The few false positives aren't much to worry about
|
||||||
int ChunkX, ChunkZ;
|
int ChunkX, ChunkZ;
|
||||||
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
|
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
|
||||||
m_World->MarkChunkDirty(ChunkX, ChunkZ);
|
m_World->MarkChunkDirty(ChunkX, ChunkZ, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@ public:
|
|||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
/// Constructor used for normal operation
|
/** Constructor used for normal operation */
|
||||||
cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
cChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World, BLOCKTYPE a_Type);
|
||||||
|
|
||||||
virtual ~cChestEntity();
|
virtual ~cChestEntity();
|
||||||
|
|
||||||
@ -48,8 +48,20 @@ public:
|
|||||||
virtual void SendTo(cClientHandle & a_Client) override;
|
virtual void SendTo(cClientHandle & a_Client) override;
|
||||||
virtual void UsedBy(cPlayer * a_Player) override;
|
virtual void UsedBy(cPlayer * a_Player) override;
|
||||||
|
|
||||||
/// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate.
|
/** Opens a new chest window for this chest.
|
||||||
|
Scans for neighbors to open a double chest window, if appropriate. */
|
||||||
void OpenNewWindow(void);
|
void OpenNewWindow(void);
|
||||||
|
|
||||||
|
/** Gets the number of players who currently have this chest open */
|
||||||
|
int GetNumberOfPlayers(void) const { return m_NumActivePlayers; }
|
||||||
|
|
||||||
|
/** Sets the number of players who currently have this chest open */
|
||||||
|
void SetNumberOfPlayers(int a_NumActivePlayers) { m_NumActivePlayers = a_NumActivePlayers; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Number of players who currently have this chest open */
|
||||||
|
int m_NumActivePlayers;
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,9 +12,8 @@
|
|||||||
|
|
||||||
|
|
||||||
cEnderChestEntity::cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
|
cEnderChestEntity::cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
|
||||||
super(E_BLOCK_ENDER_CHEST, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World)
|
super(E_BLOCK_ENDER_CHEST, a_BlockX, a_BlockY, a_BlockZ, a_World)
|
||||||
{
|
{
|
||||||
cBlockEntityWindowOwner::SetBlockEntity(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -34,60 +33,6 @@ cEnderChestEntity::~cEnderChestEntity()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cEnderChestEntity::LoadFromJson(const Json::Value & a_Value)
|
|
||||||
{
|
|
||||||
m_PosX = a_Value.get("x", 0).asInt();
|
|
||||||
m_PosY = a_Value.get("y", 0).asInt();
|
|
||||||
m_PosZ = a_Value.get("z", 0).asInt();
|
|
||||||
|
|
||||||
Json::Value AllSlots = a_Value.get("Slots", 0);
|
|
||||||
int SlotIdx = 0;
|
|
||||||
for (Json::Value::iterator itr = AllSlots.begin(); itr != AllSlots.end(); ++itr)
|
|
||||||
{
|
|
||||||
cItem Item;
|
|
||||||
Item.FromJson(*itr);
|
|
||||||
SetSlot(SlotIdx, Item);
|
|
||||||
SlotIdx++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEnderChestEntity::SaveToJson(Json::Value & a_Value)
|
|
||||||
{
|
|
||||||
a_Value["x"] = m_PosX;
|
|
||||||
a_Value["y"] = m_PosY;
|
|
||||||
a_Value["z"] = m_PosZ;
|
|
||||||
|
|
||||||
Json::Value AllSlots;
|
|
||||||
for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
Json::Value Slot;
|
|
||||||
m_Contents.GetSlot(i).GetJson(Slot);
|
|
||||||
AllSlots.append(Slot);
|
|
||||||
}
|
|
||||||
a_Value["Slots"] = AllSlots;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEnderChestEntity::SendTo(cClientHandle & a_Client)
|
|
||||||
{
|
|
||||||
// The chest entity doesn't need anything sent to the client when it's created / gets in the viewdistance
|
|
||||||
// All the actual handling is in the cWindow UI code that gets called when the chest is rclked
|
|
||||||
|
|
||||||
UNUSED(a_Client);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEnderChestEntity::UsedBy(cPlayer * a_Player)
|
void cEnderChestEntity::UsedBy(cPlayer * a_Player)
|
||||||
{
|
{
|
||||||
// If the window is not created, open it anew:
|
// If the window is not created, open it anew:
|
||||||
@ -106,21 +51,13 @@ void cEnderChestEntity::UsedBy(cPlayer * a_Player)
|
|||||||
a_Player->OpenWindow(Window);
|
a_Player->OpenWindow(Window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is rather a hack
|
|
||||||
// Instead of marking the chunk as dirty upon chest contents change, we mark it dirty now
|
|
||||||
// We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first.
|
|
||||||
// The few false positives aren't much to worry about
|
|
||||||
int ChunkX, ChunkZ;
|
|
||||||
cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
|
|
||||||
m_World->MarkChunkDirty(ChunkX, ChunkZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEnderChestEntity::OpenNewWindow(void)
|
void cEnderChestEntity::OpenNewWindow()
|
||||||
{
|
{
|
||||||
OpenWindow(new cEnderChestWindow(this));
|
OpenWindow(new cEnderChestWindow(this));
|
||||||
}
|
}
|
||||||
@ -128,3 +65,33 @@ void cEnderChestEntity::OpenNewWindow(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cEnderChestEntity::LoadFromJson(const Json::Value & a_Value, cItemGrid & a_Grid)
|
||||||
|
{
|
||||||
|
int SlotIdx = 0;
|
||||||
|
for (Json::Value::iterator itr = a_Value.begin(); itr != a_Value.end(); ++itr)
|
||||||
|
{
|
||||||
|
cItem Item;
|
||||||
|
Item.FromJson(*itr);
|
||||||
|
a_Grid.SetSlot(SlotIdx, Item);
|
||||||
|
SlotIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cEnderChestEntity::SaveToJson(Json::Value & a_Value, const cItemGrid & a_Grid)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < a_Grid.GetNumSlots(); i++)
|
||||||
|
{
|
||||||
|
Json::Value Slot;
|
||||||
|
a_Grid.GetSlot(i).GetJson(Slot);
|
||||||
|
a_Value.append(Slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,20 +1,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BlockEntityWithItems.h"
|
#include "BlockEntity.h"
|
||||||
|
#include "UI/WindowOwner.h"
|
||||||
|
#include "json/json.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Json
|
|
||||||
{
|
|
||||||
class Value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class cClientHandle;
|
|
||||||
class cServer;
|
|
||||||
class cNBTData;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -22,33 +11,28 @@ class cNBTData;
|
|||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
class cEnderChestEntity :
|
class cEnderChestEntity :
|
||||||
public cBlockEntityWithItems
|
public cBlockEntity,
|
||||||
|
public cBlockEntityWindowOwner
|
||||||
{
|
{
|
||||||
typedef cBlockEntityWithItems super;
|
typedef cBlockEntity super;
|
||||||
|
|
||||||
public:
|
|
||||||
enum {
|
|
||||||
ContentsHeight = 3,
|
|
||||||
ContentsWidth = 9,
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
public:
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
/// Constructor used for normal operation
|
cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
||||||
cEnderChestEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
|
||||||
|
|
||||||
virtual ~cEnderChestEntity();
|
virtual ~cEnderChestEntity();
|
||||||
|
|
||||||
static const char * GetClassStatic(void) { return "cEnderChestEntity"; }
|
static const char * GetClassStatic(void) { return "cEnderChestEntity"; }
|
||||||
|
|
||||||
bool LoadFromJson(const Json::Value & a_Value);
|
|
||||||
|
|
||||||
// cBlockEntity overrides:
|
// cBlockEntity overrides:
|
||||||
virtual void SaveToJson(Json::Value & a_Value) override;
|
|
||||||
virtual void SendTo(cClientHandle & a_Client) override;
|
|
||||||
virtual void UsedBy(cPlayer * a_Player) override;
|
virtual void UsedBy(cPlayer * a_Player) override;
|
||||||
|
virtual void SaveToJson(Json::Value & a_Value) override { UNUSED(a_Value); }
|
||||||
|
virtual void SendTo(cClientHandle & a_Client) override { UNUSED(a_Client); }
|
||||||
|
|
||||||
|
static void LoadFromJson(const Json::Value & a_Value, cItemGrid & a_Grid);
|
||||||
|
static void SaveToJson(Json::Value & a_Value, const cItemGrid & a_Grid);
|
||||||
|
|
||||||
/// Opens a new chest window for this chest. Scans for neighbors to open a double chest window, if appropriate.
|
/** Opens a new enderchest window for this enderchest */
|
||||||
void OpenNewWindow(void);
|
void OpenNewWindow(void);
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
@ -157,6 +157,7 @@ bool cHopperEntity::MoveItemsIn(cChunk & a_Chunk, Int64 a_CurrentTick)
|
|||||||
bool res = false;
|
bool res = false;
|
||||||
switch (a_Chunk.GetBlock(m_RelX, m_PosY + 1, m_RelZ))
|
switch (a_Chunk.GetBlock(m_RelX, m_PosY + 1, m_RelZ))
|
||||||
{
|
{
|
||||||
|
case E_BLOCK_TRAPPED_CHEST:
|
||||||
case E_BLOCK_CHEST:
|
case E_BLOCK_CHEST:
|
||||||
{
|
{
|
||||||
// Chests have special handling because of double-chests
|
// Chests have special handling because of double-chests
|
||||||
@ -322,6 +323,7 @@ bool cHopperEntity::MoveItemsOut(cChunk & a_Chunk, Int64 a_CurrentTick)
|
|||||||
bool res = false;
|
bool res = false;
|
||||||
switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ))
|
switch (DestChunk->GetBlock(OutRelX, OutY, OutRelZ))
|
||||||
{
|
{
|
||||||
|
case E_BLOCK_TRAPPED_CHEST:
|
||||||
case E_BLOCK_CHEST:
|
case E_BLOCK_CHEST:
|
||||||
{
|
{
|
||||||
// Chests have special handling because of double-chests
|
// Chests have special handling because of double-chests
|
||||||
@ -378,7 +380,7 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the chest is a double-chest, if so, try to move from there:
|
// Check if the chest is a double-chest (chest directly above was empty), if so, try to move from there:
|
||||||
static const struct
|
static const struct
|
||||||
{
|
{
|
||||||
int x, z;
|
int x, z;
|
||||||
@ -395,13 +397,18 @@ bool cHopperEntity::MoveItemsFromChest(cChunk & a_Chunk)
|
|||||||
int x = m_RelX + Coords[i].x;
|
int x = m_RelX + Coords[i].x;
|
||||||
int z = m_RelZ + Coords[i].z;
|
int z = m_RelZ + Coords[i].z;
|
||||||
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
|
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
|
||||||
if (
|
if (Neighbor == NULL)
|
||||||
(Neighbor == NULL) ||
|
|
||||||
(Neighbor->GetBlock(x, m_PosY + 1, z) != E_BLOCK_CHEST)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLOCKTYPE Block = Neighbor->GetBlock(x, m_PosY + 1, z);
|
||||||
|
if (Block != Chest->GetBlockType())
|
||||||
|
{
|
||||||
|
// Not the same kind of chest
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Chest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
|
Chest = (cChestEntity *)Neighbor->GetBlockEntity(m_PosX + Coords[i].x, m_PosY + 1, m_PosZ + Coords[i].z);
|
||||||
if (Chest == NULL)
|
if (Chest == NULL)
|
||||||
{
|
{
|
||||||
@ -550,10 +557,11 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
|
|||||||
}
|
}
|
||||||
if (MoveItemsToGrid(*Chest))
|
if (MoveItemsToGrid(*Chest))
|
||||||
{
|
{
|
||||||
|
// Chest block directly connected was not full
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the chest is a double-chest, if so, try to move into the other half:
|
// Check if the chest is a double-chest (chest block directly connected was full), if so, try to move into the other half:
|
||||||
static const struct
|
static const struct
|
||||||
{
|
{
|
||||||
int x, z;
|
int x, z;
|
||||||
@ -572,13 +580,18 @@ bool cHopperEntity::MoveItemsToChest(cChunk & a_Chunk, int a_BlockX, int a_Block
|
|||||||
int x = RelX + Coords[i].x;
|
int x = RelX + Coords[i].x;
|
||||||
int z = RelZ + Coords[i].z;
|
int z = RelZ + Coords[i].z;
|
||||||
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
|
cChunk * Neighbor = a_Chunk.GetRelNeighborChunkAdjustCoords(x, z);
|
||||||
if (
|
if (Neighbor == NULL)
|
||||||
(Neighbor == NULL) ||
|
|
||||||
(Neighbor->GetBlock(x, a_BlockY, z) != E_BLOCK_CHEST)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BLOCKTYPE Block = Neighbor->GetBlock(x, a_BlockY, z);
|
||||||
|
if (Block != Chest->GetBlockType())
|
||||||
|
{
|
||||||
|
// Not the same kind of chest
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z);
|
Chest = (cChestEntity *)Neighbor->GetBlockEntity(a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z);
|
||||||
if (Chest == NULL)
|
if (Chest == NULL)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +101,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
|||||||
a_Info[E_BLOCK_NEW_LEAVES ].m_SpreadLightFalloff = 1;
|
a_Info[E_BLOCK_NEW_LEAVES ].m_SpreadLightFalloff = 1;
|
||||||
a_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1;
|
a_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1;
|
||||||
a_Info[E_BLOCK_TORCH ].m_SpreadLightFalloff = 1;
|
a_Info[E_BLOCK_TORCH ].m_SpreadLightFalloff = 1;
|
||||||
|
a_Info[E_BLOCK_TRAPPED_CHEST ].m_SpreadLightFalloff = 1;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE ].m_SpreadLightFalloff = 1;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_SpreadLightFalloff = 1;
|
||||||
a_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
|
a_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
|
||||||
a_Info[E_BLOCK_WALLSIGN ].m_SpreadLightFalloff = 1;
|
a_Info[E_BLOCK_WALLSIGN ].m_SpreadLightFalloff = 1;
|
||||||
a_Info[E_BLOCK_WOODEN_DOOR ].m_SpreadLightFalloff = 1;
|
a_Info[E_BLOCK_WOODEN_DOOR ].m_SpreadLightFalloff = 1;
|
||||||
@ -160,6 +163,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
|||||||
a_Info[E_BLOCK_STATIONARY_WATER ].m_Transparent = true;
|
a_Info[E_BLOCK_STATIONARY_WATER ].m_Transparent = true;
|
||||||
a_Info[E_BLOCK_STONE_BUTTON ].m_Transparent = true;
|
a_Info[E_BLOCK_STONE_BUTTON ].m_Transparent = true;
|
||||||
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_Transparent = true;
|
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_Transparent = true;
|
||||||
|
a_Info[E_BLOCK_TRAPPED_CHEST ].m_Transparent = true;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE ].m_Transparent = true;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_Transparent = true;
|
||||||
a_Info[E_BLOCK_TALL_GRASS ].m_Transparent = true;
|
a_Info[E_BLOCK_TALL_GRASS ].m_Transparent = true;
|
||||||
a_Info[E_BLOCK_TORCH ].m_Transparent = true;
|
a_Info[E_BLOCK_TORCH ].m_Transparent = true;
|
||||||
a_Info[E_BLOCK_VINES ].m_Transparent = true;
|
a_Info[E_BLOCK_VINES ].m_Transparent = true;
|
||||||
@ -197,6 +203,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
|||||||
a_Info[E_BLOCK_TNT ].m_OneHitDig = true;
|
a_Info[E_BLOCK_TNT ].m_OneHitDig = true;
|
||||||
a_Info[E_BLOCK_TALL_GRASS ].m_OneHitDig = true;
|
a_Info[E_BLOCK_TALL_GRASS ].m_OneHitDig = true;
|
||||||
a_Info[E_BLOCK_TORCH ].m_OneHitDig = true;
|
a_Info[E_BLOCK_TORCH ].m_OneHitDig = true;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE ].m_OneHitDig = true;
|
||||||
|
|
||||||
|
|
||||||
// Blocks that break when pushed by piston:
|
// Blocks that break when pushed by piston:
|
||||||
@ -239,6 +246,8 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
|||||||
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_PistonBreakable = true;
|
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_PistonBreakable = true;
|
||||||
a_Info[E_BLOCK_TALL_GRASS ].m_PistonBreakable = true;
|
a_Info[E_BLOCK_TALL_GRASS ].m_PistonBreakable = true;
|
||||||
a_Info[E_BLOCK_TORCH ].m_PistonBreakable = true;
|
a_Info[E_BLOCK_TORCH ].m_PistonBreakable = true;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE ].m_PistonBreakable = true;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_PistonBreakable = true;
|
||||||
a_Info[E_BLOCK_VINES ].m_PistonBreakable = true;
|
a_Info[E_BLOCK_VINES ].m_PistonBreakable = true;
|
||||||
a_Info[E_BLOCK_WATER ].m_PistonBreakable = true;
|
a_Info[E_BLOCK_WATER ].m_PistonBreakable = true;
|
||||||
a_Info[E_BLOCK_WOODEN_BUTTON ].m_PistonBreakable = true;
|
a_Info[E_BLOCK_WOODEN_BUTTON ].m_PistonBreakable = true;
|
||||||
@ -280,6 +289,9 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
|||||||
a_Info[E_BLOCK_TALL_GRASS ].m_IsSnowable = false;
|
a_Info[E_BLOCK_TALL_GRASS ].m_IsSnowable = false;
|
||||||
a_Info[E_BLOCK_TNT ].m_IsSnowable = false;
|
a_Info[E_BLOCK_TNT ].m_IsSnowable = false;
|
||||||
a_Info[E_BLOCK_TORCH ].m_IsSnowable = false;
|
a_Info[E_BLOCK_TORCH ].m_IsSnowable = false;
|
||||||
|
a_Info[E_BLOCK_TRAPPED_CHEST ].m_IsSnowable = false;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE ].m_IsSnowable = false;
|
||||||
|
a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_IsSnowable = false;
|
||||||
a_Info[E_BLOCK_VINES ].m_IsSnowable = false;
|
a_Info[E_BLOCK_VINES ].m_IsSnowable = false;
|
||||||
a_Info[E_BLOCK_WALLSIGN ].m_IsSnowable = false;
|
a_Info[E_BLOCK_WALLSIGN ].m_IsSnowable = false;
|
||||||
a_Info[E_BLOCK_WATER ].m_IsSnowable = false;
|
a_Info[E_BLOCK_WATER ].m_IsSnowable = false;
|
||||||
@ -356,7 +368,6 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
|
|||||||
a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_IsSolid = false;
|
a_Info[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE].m_IsSolid = false;
|
||||||
a_Info[E_BLOCK_MELON_STEM ].m_IsSolid = false;
|
a_Info[E_BLOCK_MELON_STEM ].m_IsSolid = false;
|
||||||
a_Info[E_BLOCK_NETHER_PORTAL ].m_IsSolid = false;
|
a_Info[E_BLOCK_NETHER_PORTAL ].m_IsSolid = false;
|
||||||
a_Info[E_BLOCK_PISTON_EXTENSION ].m_IsSolid = false;
|
|
||||||
a_Info[E_BLOCK_POTATOES ].m_IsSolid = false;
|
a_Info[E_BLOCK_POTATOES ].m_IsSolid = false;
|
||||||
a_Info[E_BLOCK_POWERED_RAIL ].m_IsSolid = false;
|
a_Info[E_BLOCK_POWERED_RAIL ].m_IsSolid = false;
|
||||||
a_Info[E_BLOCK_RAIL ].m_IsSolid = false;
|
a_Info[E_BLOCK_RAIL ].m_IsSolid = false;
|
||||||
|
@ -23,6 +23,7 @@ public:
|
|||||||
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08);
|
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) | 0x08);
|
||||||
|
|
||||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
|
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
|
||||||
|
a_WorldInterface.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
|
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
|
||||||
|
|
||||||
// Queue a button reset (unpress)
|
// Queue a button reset (unpress)
|
||||||
@ -102,7 +103,7 @@ public:
|
|||||||
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
|
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
|
||||||
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
|
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
|
||||||
|
|
||||||
return (a_RelY > 0) && (cBlockInfo::IsSolid(BlockIsOn));
|
return (a_RelY > 0) && (cBlockInfo::FullyOccupiesVoxel(BlockIsOn));
|
||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
@ -44,16 +44,16 @@ public:
|
|||||||
}
|
}
|
||||||
double yaw = a_Player->GetYaw();
|
double yaw = a_Player->GetYaw();
|
||||||
if (
|
if (
|
||||||
(Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(0, 0, 1) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
|
(Area.GetRelBlockType(2, 0, 1) == m_BlockType)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
a_BlockMeta = ((yaw >= -90) && (yaw < 90)) ? 2 : 3;
|
a_BlockMeta = ((yaw >= -90) && (yaw < 90)) ? 2 : 3;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
(Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(0, 0, 1) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
|
(Area.GetRelBlockType(2, 0, 1) == m_BlockType)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// FIXME: This is unreachable, as the condition is the same as the above one
|
// FIXME: This is unreachable, as the condition is the same as the above one
|
||||||
@ -130,12 +130,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int NumChestNeighbors = 0;
|
int NumChestNeighbors = 0;
|
||||||
if (Area.GetRelBlockType(1, 0, 2) == E_BLOCK_CHEST)
|
if (Area.GetRelBlockType(1, 0, 2) == m_BlockType)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
(Area.GetRelBlockType(0, 0, 2) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(0, 0, 2) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(1, 0, 1) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(1, 0, 1) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(1, 0, 3) == E_BLOCK_CHEST)
|
(Area.GetRelBlockType(1, 0, 3) == m_BlockType)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Already a doublechest neighbor, disallow:
|
// Already a doublechest neighbor, disallow:
|
||||||
@ -143,12 +143,12 @@ public:
|
|||||||
}
|
}
|
||||||
NumChestNeighbors += 1;
|
NumChestNeighbors += 1;
|
||||||
}
|
}
|
||||||
if (Area.GetRelBlockType(3, 0, 2) == E_BLOCK_CHEST)
|
if (Area.GetRelBlockType(3, 0, 2) == m_BlockType)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
(Area.GetRelBlockType(4, 0, 2) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(4, 0, 2) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(3, 0, 1) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(3, 0, 1) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(3, 0, 3) == E_BLOCK_CHEST)
|
(Area.GetRelBlockType(3, 0, 3) == m_BlockType)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Already a doublechest neighbor, disallow:
|
// Already a doublechest neighbor, disallow:
|
||||||
@ -156,12 +156,12 @@ public:
|
|||||||
}
|
}
|
||||||
NumChestNeighbors += 1;
|
NumChestNeighbors += 1;
|
||||||
}
|
}
|
||||||
if (Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
|
if (Area.GetRelBlockType(2, 0, 1) == m_BlockType)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
(Area.GetRelBlockType(2, 0, 0) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(2, 0, 0) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(1, 0, 1) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(1, 0, 1) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(3, 0, 1) == E_BLOCK_CHEST)
|
(Area.GetRelBlockType(3, 0, 1) == m_BlockType)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Already a doublechest neighbor, disallow:
|
// Already a doublechest neighbor, disallow:
|
||||||
@ -169,12 +169,12 @@ public:
|
|||||||
}
|
}
|
||||||
NumChestNeighbors += 1;
|
NumChestNeighbors += 1;
|
||||||
}
|
}
|
||||||
if (Area.GetRelBlockType(2, 0, 3) == E_BLOCK_CHEST)
|
if (Area.GetRelBlockType(2, 0, 3) == m_BlockType)
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
(Area.GetRelBlockType(2, 0, 4) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(2, 0, 4) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(1, 0, 3) == E_BLOCK_CHEST) ||
|
(Area.GetRelBlockType(1, 0, 3) == m_BlockType) ||
|
||||||
(Area.GetRelBlockType(3, 0, 3) == E_BLOCK_CHEST)
|
(Area.GetRelBlockType(3, 0, 3) == m_BlockType)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Already a doublechest neighbor, disallow:
|
// Already a doublechest neighbor, disallow:
|
||||||
@ -217,7 +217,7 @@ public:
|
|||||||
/// If there's a chest in the a_Area in the specified coords, modifies its meta to a_NewMeta and returns true.
|
/// If there's a chest in the a_Area in the specified coords, modifies its meta to a_NewMeta and returns true.
|
||||||
bool CheckAndAdjustNeighbor(cChunkInterface & a_ChunkInterface, const cBlockArea & a_Area, int a_RelX, int a_RelZ, NIBBLETYPE a_NewMeta)
|
bool CheckAndAdjustNeighbor(cChunkInterface & a_ChunkInterface, const cBlockArea & a_Area, int a_RelX, int a_RelZ, NIBBLETYPE a_NewMeta)
|
||||||
{
|
{
|
||||||
if (a_Area.GetRelBlockType(a_RelX, 0, a_RelZ) != E_BLOCK_CHEST)
|
if (a_Area.GetRelBlockType(a_RelX, 0, a_RelZ) != m_BlockType)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -228,7 +228,7 @@ public:
|
|||||||
|
|
||||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||||
{
|
{
|
||||||
a_Pickups.push_back(cItem(E_BLOCK_CHEST, 1, 0));
|
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
|
||||||
}
|
}
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@
|
|||||||
#include "BlockRedstoneRepeater.h"
|
#include "BlockRedstoneRepeater.h"
|
||||||
#include "BlockRedstoneTorch.h"
|
#include "BlockRedstoneTorch.h"
|
||||||
#include "BlockTNT.h"
|
#include "BlockTNT.h"
|
||||||
|
#include "BlockTripwire.h"
|
||||||
|
#include "BlockTripwireHook.h"
|
||||||
#include "BlockSand.h"
|
#include "BlockSand.h"
|
||||||
#include "BlockSapling.h"
|
#include "BlockSapling.h"
|
||||||
#include "BlockSideways.h"
|
#include "BlockSideways.h"
|
||||||
@ -174,7 +176,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
|||||||
{
|
{
|
||||||
switch(a_BlockType)
|
switch(a_BlockType)
|
||||||
{
|
{
|
||||||
// Block handlers, alphabetically sorted:
|
// Block handlers, alphabetically sorted:
|
||||||
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||||
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
|
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
|
||||||
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
|
case E_BLOCK_ANVIL: return new cBlockAnvilHandler (a_BlockType);
|
||||||
@ -236,9 +238,9 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
|||||||
case E_BLOCK_LAPIS_ORE: return new cBlockOreHandler (a_BlockType);
|
case E_BLOCK_LAPIS_ORE: return new cBlockOreHandler (a_BlockType);
|
||||||
case E_BLOCK_LAVA: return new cBlockLavaHandler (a_BlockType);
|
case E_BLOCK_LAVA: return new cBlockLavaHandler (a_BlockType);
|
||||||
case E_BLOCK_LEAVES: return new cBlockLeavesHandler (a_BlockType);
|
case E_BLOCK_LEAVES: return new cBlockLeavesHandler (a_BlockType);
|
||||||
|
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
|
||||||
case E_BLOCK_LILY_PAD: return new cBlockLilypadHandler (a_BlockType);
|
case E_BLOCK_LILY_PAD: return new cBlockLilypadHandler (a_BlockType);
|
||||||
case E_BLOCK_LIT_FURNACE: return new cBlockFurnaceHandler (a_BlockType);
|
case E_BLOCK_LIT_FURNACE: return new cBlockFurnaceHandler (a_BlockType);
|
||||||
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE: return new cBlockPressurePlateHandler(a_BlockType);
|
|
||||||
case E_BLOCK_LOG: return new cBlockSidewaysHandler (a_BlockType);
|
case E_BLOCK_LOG: return new cBlockSidewaysHandler (a_BlockType);
|
||||||
case E_BLOCK_MELON: return new cBlockMelonHandler (a_BlockType);
|
case E_BLOCK_MELON: return new cBlockMelonHandler (a_BlockType);
|
||||||
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
|
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
|
||||||
@ -291,6 +293,9 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
|||||||
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
|
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
|
||||||
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
|
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
|
||||||
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
|
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
|
||||||
|
case E_BLOCK_TRAPPED_CHEST: return new cBlockChestHandler (a_BlockType);
|
||||||
|
case E_BLOCK_TRIPWIRE: return new cBlockTripwireHandler (a_BlockType);
|
||||||
|
case E_BLOCK_TRIPWIRE_HOOK: return new cBlockTripwireHookHandler (a_BlockType);
|
||||||
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
|
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
|
||||||
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType); // TODO: This needs a special handler
|
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType); // TODO: This needs a special handler
|
||||||
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
|
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
|
||||||
|
@ -22,7 +22,8 @@ public:
|
|||||||
// Flip the ON bit on/off using the XOR bitwise operation
|
// Flip the ON bit on/off using the XOR bitwise operation
|
||||||
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08);
|
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08);
|
||||||
|
|
||||||
a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LEVER, Meta); // SetMeta doesn't work for unpowering levers, so setblock
|
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
|
||||||
|
a_WorldInterface.WakeUpSimulators(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
|
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ public:
|
|||||||
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
|
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
|
||||||
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
|
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
|
||||||
|
|
||||||
return (a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn);
|
return (a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ int cBlockPistonHandler::FirstPassthroughBlock(int a_PistonX, int a_PistonY, int
|
|||||||
NIBBLETYPE currMeta;
|
NIBBLETYPE currMeta;
|
||||||
AddPistonDir(a_PistonX, a_PistonY, a_PistonZ, pistonmeta, 1);
|
AddPistonDir(a_PistonX, a_PistonY, a_PistonZ, pistonmeta, 1);
|
||||||
a_World->GetBlockTypeMeta(a_PistonX, a_PistonY, a_PistonZ, currBlock, currMeta);
|
a_World->GetBlockTypeMeta(a_PistonX, a_PistonY, a_PistonZ, currBlock, currMeta);
|
||||||
if (CanBreakPush(currBlock))
|
if (cBlockInfo::IsPistonBreakable(currBlock))
|
||||||
{
|
{
|
||||||
// This block breaks when pushed, extend up to here
|
// This block breaks when pushed, extend up to here
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -104,6 +104,7 @@ private:
|
|||||||
case E_BLOCK_ENCHANTMENT_TABLE:
|
case E_BLOCK_ENCHANTMENT_TABLE:
|
||||||
case E_BLOCK_END_PORTAL:
|
case E_BLOCK_END_PORTAL:
|
||||||
case E_BLOCK_END_PORTAL_FRAME:
|
case E_BLOCK_END_PORTAL_FRAME:
|
||||||
|
// Notice the lack of an E_BLOCK_ENDER_CHEST here; its because ender chests can totally be pushed/pulled in MCS :)
|
||||||
case E_BLOCK_FURNACE:
|
case E_BLOCK_FURNACE:
|
||||||
case E_BLOCK_LIT_FURNACE:
|
case E_BLOCK_LIT_FURNACE:
|
||||||
case E_BLOCK_HOPPER:
|
case E_BLOCK_HOPPER:
|
||||||
@ -113,6 +114,7 @@ private:
|
|||||||
case E_BLOCK_NOTE_BLOCK:
|
case E_BLOCK_NOTE_BLOCK:
|
||||||
case E_BLOCK_OBSIDIAN:
|
case E_BLOCK_OBSIDIAN:
|
||||||
case E_BLOCK_PISTON_EXTENSION:
|
case E_BLOCK_PISTON_EXTENSION:
|
||||||
|
case E_BLOCK_TRAPPED_CHEST:
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -126,24 +128,10 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the specified block can be pushed by a piston and broken / replaced
|
|
||||||
static inline bool CanBreakPush(BLOCKTYPE a_BlockType) { return cBlockInfo::IsPistonBreakable(a_BlockType); }
|
|
||||||
|
|
||||||
/// Returns true if the specified block can be pulled by a sticky piston
|
/// Returns true if the specified block can be pulled by a sticky piston
|
||||||
static inline bool CanPull(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
static inline bool CanPull(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||||
{
|
{
|
||||||
switch (a_BlockType)
|
if (cBlockInfo::IsPistonBreakable(a_BlockType))
|
||||||
{
|
|
||||||
case E_BLOCK_LAVA:
|
|
||||||
case E_BLOCK_STATIONARY_LAVA:
|
|
||||||
case E_BLOCK_STATIONARY_WATER:
|
|
||||||
case E_BLOCK_WATER:
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CanBreakPush(a_BlockType))
|
|
||||||
{
|
{
|
||||||
return false; // CanBreakPush returns true, but we need false to prevent pulling
|
return false; // CanBreakPush returns true, but we need false to prevent pulling
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BlockHandler.h"
|
#include "BlockHandler.h"
|
||||||
#include "../MersenneTwister.h"
|
|
||||||
#include "../World.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,7 +154,11 @@ public:
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
(BlockInQuestion == E_BLOCK_GLASS) ||
|
(BlockInQuestion == E_BLOCK_GLASS) ||
|
||||||
|
(BlockInQuestion == E_BLOCK_STAINED_GLASS) ||
|
||||||
(BlockInQuestion == E_BLOCK_FENCE) ||
|
(BlockInQuestion == E_BLOCK_FENCE) ||
|
||||||
|
(BlockInQuestion == E_BLOCK_SOULSAND) ||
|
||||||
|
(BlockInQuestion == E_BLOCK_MOB_SPAWNER) ||
|
||||||
|
(BlockInQuestion == E_BLOCK_END_PORTAL_FRAME) || // Actual vanilla behaviour
|
||||||
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
|
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
|
||||||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)
|
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)
|
||||||
)
|
)
|
||||||
|
32
src/Blocks/BlockTripwire.h
Normal file
32
src/Blocks/BlockTripwire.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BlockHandler.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cBlockTripwireHandler :
|
||||||
|
public cBlockHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cBlockTripwireHandler(BLOCKTYPE a_BlockType)
|
||||||
|
: cBlockHandler(a_BlockType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||||
|
{
|
||||||
|
a_Pickups.push_back(cItem(E_ITEM_STRING, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char * GetStepSound(void) override
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
82
src/Blocks/BlockTripwireHook.h
Normal file
82
src/Blocks/BlockTripwireHook.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BlockHandler.h"
|
||||||
|
#include "MetaRotator.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cBlockTripwireHookHandler :
|
||||||
|
public cMetaRotator<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cBlockTripwireHookHandler(BLOCKTYPE a_BlockType)
|
||||||
|
: cMetaRotator<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01>(a_BlockType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetPlacementBlockTypeMeta(
|
||||||
|
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
||||||
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||||
|
int a_CursorX, int a_CursorY, int a_CursorZ,
|
||||||
|
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||||
|
) override
|
||||||
|
{
|
||||||
|
a_BlockType = m_BlockType;
|
||||||
|
|
||||||
|
a_BlockMeta = DirectionToMetadata(a_BlockFace);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static NIBBLETYPE DirectionToMetadata(eBlockFace a_Direction)
|
||||||
|
{
|
||||||
|
switch (a_Direction)
|
||||||
|
{
|
||||||
|
case BLOCK_FACE_XM: return 0x1;
|
||||||
|
case BLOCK_FACE_XP: return 0x3;
|
||||||
|
case BLOCK_FACE_ZM: return 0x2;
|
||||||
|
case BLOCK_FACE_ZP: return 0x0;
|
||||||
|
default: ASSERT(!"Unhandled tripwire hook direction!"); return 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static eBlockFace MetadataToDirection(NIBBLETYPE a_Meta)
|
||||||
|
{
|
||||||
|
switch (a_Meta & 0x03)
|
||||||
|
{
|
||||||
|
case 0x1: return BLOCK_FACE_XM;
|
||||||
|
case 0x3: return BLOCK_FACE_XP;
|
||||||
|
case 0x2: return BLOCK_FACE_ZM;
|
||||||
|
case 0x0: return BLOCK_FACE_ZP;
|
||||||
|
default: ASSERT(!"Unhandled tripwire hook metadata!"); return BLOCK_FACE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||||
|
{
|
||||||
|
// Reset meta to 0
|
||||||
|
a_Pickups.push_back(cItem(E_BLOCK_TRIPWIRE_HOOK, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||||
|
{
|
||||||
|
NIBBLETYPE Meta;
|
||||||
|
a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
|
||||||
|
|
||||||
|
AddFaceDirection(a_RelX, a_RelY, a_RelZ, MetadataToDirection(Meta), true);
|
||||||
|
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
|
||||||
|
|
||||||
|
return (a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char * GetStepSound(void) override
|
||||||
|
{
|
||||||
|
return "step.wood";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,4 +46,7 @@ public:
|
|||||||
|
|
||||||
virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0;
|
virtual void SetTimeOfDay(Int64 a_TimeOfDay) = 0;
|
||||||
|
|
||||||
|
/** Wakes up the simulators for the specified block */
|
||||||
|
virtual void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
cmake_minimum_required (VERSION 2.8.2)
|
cmake_minimum_required (VERSION 2.8.2)
|
||||||
project (MCServer)
|
project (MCServer)
|
||||||
|
|
||||||
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/")
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/")
|
||||||
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/jsoncpp/include")
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include")
|
||||||
include_directories (SYSTEM "${PROJECT_SOURCE_DIR}/../lib/polarssl/include")
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
|
||||||
|
|
||||||
set(FOLDERS OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++)
|
set(FOLDERS OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++)
|
||||||
set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities Generating/Prefabs)
|
set(FOLDERS ${FOLDERS} WorldStorage Mobs Entities Simulator UI BlockEntities Generating/Prefabs)
|
||||||
@ -12,6 +12,7 @@ set(BINDING_DEPENDECIES
|
|||||||
tolua
|
tolua
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua
|
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/virtual_method_hooks.lua
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg
|
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/AllToLua.pkg
|
||||||
|
Bindings/gen_LuaState_Call.lua
|
||||||
Bindings/LuaFunctions.h
|
Bindings/LuaFunctions.h
|
||||||
Bindings/LuaWindow.h
|
Bindings/LuaWindow.h
|
||||||
Bindings/Plugin.h
|
Bindings/Plugin.h
|
||||||
@ -79,16 +80,22 @@ set(BINDING_DEPENDECIES
|
|||||||
World.h
|
World.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# List all the files that are generated as part of the Bindings build process
|
||||||
|
set (BINDING_OUTPUTS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/Bindings/LuaState_Call.inc
|
||||||
|
)
|
||||||
|
|
||||||
include_directories(Bindings)
|
include_directories(Bindings)
|
||||||
include_directories(.)
|
include_directories(.)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
ADD_CUSTOM_COMMAND(
|
ADD_CUSTOM_COMMAND(
|
||||||
# add any new generated bindings here
|
OUTPUT ${BINDING_OUTPUTS}
|
||||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/Bindings.h
|
|
||||||
|
|
||||||
# Copy the Lua DLL into the Bindings folder, so that tolua can run from there:
|
# Copy the Lua DLL into the Bindings folder, so that tolua can run from there:
|
||||||
COMMAND copy /y ..\\..\\MCServer\\lua51.dll .
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ../../MCServer/lua51.dll ./lua51.dll
|
||||||
|
|
||||||
# Regenerate bindings:
|
# Regenerate bindings:
|
||||||
COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
|
COMMAND tolua -L virtual_method_hooks.lua -o Bindings.cpp -H Bindings.h AllToLua.pkg
|
||||||
@ -119,7 +126,8 @@ if (NOT MSVC)
|
|||||||
|
|
||||||
# lib dependencies are not included
|
# lib dependencies are not included
|
||||||
|
|
||||||
|
include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
|
||||||
|
|
||||||
#add cpp files here
|
#add cpp files here
|
||||||
add_library(Bindings
|
add_library(Bindings
|
||||||
Bindings/Bindings
|
Bindings/Bindings
|
||||||
@ -134,7 +142,7 @@ if (NOT MSVC)
|
|||||||
Bindings/WebPlugin
|
Bindings/WebPlugin
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(Bindings lua sqlite tolualib)
|
target_link_libraries(Bindings lua sqlite tolualib polarssl)
|
||||||
|
|
||||||
#clear file
|
#clear file
|
||||||
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt)
|
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/Bindings/BindingDependecies.txt)
|
||||||
@ -260,4 +268,4 @@ endif ()
|
|||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib)
|
target_link_libraries(${EXECUTABLE} expat tolualib ws2_32.lib Psapi.lib)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(${EXECUTABLE} md5 luaexpat iniFile jsoncpp polarssl zlib lua sqlite)
|
target_link_libraries(${EXECUTABLE} luaexpat iniFile jsoncpp polarssl zlib sqlite lua)
|
||||||
|
157
src/Chunk.cpp
157
src/Chunk.cpp
@ -87,7 +87,8 @@ cChunk::cChunk(
|
|||||||
m_NeighborZM(a_NeighborZM),
|
m_NeighborZM(a_NeighborZM),
|
||||||
m_NeighborZP(a_NeighborZP),
|
m_NeighborZP(a_NeighborZP),
|
||||||
m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()),
|
m_WaterSimulatorData(a_World->GetWaterSimulator()->CreateChunkData()),
|
||||||
m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData())
|
m_LavaSimulatorData (a_World->GetLavaSimulator ()->CreateChunkData()),
|
||||||
|
m_AlwaysTicked(0)
|
||||||
{
|
{
|
||||||
if (a_NeighborXM != NULL)
|
if (a_NeighborXM != NULL)
|
||||||
{
|
{
|
||||||
@ -463,7 +464,7 @@ void cChunk::CollectMobCensus(cMobCensus& toFill)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a_MaxY, int a_MaxZ)
|
void cChunk::GetThreeRandomNumbers(int & a_X, int & a_Y, int & a_Z,int a_MaxX, int a_MaxY, int a_MaxZ)
|
||||||
{
|
{
|
||||||
ASSERT(a_MaxX * a_MaxY * a_MaxZ * 8 < 0x00ffffff);
|
ASSERT(a_MaxX * a_MaxY * a_MaxZ * 8 < 0x00ffffff);
|
||||||
int Random = m_World->GetTickRandomNumber(0x00ffffff);
|
int Random = m_World->GetTickRandomNumber(0x00ffffff);
|
||||||
@ -479,12 +480,12 @@ void cChunk::getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z)
|
void cChunk::GetRandomBlockCoords(int & a_X, int & a_Y, int & a_Z)
|
||||||
{
|
{
|
||||||
// MG TODO : check if this kind of optimization (only one random call) is still needed
|
// MG TODO : check if this kind of optimization (only one random call) is still needed
|
||||||
// MG TODO : if so propagate it
|
// MG TODO : if so propagate it
|
||||||
|
|
||||||
getThreeRandomNumber(a_X, a_Y, a_Z, Width, Height-2, Width);
|
GetThreeRandomNumbers(a_X, a_Y, a_Z, Width, Height - 2, Width);
|
||||||
a_Y++;
|
a_Y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,65 +495,68 @@ void cChunk::getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z)
|
|||||||
|
|
||||||
void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner)
|
void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner)
|
||||||
{
|
{
|
||||||
int Center_X,Center_Y,Center_Z;
|
int CenterX, CenterY, CenterZ;
|
||||||
getRandomBlockCoords(Center_X,Center_Y,Center_Z);
|
GetRandomBlockCoords(CenterX, CenterY, CenterZ);
|
||||||
|
|
||||||
BLOCKTYPE PackCenterBlock = GetBlock(Center_X, Center_Y, Center_Z);
|
BLOCKTYPE PackCenterBlock = GetBlock(CenterX, CenterY, CenterZ);
|
||||||
if (a_MobSpawner.CheckPackCenter(PackCenterBlock))
|
if (!a_MobSpawner.CheckPackCenter(PackCenterBlock))
|
||||||
{
|
{
|
||||||
a_MobSpawner.NewPack();
|
return;
|
||||||
int NumberOfTries = 0;
|
|
||||||
int NumberOfSuccess = 0;
|
|
||||||
int MaxNbOfSuccess = 4; // this can be changed during the process for Wolves and Ghass
|
|
||||||
while (NumberOfTries < 12 && NumberOfSuccess < MaxNbOfSuccess)
|
|
||||||
{
|
|
||||||
const int HorizontalRange = 20; // MG TODO : relocate
|
|
||||||
const int VerticalRange = 0; // MG TODO : relocate
|
|
||||||
int Try_X, Try_Y, Try_Z;
|
|
||||||
getThreeRandomNumber(Try_X, Try_Y, Try_Z, 2*HorizontalRange+1 , 2*VerticalRange+1 , 2*HorizontalRange+1);
|
|
||||||
Try_X -= HorizontalRange;
|
|
||||||
Try_Y -= VerticalRange;
|
|
||||||
Try_Z -= HorizontalRange;
|
|
||||||
Try_X += Center_X;
|
|
||||||
Try_Y += Center_Y;
|
|
||||||
Try_Z += Center_Z;
|
|
||||||
|
|
||||||
ASSERT(Try_Y > 0);
|
|
||||||
ASSERT(Try_Y < cChunkDef::Height-1);
|
|
||||||
|
|
||||||
EMCSBiome Biome = m_ChunkMap->GetBiomeAt (Try_X, Try_Z);
|
|
||||||
// MG TODO :
|
|
||||||
// Moon cycle (for slime)
|
|
||||||
// check player and playerspawn presence < 24 blocks
|
|
||||||
// check mobs presence on the block
|
|
||||||
|
|
||||||
// MG TODO : check that "Level" really means Y
|
|
||||||
|
|
||||||
/*
|
|
||||||
NIBBLETYPE SkyLight = 0;
|
|
||||||
|
|
||||||
NIBBLETYPE BlockLight = 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (IsLightValid())
|
|
||||||
{
|
|
||||||
cEntity* newMob = a_MobSpawner.TryToSpawnHere(this, Try_X, Try_Y, Try_Z, Biome, MaxNbOfSuccess);
|
|
||||||
if (newMob)
|
|
||||||
{
|
|
||||||
int WorldX, WorldY, WorldZ;
|
|
||||||
PositionToWorldPosition(Try_X, Try_Y, Try_Z, WorldX, WorldY, WorldZ);
|
|
||||||
double ActualX = WorldX + 0.5;
|
|
||||||
double ActualZ = WorldZ + 0.5;
|
|
||||||
newMob->SetPosition(ActualX, WorldY, ActualZ);
|
|
||||||
LOGD("Spawning %s #%i at %d,%d,%d",newMob->GetClass(),newMob->GetUniqueID(),WorldX, WorldY, WorldZ);
|
|
||||||
NumberOfSuccess++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NumberOfTries++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a_MobSpawner.NewPack();
|
||||||
|
int NumberOfTries = 0;
|
||||||
|
int NumberOfSuccess = 0;
|
||||||
|
int MaxNbOfSuccess = 4; // This can be changed during the process for Wolves and Ghasts
|
||||||
|
while ((NumberOfTries < 12) && (NumberOfSuccess < MaxNbOfSuccess))
|
||||||
|
{
|
||||||
|
const int HorizontalRange = 20; // MG TODO : relocate
|
||||||
|
const int VerticalRange = 0; // MG TODO : relocate
|
||||||
|
int TryX, TryY, TryZ;
|
||||||
|
GetThreeRandomNumbers(TryX, TryY, TryZ, 2 * HorizontalRange + 1, 2 * VerticalRange + 1, 2 * HorizontalRange + 1);
|
||||||
|
TryX -= HorizontalRange;
|
||||||
|
TryY -= VerticalRange;
|
||||||
|
TryZ -= HorizontalRange;
|
||||||
|
TryX += CenterX;
|
||||||
|
TryY += CenterY;
|
||||||
|
TryZ += CenterZ;
|
||||||
|
|
||||||
|
ASSERT(TryY > 0);
|
||||||
|
ASSERT(TryY < cChunkDef::Height - 1);
|
||||||
|
|
||||||
|
EMCSBiome Biome = m_ChunkMap->GetBiomeAt(TryX, TryZ);
|
||||||
|
// MG TODO :
|
||||||
|
// Moon cycle (for slime)
|
||||||
|
// check player and playerspawn presence < 24 blocks
|
||||||
|
// check mobs presence on the block
|
||||||
|
|
||||||
|
// MG TODO : check that "Level" really means Y
|
||||||
|
|
||||||
|
/*
|
||||||
|
NIBBLETYPE SkyLight = 0;
|
||||||
|
|
||||||
|
NIBBLETYPE BlockLight = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
NumberOfTries++;
|
||||||
|
if (!IsLightValid())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
cEntity * newMob = a_MobSpawner.TryToSpawnHere(this, TryX, TryY, TryZ, Biome, MaxNbOfSuccess);
|
||||||
|
if (newMob == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int WorldX, WorldY, WorldZ;
|
||||||
|
PositionToWorldPosition(TryX, TryY, TryZ, WorldX, WorldY, WorldZ);
|
||||||
|
double ActualX = WorldX + 0.5;
|
||||||
|
double ActualZ = WorldZ + 0.5;
|
||||||
|
newMob->SetPosition(ActualX, WorldY, ActualZ);
|
||||||
|
LOGD("Spawning %s #%i at {%d, %d, %d}", newMob->GetClass(), newMob->GetUniqueID(), WorldX, WorldY, WorldZ);
|
||||||
|
NumberOfSuccess++;
|
||||||
|
} // while (retry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1297,6 +1301,7 @@ void cChunk::CreateBlockEntities(void)
|
|||||||
switch (BlockType)
|
switch (BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_BEACON:
|
case E_BLOCK_BEACON:
|
||||||
|
case E_BLOCK_TRAPPED_CHEST:
|
||||||
case E_BLOCK_CHEST:
|
case E_BLOCK_CHEST:
|
||||||
case E_BLOCK_COMMAND_BLOCK:
|
case E_BLOCK_COMMAND_BLOCK:
|
||||||
case E_BLOCK_DISPENSER:
|
case E_BLOCK_DISPENSER:
|
||||||
@ -1427,6 +1432,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
|
|||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
case E_BLOCK_BEACON:
|
case E_BLOCK_BEACON:
|
||||||
|
case E_BLOCK_TRAPPED_CHEST:
|
||||||
case E_BLOCK_CHEST:
|
case E_BLOCK_CHEST:
|
||||||
case E_BLOCK_COMMAND_BLOCK:
|
case E_BLOCK_COMMAND_BLOCK:
|
||||||
case E_BLOCK_DISPENSER:
|
case E_BLOCK_DISPENSER:
|
||||||
@ -1641,6 +1647,31 @@ cBlockEntity * cChunk::GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunk::ShouldBeTicked(void) const
|
||||||
|
{
|
||||||
|
return (HasAnyClients() || (m_AlwaysTicked > 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunk::SetAlwaysTicked(bool a_AlwaysTicked)
|
||||||
|
{
|
||||||
|
if (a_AlwaysTicked)
|
||||||
|
{
|
||||||
|
m_AlwaysTicked += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_AlwaysTicked -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z)
|
void cChunk::UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z)
|
||||||
{
|
{
|
||||||
cBlockEntity * be = GetBlockEntity(a_X, a_Y, a_Z);
|
cBlockEntity * be = GetBlockEntity(a_X, a_Y, a_Z);
|
||||||
@ -1852,7 +1883,7 @@ bool cChunk::HasClient( cClientHandle* a_Client )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cChunk::HasAnyClients(void)
|
bool cChunk::HasAnyClients(void) const
|
||||||
{
|
{
|
||||||
return !m_LoadedByClient.empty();
|
return !m_LoadedByClient.empty();
|
||||||
}
|
}
|
||||||
@ -2121,7 +2152,7 @@ bool cChunk::DoWithChestAt(int a_BlockX, int a_BlockY, int a_BlockZ, cChestCallb
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((*itr)->GetBlockType() != E_BLOCK_CHEST)
|
if (((*itr)->GetBlockType() != E_BLOCK_CHEST) && ((*itr)->GetBlockType() != E_BLOCK_TRAPPED_CHEST)) // Trapped chests use normal chests' handlers
|
||||||
{
|
{
|
||||||
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
// There is a block entity here, but of different type. No other block entity can be here, so we can safely bail out
|
||||||
return false;
|
return false;
|
||||||
@ -2501,8 +2532,8 @@ cChunk * cChunk::GetRelNeighborChunk(int a_RelX, int a_RelZ)
|
|||||||
{
|
{
|
||||||
int BlockX = m_PosX * cChunkDef::Width + a_RelX;
|
int BlockX = m_PosX * cChunkDef::Width + a_RelX;
|
||||||
int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
|
int BlockZ = m_PosZ * cChunkDef::Width + a_RelZ;
|
||||||
int BlockY, ChunkX, ChunkZ;
|
int ChunkX, ChunkZ;
|
||||||
AbsoluteToRelative(BlockX, BlockY, BlockZ, ChunkX, ChunkZ);
|
BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
||||||
return m_ChunkMap->GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
return m_ChunkMap->GetChunkNoLoad(ChunkX, ZERO_CHUNK_Y, ChunkZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
34
src/Chunk.h
34
src/Chunk.h
@ -200,11 +200,16 @@ public:
|
|||||||
void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client);
|
void SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client);
|
||||||
|
|
||||||
/** Adds a client to the chunk; returns true if added, false if already there */
|
/** Adds a client to the chunk; returns true if added, false if already there */
|
||||||
bool AddClient (cClientHandle* a_Client );
|
bool AddClient(cClientHandle * a_Client);
|
||||||
|
|
||||||
void RemoveClient (cClientHandle* a_Client );
|
/** Removes the specified client from the chunk; ignored if client not in chunk. */
|
||||||
bool HasClient (cClientHandle* a_Client );
|
void RemoveClient(cClientHandle * a_Client);
|
||||||
bool HasAnyClients(void); // Returns true if theres any client in the chunk; false otherwise
|
|
||||||
|
/** Returns true if the specified client is present in this chunk. */
|
||||||
|
bool HasClient(cClientHandle * a_Client);
|
||||||
|
|
||||||
|
/** Returns true if theres any client in the chunk; false otherwise */
|
||||||
|
bool HasAnyClients(void) const;
|
||||||
|
|
||||||
void AddEntity(cEntity * a_Entity);
|
void AddEntity(cEntity * a_Entity);
|
||||||
void RemoveEntity(cEntity * a_Entity);
|
void RemoveEntity(cEntity * a_Entity);
|
||||||
@ -390,6 +395,17 @@ public:
|
|||||||
|
|
||||||
cBlockEntity * GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ);
|
cBlockEntity * GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
cBlockEntity * GetBlockEntity(const Vector3i & a_BlockPos) { return GetBlockEntity(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); }
|
cBlockEntity * GetBlockEntity(const Vector3i & a_BlockPos) { return GetBlockEntity(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); }
|
||||||
|
|
||||||
|
/** Returns true if the chunk should be ticked in the tick-thread.
|
||||||
|
Checks if there are any clients and if the always-tick flag is set */
|
||||||
|
bool ShouldBeTicked(void) const;
|
||||||
|
|
||||||
|
/** Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter.
|
||||||
|
If the m_AlwaysTicked counter is greater than zero, the chunk is ticked in the tick-thread regardless of
|
||||||
|
whether it has any clients or not.
|
||||||
|
This function allows nesting and task-concurrency (multiple separate tasks can request ticking and as long
|
||||||
|
as at least one requests is active the chunk will be ticked). */
|
||||||
|
void SetAlwaysTicked(bool a_AlwaysTicked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -462,10 +478,16 @@ private:
|
|||||||
|
|
||||||
/** Indicates if simulate-once blocks should be updated by the redstone simulator */
|
/** Indicates if simulate-once blocks should be updated by the redstone simulator */
|
||||||
bool m_IsRedstoneDirty;
|
bool m_IsRedstoneDirty;
|
||||||
|
|
||||||
|
/** If greater than zero, the chunk is ticked even if it has no clients.
|
||||||
|
Manipulated by the SetAlwaysTicked() function, allows for nested calls of the function.
|
||||||
|
This is the support for plugin-accessible chunk tick forcing. */
|
||||||
|
int m_AlwaysTicked;
|
||||||
|
|
||||||
|
|
||||||
// Pick up a random block of this chunk
|
// Pick up a random block of this chunk
|
||||||
void getRandomBlockCoords(int& a_X, int& a_Y, int& a_Z);
|
void GetRandomBlockCoords(int & a_X, int & a_Y, int & a_Z);
|
||||||
void getThreeRandomNumber(int& a_X, int& a_Y, int& a_Z,int a_MaxX, int a_MaxY, int a_MaxZ);
|
void GetThreeRandomNumbers(int & a_X, int & a_Y, int & a_Z, int a_MaxX, int a_MaxY, int a_MaxZ);
|
||||||
|
|
||||||
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
|
void RemoveBlockEntity(cBlockEntity * a_BlockEntity);
|
||||||
void AddBlockEntity (cBlockEntity * a_BlockEntity);
|
void AddBlockEntity (cBlockEntity * a_BlockEntity);
|
||||||
|
@ -847,7 +847,22 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
|
void cChunkMap::MarkRedstoneDirty(int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||||
|
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Chunk->SetIsRedstoneDirty(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkMap::MarkChunkDirty(int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||||
@ -856,6 +871,10 @@ void cChunkMap::MarkChunkDirty (int a_ChunkX, int a_ChunkZ)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Chunk->MarkDirty();
|
Chunk->MarkDirty();
|
||||||
|
if (a_MarkRedstoneDirty)
|
||||||
|
{
|
||||||
|
Chunk->SetIsRedstoneDirty(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2674,6 +2693,20 @@ void cChunkMap::QueueTickBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkMap::SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
|
||||||
|
if (Chunk != NULL)
|
||||||
|
{
|
||||||
|
Chunk->SetAlwaysTicked(a_AlwaysTicked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// cChunkMap::cChunkLayer:
|
// cChunkMap::cChunkLayer:
|
||||||
|
|
||||||
@ -2788,12 +2821,14 @@ void cChunkMap::cChunkLayer::SpawnMobs(cMobSpawner& a_MobSpawner)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::cChunkLayer::Tick(float a_Dt)
|
void cChunkMap::cChunkLayer::Tick(float a_Dt)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||||
{
|
{
|
||||||
// Only tick chunks that are valid and have clients:
|
// Only tick chunks that are valid and should be ticked:
|
||||||
if ((m_Chunks[i] != NULL) && m_Chunks[i]->IsValid() && m_Chunks[i]->HasAnyClients())
|
if ((m_Chunks[i] != NULL) && m_Chunks[i]->IsValid() && m_Chunks[i]->ShouldBeTicked())
|
||||||
{
|
{
|
||||||
m_Chunks[i]->Tick(a_Dt);
|
m_Chunks[i]->Tick(a_Dt);
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,8 @@ public:
|
|||||||
/** Wakes up the simulators for the specified area of blocks */
|
/** Wakes up the simulators for the specified area of blocks */
|
||||||
void WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ);
|
void WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ);
|
||||||
|
|
||||||
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ);
|
void MarkRedstoneDirty (int a_ChunkX, int a_ChunkZ);
|
||||||
|
void MarkChunkDirty (int a_ChunkX, int a_ChunkZ, bool a_MarkRedstoneDirty = false);
|
||||||
void MarkChunkSaving (int a_ChunkX, int a_ChunkZ);
|
void MarkChunkSaving (int a_ChunkX, int a_ChunkZ);
|
||||||
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
|
void MarkChunkSaved (int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
@ -339,6 +340,13 @@ public:
|
|||||||
|
|
||||||
/** Returns the CS for locking the chunkmap; only cWorld::cLock may use this function! */
|
/** Returns the CS for locking the chunkmap; only cWorld::cLock may use this function! */
|
||||||
cCriticalSection & GetCS(void) { return m_CSLayers; }
|
cCriticalSection & GetCS(void) { return m_CSLayers; }
|
||||||
|
|
||||||
|
/** Increments (a_AlwaysTicked == true) or decrements (false) the m_AlwaysTicked counter for the specified chunk.
|
||||||
|
If the m_AlwaysTicked counter is greater than zero, the chunk is ticked in the tick-thread regardless of
|
||||||
|
whether it has any clients or not.
|
||||||
|
This function allows nesting and task-concurrency (multiple separate tasks can request ticking and as long
|
||||||
|
as at least one requests is active the chunk will be ticked). */
|
||||||
|
void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include "CompositeChat.h"
|
#include "CompositeChat.h"
|
||||||
#include "Items/ItemSword.h"
|
#include "Items/ItemSword.h"
|
||||||
|
|
||||||
#include "md5/md5.h"
|
#include "polarssl/md5.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -239,18 +239,16 @@ AString cClientHandle::GenerateOfflineUUID(const AString & a_Username)
|
|||||||
// xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B
|
// xxxxxxxx-xxxx-3xxx-yxxx-xxxxxxxxxxxx where x is any hexadecimal digit and y is one of 8, 9, A, or B
|
||||||
|
|
||||||
// Generate an md5 checksum, and use it as base for the ID:
|
// Generate an md5 checksum, and use it as base for the ID:
|
||||||
MD5 Checksum(a_Username);
|
unsigned char MD5[16];
|
||||||
AString UUID = Checksum.hexdigest();
|
md5((const unsigned char *)a_Username.c_str(), a_Username.length(), MD5);
|
||||||
UUID[12] = '3'; // Version 3 UUID
|
MD5[6] &= 0x0f; // Need to trim to 4 bits only...
|
||||||
UUID[16] = '8'; // Variant 1 UUID
|
MD5[8] &= 0x0f; // ... otherwise %01x overflows into two chars
|
||||||
|
return Printf("%02x%02x%02x%02x-%02x%02x-3%01x%02x-8%01x%02x-%02x%02x%02x%02x%02x%02x",
|
||||||
// Now the digest doesn't have the UUID slashes, but the client requires them, so add them into the appropriate positions:
|
MD5[0], MD5[1], MD5[2], MD5[3],
|
||||||
UUID.insert(8, "-");
|
MD5[4], MD5[5], MD5[6], MD5[7],
|
||||||
UUID.insert(13, "-");
|
MD5[8], MD5[9], MD5[10], MD5[11],
|
||||||
UUID.insert(18, "-");
|
MD5[12], MD5[13], MD5[14], MD5[15]
|
||||||
UUID.insert(23, "-");
|
);
|
||||||
|
|
||||||
return UUID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -365,6 +363,9 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID)
|
|||||||
// Send scoreboard data
|
// Send scoreboard data
|
||||||
World->GetScoreBoard().SendTo(*this);
|
World->GetScoreBoard().SendTo(*this);
|
||||||
|
|
||||||
|
// Send statistics
|
||||||
|
SendStatistics(m_Player->GetStatManager());
|
||||||
|
|
||||||
// Delay the first ping until the client "settles down"
|
// Delay the first ping until the client "settles down"
|
||||||
// This should fix #889, "BadCast exception, cannot convert bit to fm" error in client
|
// This should fix #889, "BadCast exception, cannot convert bit to fm" error in client
|
||||||
cTimer t1;
|
cTimer t1;
|
||||||
@ -1085,12 +1086,7 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
|
|||||||
|
|
||||||
void cClientHandle::FinishDigAnimation()
|
void cClientHandle::FinishDigAnimation()
|
||||||
{
|
{
|
||||||
if (
|
if (!m_HasStartedDigging) // Hasn't received the DIG_STARTED packet
|
||||||
!m_HasStartedDigging || // Hasn't received the DIG_STARTED packet
|
|
||||||
(m_LastDigBlockX == -1) ||
|
|
||||||
(m_LastDigBlockY == -1) ||
|
|
||||||
(m_LastDigBlockZ == -1)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1227,9 +1223,7 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
|||||||
{
|
{
|
||||||
// A plugin won't let us eat, abort (send the proper packets to the client, too):
|
// A plugin won't let us eat, abort (send the proper packets to the client, too):
|
||||||
m_Player->AbortEating();
|
m_Player->AbortEating();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2401,9 +2395,9 @@ void cClientHandle::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effec
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::SendRespawn(const cWorld & a_World)
|
void cClientHandle::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
|
||||||
{
|
{
|
||||||
m_Protocol->SendRespawn(a_World);
|
m_Protocol->SendRespawn(a_World, a_ShouldIgnoreDimensionChecks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ public:
|
|||||||
void SendPlayerSpawn (const cPlayer & a_Player);
|
void SendPlayerSpawn (const cPlayer & a_Player);
|
||||||
void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
|
void SendPluginMessage (const AString & a_Channel, const AString & a_Message); // Exported in ManualBindings.cpp
|
||||||
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
|
void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID);
|
||||||
void SendRespawn (const cWorld & a_World);
|
void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false);
|
||||||
void SendExperience (void);
|
void SendExperience (void);
|
||||||
void SendExperienceOrb (const cExpOrb & a_ExpOrb);
|
void SendExperienceOrb (const cExpOrb & a_ExpOrb);
|
||||||
void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
|
void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode);
|
||||||
|
@ -72,26 +72,24 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
|
|||||||
|
|
||||||
|
|
||||||
void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
|
void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
|
||||||
{
|
{
|
||||||
if (a_HitFace == BLOCK_FACE_NONE) { return; }
|
if (GetSpeed().EqualsEps(Vector3d(0, 0, 0), 0.0000001))
|
||||||
|
|
||||||
super::OnHitSolidBlock(a_HitPos, a_HitFace);
|
|
||||||
int a_X = (int)a_HitPos.x, a_Y = (int)a_HitPos.y, a_Z = (int)a_HitPos.z;
|
|
||||||
|
|
||||||
switch (a_HitFace)
|
|
||||||
{
|
{
|
||||||
case BLOCK_FACE_XM: // Strangely, bounding boxes / block tracers return the actual block for these two directions, so AddFace not needed
|
SetSpeed(GetLookVector().NormalizeCopy() * 0.1); // Ensure that no division by zero happens later
|
||||||
case BLOCK_FACE_YM:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: AddFaceDirection(a_X, a_Y, a_Z, a_HitFace, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_HitBlockPos = Vector3i(a_X, a_Y, a_Z);
|
Vector3d Hit = a_HitPos;
|
||||||
|
Vector3d SinkMovement = (GetSpeed() / 800);
|
||||||
|
Hit += (SinkMovement * 0.01) / SinkMovement.Length(); // Make arrow sink into block a centimetre so it lodges (but not to far so it goes black clientside)
|
||||||
|
|
||||||
|
super::OnHitSolidBlock(Hit, a_HitFace);
|
||||||
|
Vector3i BlockHit = Hit.Floor();
|
||||||
|
|
||||||
|
int X = BlockHit.x, Y = BlockHit.y, Z = BlockHit.z;
|
||||||
|
m_HitBlockPos = Vector3i(X, Y, Z);
|
||||||
|
|
||||||
// Broadcast arrow hit sound
|
// Broadcast arrow hit sound
|
||||||
m_World->BroadcastSoundEffect("random.bowhit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
m_World->BroadcastSoundEffect("random.bowhit", X * 8, Y * 8, Z * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,13 +97,7 @@ void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFa
|
|||||||
|
|
||||||
|
|
||||||
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
|
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
|
||||||
{
|
{
|
||||||
if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer() && !a_EntityHit.IsBoat())
|
|
||||||
{
|
|
||||||
// Not an entity that interacts with an arrow
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5);
|
int Damage = (int)(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5);
|
||||||
if (m_IsCritical)
|
if (m_IsCritical)
|
||||||
{
|
{
|
||||||
@ -114,14 +106,7 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
|
|||||||
a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1);
|
a_EntityHit.TakeDamage(dtRangedAttack, this, Damage, 1);
|
||||||
|
|
||||||
// Broadcast successful hit sound
|
// Broadcast successful hit sound
|
||||||
m_World->BroadcastSoundEffect(
|
GetWorld()->BroadcastSoundEffect("random.successful_hit", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||||
"random.successful_hit",
|
|
||||||
(int)std::floor(GetPosX() * 8.0),
|
|
||||||
(int)std::floor(GetPosY() * 8.0),
|
|
||||||
(int)std::floor(GetPosZ() * 8.0),
|
|
||||||
0.5f,
|
|
||||||
0.75f + ((float)((GetUniqueID() * 23) % 32)) / 64.0f
|
|
||||||
);
|
|
||||||
|
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
@ -144,21 +129,10 @@ void cArrowEntity::CollectedBy(cPlayer * a_Dest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: BroadcastCollectPickup needs a cPickup, which we don't have
|
|
||||||
// m_World->BroadcastCollectPickup(*this, *a_Dest);
|
|
||||||
|
|
||||||
|
GetWorld()->BroadcastCollectEntity(*this, *a_Dest);
|
||||||
|
GetWorld()->BroadcastSoundEffect("random.pop", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||||
m_bIsCollected = true;
|
m_bIsCollected = true;
|
||||||
|
|
||||||
cFastRandom Random;
|
|
||||||
m_World->BroadcastSoundEffect(
|
|
||||||
"random.pop",
|
|
||||||
(int)std::floor(GetPosX() * 8.0),
|
|
||||||
(int)std::floor(GetPosY() * 8),
|
|
||||||
(int)std::floor(GetPosZ() * 8),
|
|
||||||
0.2F,
|
|
||||||
((Random.NextFloat(1.0F) - Random.NextFloat(1.0F)) * 0.7F + 1.0F) * 2.0F
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +168,7 @@ void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
if (!m_HasTeleported) // Sent a teleport already, don't do again
|
if (!m_HasTeleported) // Sent a teleport already, don't do again
|
||||||
{
|
{
|
||||||
if (m_HitGroundTimer > 1000.f) // Send after a second, could be less, but just in case
|
if (m_HitGroundTimer > 500.f) // Send after half a second, could be less, but just in case
|
||||||
{
|
{
|
||||||
m_World->BroadcastTeleportEntity(*this);
|
m_World->BroadcastTeleportEntity(*this);
|
||||||
m_HasTeleported = true;
|
m_HasTeleported = true;
|
||||||
|
@ -58,8 +58,14 @@ public:
|
|||||||
|
|
||||||
/// Sets the IsCritical flag
|
/// Sets the IsCritical flag
|
||||||
void SetIsCritical(bool a_IsCritical) { m_IsCritical = a_IsCritical; }
|
void SetIsCritical(bool a_IsCritical) { m_IsCritical = a_IsCritical; }
|
||||||
|
|
||||||
|
/** Gets the block arrow is in */
|
||||||
|
Vector3i GetBlockHit(void) const { return m_HitBlockPos; }
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
/** Sets the block arrow is in. To be used by the MCA loader only! */
|
||||||
|
void SetBlockHit(const Vector3i & a_BlockHit) { m_HitBlockPos = a_BlockHit; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -1090,7 +1090,10 @@ void cEntity::HandleAir(void)
|
|||||||
|
|
||||||
if (IsSubmerged())
|
if (IsSubmerged())
|
||||||
{
|
{
|
||||||
SetSpeedY(1); // Float in the water
|
if (!IsPlayer()) // Players control themselves
|
||||||
|
{
|
||||||
|
SetSpeedY(1); // Float in the water
|
||||||
|
}
|
||||||
|
|
||||||
// Either reduce air level or damage player
|
// Either reduce air level or damage player
|
||||||
if (m_AirLevel < 1)
|
if (m_AirLevel < 1)
|
||||||
@ -1476,8 +1479,7 @@ void cEntity::SetWidth(double a_Width)
|
|||||||
|
|
||||||
void cEntity::AddPosX(double a_AddPosX)
|
void cEntity::AddPosX(double a_AddPosX)
|
||||||
{
|
{
|
||||||
m_Pos.x += a_AddPosX;
|
m_Pos.x += a_AddPosX;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1485,8 +1487,7 @@ void cEntity::AddPosX(double a_AddPosX)
|
|||||||
|
|
||||||
void cEntity::AddPosY(double a_AddPosY)
|
void cEntity::AddPosY(double a_AddPosY)
|
||||||
{
|
{
|
||||||
m_Pos.y += a_AddPosY;
|
m_Pos.y += a_AddPosY;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1494,8 +1495,7 @@ void cEntity::AddPosY(double a_AddPosY)
|
|||||||
|
|
||||||
void cEntity::AddPosZ(double a_AddPosZ)
|
void cEntity::AddPosZ(double a_AddPosZ)
|
||||||
{
|
{
|
||||||
m_Pos.z += a_AddPosZ;
|
m_Pos.z += a_AddPosZ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1505,8 +1505,7 @@ void cEntity::AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ)
|
|||||||
{
|
{
|
||||||
m_Pos.x += a_AddPosX;
|
m_Pos.x += a_AddPosX;
|
||||||
m_Pos.y += a_AddPosY;
|
m_Pos.y += a_AddPosY;
|
||||||
m_Pos.z += a_AddPosZ;
|
m_Pos.z += a_AddPosZ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -237,9 +237,9 @@ public:
|
|||||||
void AddPosY (double a_AddPosY);
|
void AddPosY (double a_AddPosY);
|
||||||
void AddPosZ (double a_AddPosZ);
|
void AddPosZ (double a_AddPosZ);
|
||||||
void AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ);
|
void AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ);
|
||||||
void AddPosition(const Vector3d & a_AddPos) { AddPosition(a_AddPos.x,a_AddPos.y,a_AddPos.z);}
|
void AddPosition(const Vector3d & a_AddPos) { AddPosition(a_AddPos.x, a_AddPos.y, a_AddPos.z); }
|
||||||
void AddSpeed (double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ);
|
void AddSpeed (double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ);
|
||||||
void AddSpeed (const Vector3d & a_AddSpeed) { AddSpeed(a_AddSpeed.x,a_AddSpeed.y,a_AddSpeed.z);}
|
void AddSpeed (const Vector3d & a_AddSpeed) { AddSpeed(a_AddSpeed.x, a_AddSpeed.y, a_AddSpeed.z); }
|
||||||
void AddSpeedX (double a_AddSpeedX);
|
void AddSpeedX (double a_AddSpeedX);
|
||||||
void AddSpeedY (double a_AddSpeedY);
|
void AddSpeedY (double a_AddSpeedY);
|
||||||
void AddSpeedZ (double a_AddSpeedZ);
|
void AddSpeedZ (double a_AddSpeedZ);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
class cExpOrb :
|
class cExpOrb :
|
||||||
public cEntity
|
public cEntity
|
||||||
{
|
{
|
||||||
typedef cExpOrb super;
|
typedef cEntity super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
@ -224,7 +224,7 @@ bool cPickup::CollectedBy(cPlayer * a_Dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_Item.m_ItemCount -= NumAdded;
|
m_Item.m_ItemCount -= NumAdded;
|
||||||
m_World->BroadcastCollectPickup(*this, *a_Dest);
|
m_World->BroadcastCollectEntity(*this, *a_Dest);
|
||||||
// Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
|
// Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
|
||||||
m_World->BroadcastSoundEffect("random.pop",(int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
m_World->BroadcastSoundEffect("random.pop",(int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64));
|
||||||
if (m_Item.m_ItemCount <= 0)
|
if (m_Item.m_ItemCount <= 0)
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "../World.h"
|
#include "../World.h"
|
||||||
#include "../Bindings/PluginManager.h"
|
#include "../Bindings/PluginManager.h"
|
||||||
#include "../BlockEntities/BlockEntity.h"
|
#include "../BlockEntities/BlockEntity.h"
|
||||||
|
#include "../BlockEntities/EnderChestEntity.h"
|
||||||
#include "../GroupManager.h"
|
#include "../GroupManager.h"
|
||||||
#include "../Group.h"
|
#include "../Group.h"
|
||||||
#include "../Root.h"
|
#include "../Root.h"
|
||||||
@ -33,50 +34,48 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) :
|
||||||
: super(etPlayer, 0.6, 1.8)
|
super(etPlayer, 0.6, 1.8),
|
||||||
, m_bVisible(true)
|
m_bVisible(true),
|
||||||
, m_FoodLevel(MAX_FOOD_LEVEL)
|
m_FoodLevel(MAX_FOOD_LEVEL),
|
||||||
, m_FoodSaturationLevel(5)
|
m_FoodSaturationLevel(5.0),
|
||||||
, m_FoodTickTimer(0)
|
m_FoodTickTimer(0),
|
||||||
, m_FoodExhaustionLevel(0)
|
m_FoodExhaustionLevel(0.0),
|
||||||
, m_FoodPoisonedTicksRemaining(0)
|
m_FoodPoisonedTicksRemaining(0),
|
||||||
, m_LastJumpHeight(0)
|
m_LastJumpHeight(0),
|
||||||
, m_LastGroundHeight(0)
|
m_LastGroundHeight(0),
|
||||||
, m_bTouchGround(false)
|
m_bTouchGround(false),
|
||||||
, m_Stance(0.0)
|
m_Stance(0.0),
|
||||||
, m_Inventory(*this)
|
m_Inventory(*this),
|
||||||
, m_CurrentWindow(NULL)
|
m_EnderChestContents(9, 3),
|
||||||
, m_InventoryWindow(NULL)
|
m_CurrentWindow(NULL),
|
||||||
, m_Color('-')
|
m_InventoryWindow(NULL),
|
||||||
, m_GameMode(eGameMode_NotSet)
|
m_Color('-'),
|
||||||
, m_IP("")
|
m_GameMode(eGameMode_NotSet),
|
||||||
, m_ClientHandle(a_Client)
|
m_IP(""),
|
||||||
, m_NormalMaxSpeed(1.0)
|
m_ClientHandle(a_Client),
|
||||||
, m_SprintingMaxSpeed(1.3)
|
m_NormalMaxSpeed(1.0),
|
||||||
, m_FlyingMaxSpeed(1.0)
|
m_SprintingMaxSpeed(1.3),
|
||||||
, m_IsCrouched(false)
|
m_FlyingMaxSpeed(1.0),
|
||||||
, m_IsSprinting(false)
|
m_IsCrouched(false),
|
||||||
, m_IsFlying(false)
|
m_IsSprinting(false),
|
||||||
, m_IsSwimming(false)
|
m_IsFlying(false),
|
||||||
, m_IsSubmerged(false)
|
m_IsSwimming(false),
|
||||||
, m_IsFishing(false)
|
m_IsSubmerged(false),
|
||||||
, m_CanFly(false)
|
m_IsFishing(false),
|
||||||
, m_EatingFinishTick(-1)
|
m_CanFly(false),
|
||||||
, m_LifetimeTotalXp(0)
|
m_EatingFinishTick(-1),
|
||||||
, m_CurrentXp(0)
|
m_LifetimeTotalXp(0),
|
||||||
, m_bDirtyExperience(false)
|
m_CurrentXp(0),
|
||||||
, m_IsChargingBow(false)
|
m_bDirtyExperience(false),
|
||||||
, m_BowCharge(0)
|
m_IsChargingBow(false),
|
||||||
, m_FloaterID(-1)
|
m_BowCharge(0),
|
||||||
, m_Team(NULL)
|
m_FloaterID(-1),
|
||||||
, m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL)
|
m_Team(NULL),
|
||||||
|
m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
|
||||||
|
m_bIsTeleporting(false),
|
||||||
|
m_UUID((a_Client != NULL) ? a_Client->GetUUID() : "")
|
||||||
{
|
{
|
||||||
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
|
|
||||||
a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
|
|
||||||
this, GetUniqueID()
|
|
||||||
);
|
|
||||||
|
|
||||||
m_InventoryWindow = new cInventoryWindow(*this);
|
m_InventoryWindow = new cInventoryWindow(*this);
|
||||||
m_CurrentWindow = m_InventoryWindow;
|
m_CurrentWindow = m_InventoryWindow;
|
||||||
m_InventoryWindow->OpenedByPlayer(*this);
|
m_InventoryWindow->OpenedByPlayer(*this);
|
||||||
@ -225,7 +224,7 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
SendExperience();
|
SendExperience();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetPosition() != m_LastPos) // Change in position from last tick?
|
if (!GetPosition().EqualsEps(m_LastPos, 0.01)) // Non negligible change in position from last tick?
|
||||||
{
|
{
|
||||||
// Apply food exhaustion from movement:
|
// Apply food exhaustion from movement:
|
||||||
ApplyFoodExhaustionFromMovement();
|
ApplyFoodExhaustionFromMovement();
|
||||||
@ -521,7 +520,15 @@ void cPlayer::Heal(int a_Health)
|
|||||||
|
|
||||||
void cPlayer::SetFoodLevel(int a_FoodLevel)
|
void cPlayer::SetFoodLevel(int a_FoodLevel)
|
||||||
{
|
{
|
||||||
m_FoodLevel = std::max(0, std::min(a_FoodLevel, (int)MAX_FOOD_LEVEL));
|
int FoodLevel = std::max(0, std::min(a_FoodLevel, (int)MAX_FOOD_LEVEL));
|
||||||
|
|
||||||
|
if (cRoot::Get()->GetPluginManager()->CallHookPlayerFoodLevelChange(*this, FoodLevel))
|
||||||
|
{
|
||||||
|
m_FoodSaturationLevel = 5.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_FoodLevel = FoodLevel;
|
||||||
SendHealth();
|
SendHealth();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,11 +578,9 @@ bool cPlayer::Feed(int a_Food, double a_Saturation)
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_FoodLevel = std::min(a_Food + m_FoodLevel, (int)MAX_FOOD_LEVEL);
|
SetFoodSaturationLevel(m_FoodSaturationLevel + a_Saturation);
|
||||||
m_FoodSaturationLevel = std::min(m_FoodSaturationLevel + a_Saturation, (double)m_FoodLevel);
|
SetFoodLevel(m_FoodLevel + a_Food);
|
||||||
|
|
||||||
SendHealth();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,14 +974,15 @@ void cPlayer::Respawn(void)
|
|||||||
|
|
||||||
// Reset food level:
|
// Reset food level:
|
||||||
m_FoodLevel = MAX_FOOD_LEVEL;
|
m_FoodLevel = MAX_FOOD_LEVEL;
|
||||||
m_FoodSaturationLevel = 5;
|
m_FoodSaturationLevel = 5.0;
|
||||||
|
m_FoodExhaustionLevel = 0.0;
|
||||||
|
|
||||||
// Reset Experience
|
// Reset Experience
|
||||||
m_CurrentXp = 0;
|
m_CurrentXp = 0;
|
||||||
m_LifetimeTotalXp = 0;
|
m_LifetimeTotalXp = 0;
|
||||||
// ToDo: send score to client? How?
|
// ToDo: send score to client? How?
|
||||||
|
|
||||||
m_ClientHandle->SendRespawn(*m_World);
|
m_ClientHandle->SendRespawn(*m_World, true);
|
||||||
|
|
||||||
// Extinguish the fire:
|
// Extinguish the fire:
|
||||||
StopBurning();
|
StopBurning();
|
||||||
@ -1226,6 +1232,7 @@ void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
|||||||
SetPosition(a_PosX, a_PosY, a_PosZ);
|
SetPosition(a_PosX, a_PosY, a_PosZ);
|
||||||
m_LastGroundHeight = (float)a_PosY;
|
m_LastGroundHeight = (float)a_PosY;
|
||||||
m_LastJumpHeight = (float)a_PosY;
|
m_LastJumpHeight = (float)a_PosY;
|
||||||
|
m_bIsTeleporting = true;
|
||||||
|
|
||||||
m_World->BroadcastTeleportEntity(*this, GetClientHandle());
|
m_World->BroadcastTeleportEntity(*this, GetClientHandle());
|
||||||
m_ClientHandle->SendPlayerMoveLook();
|
m_ClientHandle->SendPlayerMoveLook();
|
||||||
@ -1679,53 +1686,98 @@ void cPlayer::LoadPermissionsFromDisk()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPlayer::LoadFromDisk()
|
|
||||||
|
bool cPlayer::LoadFromDisk(void)
|
||||||
{
|
{
|
||||||
LoadPermissionsFromDisk();
|
LoadPermissionsFromDisk();
|
||||||
|
|
||||||
AString SourceFile;
|
// Load from the UUID file:
|
||||||
Printf(SourceFile, "players/%s.json", GetName().c_str() );
|
if (LoadFromFile(GetUUIDFileName(m_UUID)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load from the offline UUID file, if allowed:
|
||||||
|
AString OfflineUUID = cClientHandle::GenerateOfflineUUID(GetName());
|
||||||
|
if (cRoot::Get()->GetServer()->ShouldLoadOfflinePlayerData())
|
||||||
|
{
|
||||||
|
if (LoadFromFile(GetUUIDFileName(OfflineUUID)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load from the old-style name-based file, if allowed:
|
||||||
|
if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData())
|
||||||
|
{
|
||||||
|
AString OldStyleFileName = Printf("players/%s.json", GetName().c_str());
|
||||||
|
if (LoadFromFile(OldStyleFileName))
|
||||||
|
{
|
||||||
|
// Save in new format and remove the old file
|
||||||
|
if (SaveToDisk())
|
||||||
|
{
|
||||||
|
cFile::Delete(OldStyleFileName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None of the files loaded successfully
|
||||||
|
LOG("Player data file not found for %s (%s, offline %s), will be reset to defaults.",
|
||||||
|
GetName().c_str(), m_UUID.c_str(), OfflineUUID.c_str()
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPlayer::LoadFromFile(const AString & a_FileName)
|
||||||
|
{
|
||||||
|
// Load the data from the file:
|
||||||
cFile f;
|
cFile f;
|
||||||
if (!f.Open(SourceFile, cFile::fmRead))
|
if (!f.Open(a_FileName, cFile::fmRead))
|
||||||
{
|
{
|
||||||
// This is a new player whom we haven't seen yet, bail out, let them have the defaults
|
// This is a new player whom we haven't seen yet, bail out, let them have the defaults
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AString buffer;
|
AString buffer;
|
||||||
if (f.ReadRestOfFile(buffer) != f.GetSize())
|
if (f.ReadRestOfFile(buffer) != f.GetSize())
|
||||||
{
|
{
|
||||||
LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str());
|
LOGWARNING("Cannot read player data from file \"%s\"", a_FileName.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
f.Close(); //cool kids play nice
|
f.Close();
|
||||||
|
|
||||||
|
// Parse the JSON format:
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
Json::Reader reader;
|
Json::Reader reader;
|
||||||
if (!reader.parse(buffer, root, false))
|
if (!reader.parse(buffer, root, false))
|
||||||
{
|
{
|
||||||
LOGWARNING("Cannot parse player data in file \"%s\", player will be reset", SourceFile.c_str());
|
LOGWARNING("Cannot parse player data in file \"%s\"", a_FileName.c_str());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the player data:
|
||||||
Json::Value & JSON_PlayerPosition = root["position"];
|
Json::Value & JSON_PlayerPosition = root["position"];
|
||||||
if (JSON_PlayerPosition.size() == 3)
|
if (JSON_PlayerPosition.size() == 3)
|
||||||
{
|
{
|
||||||
SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
|
SetPosX(JSON_PlayerPosition[(unsigned)0].asDouble());
|
||||||
SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
|
SetPosY(JSON_PlayerPosition[(unsigned)1].asDouble());
|
||||||
SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
|
SetPosZ(JSON_PlayerPosition[(unsigned)2].asDouble());
|
||||||
m_LastPos = GetPosition();
|
m_LastPos = GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value & JSON_PlayerRotation = root["rotation"];
|
Json::Value & JSON_PlayerRotation = root["rotation"];
|
||||||
if (JSON_PlayerRotation.size() == 3)
|
if (JSON_PlayerRotation.size() == 3)
|
||||||
{
|
{
|
||||||
SetYaw ((float)JSON_PlayerRotation[(unsigned int)0].asDouble());
|
SetYaw ((float)JSON_PlayerRotation[(unsigned)0].asDouble());
|
||||||
SetPitch ((float)JSON_PlayerRotation[(unsigned int)1].asDouble());
|
SetPitch ((float)JSON_PlayerRotation[(unsigned)1].asDouble());
|
||||||
SetRoll ((float)JSON_PlayerRotation[(unsigned int)2].asDouble());
|
SetRoll ((float)JSON_PlayerRotation[(unsigned)2].asDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Health = root.get("health", 0).asInt();
|
m_Health = root.get("health", 0).asInt();
|
||||||
m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
|
m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
|
||||||
m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
|
m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
|
||||||
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
|
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
|
||||||
@ -1743,6 +1795,7 @@ bool cPlayer::LoadFromDisk()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_Inventory.LoadFromJson(root["inventory"]);
|
m_Inventory.LoadFromJson(root["inventory"]);
|
||||||
|
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
|
||||||
|
|
||||||
m_LoadedWorldName = root.get("world", "world").asString();
|
m_LoadedWorldName = root.get("world", "world").asString();
|
||||||
|
|
||||||
@ -1751,8 +1804,8 @@ bool cPlayer::LoadFromDisk()
|
|||||||
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
|
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
|
||||||
StatSerializer.Load();
|
StatSerializer.Load();
|
||||||
|
|
||||||
LOGD("Player \"%s\" was read from file, spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
|
LOGD("Player \"%s\" was read from file \"%s\", spawning at {%.2f, %.2f, %.2f} in world \"%s\"",
|
||||||
GetName().c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
|
GetName().c_str(), a_FileName.c_str(), GetPosX(), GetPosY(), GetPosZ(), m_LoadedWorldName.c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1765,6 +1818,7 @@ bool cPlayer::LoadFromDisk()
|
|||||||
bool cPlayer::SaveToDisk()
|
bool cPlayer::SaveToDisk()
|
||||||
{
|
{
|
||||||
cFile::CreateFolder(FILE_IO_PREFIX + AString("players"));
|
cFile::CreateFolder(FILE_IO_PREFIX + AString("players"));
|
||||||
|
cFile::CreateFolder(FILE_IO_PREFIX + AString("players/") + m_UUID.substr(0, 2));
|
||||||
|
|
||||||
// create the JSON data
|
// create the JSON data
|
||||||
Json::Value JSON_PlayerPosition;
|
Json::Value JSON_PlayerPosition;
|
||||||
@ -1780,45 +1834,61 @@ bool cPlayer::SaveToDisk()
|
|||||||
Json::Value JSON_Inventory;
|
Json::Value JSON_Inventory;
|
||||||
m_Inventory.SaveToJson(JSON_Inventory);
|
m_Inventory.SaveToJson(JSON_Inventory);
|
||||||
|
|
||||||
Json::Value root;
|
Json::Value JSON_EnderChestInventory;
|
||||||
root["position"] = JSON_PlayerPosition;
|
cEnderChestEntity::SaveToJson(JSON_EnderChestInventory, m_EnderChestContents);
|
||||||
root["rotation"] = JSON_PlayerRotation;
|
|
||||||
root["inventory"] = JSON_Inventory;
|
|
||||||
root["health"] = m_Health;
|
|
||||||
root["xpTotal"] = m_LifetimeTotalXp;
|
|
||||||
root["xpCurrent"] = m_CurrentXp;
|
|
||||||
root["air"] = m_AirLevel;
|
|
||||||
root["food"] = m_FoodLevel;
|
|
||||||
root["foodSaturation"] = m_FoodSaturationLevel;
|
|
||||||
root["foodTickTimer"] = m_FoodTickTimer;
|
|
||||||
root["foodExhaustion"] = m_FoodExhaustionLevel;
|
|
||||||
root["world"] = GetWorld()->GetName();
|
|
||||||
root["isflying"] = IsFlying();
|
|
||||||
|
|
||||||
if (m_GameMode == GetWorld()->GetGameMode())
|
Json::Value root;
|
||||||
|
root["position"] = JSON_PlayerPosition;
|
||||||
|
root["rotation"] = JSON_PlayerRotation;
|
||||||
|
root["inventory"] = JSON_Inventory;
|
||||||
|
root["enderchestinventory"] = JSON_EnderChestInventory;
|
||||||
|
root["health"] = m_Health;
|
||||||
|
root["xpTotal"] = m_LifetimeTotalXp;
|
||||||
|
root["xpCurrent"] = m_CurrentXp;
|
||||||
|
root["air"] = m_AirLevel;
|
||||||
|
root["food"] = m_FoodLevel;
|
||||||
|
root["foodSaturation"] = m_FoodSaturationLevel;
|
||||||
|
root["foodTickTimer"] = m_FoodTickTimer;
|
||||||
|
root["foodExhaustion"] = m_FoodExhaustionLevel;
|
||||||
|
root["isflying"] = IsFlying();
|
||||||
|
root["lastknownname"] = GetName();
|
||||||
|
if (m_World != NULL)
|
||||||
{
|
{
|
||||||
root["gamemode"] = (int) eGameMode_NotSet;
|
root["world"] = m_World->GetName();
|
||||||
|
if (m_GameMode == m_World->GetGameMode())
|
||||||
|
{
|
||||||
|
root["gamemode"] = (int) eGameMode_NotSet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root["gamemode"] = (int) m_GameMode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
root["gamemode"] = (int) m_GameMode;
|
// This happens if the player is saved to new format after loading from the old format
|
||||||
|
root["world"] = m_LoadedWorldName;
|
||||||
|
root["gamemode"] = (int) eGameMode_NotSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::StyledWriter writer;
|
Json::StyledWriter writer;
|
||||||
std::string JsonData = writer.write(root);
|
std::string JsonData = writer.write(root);
|
||||||
|
|
||||||
AString SourceFile;
|
AString SourceFile = GetUUIDFileName(m_UUID);
|
||||||
Printf(SourceFile, "players/%s.json", GetName().c_str() );
|
|
||||||
|
|
||||||
cFile f;
|
cFile f;
|
||||||
if (!f.Open(SourceFile, cFile::fmWrite))
|
if (!f.Open(SourceFile, cFile::fmWrite))
|
||||||
{
|
{
|
||||||
LOGERROR("ERROR WRITING PLAYER \"%s\" TO FILE \"%s\" - cannot open file", GetName().c_str(), SourceFile.c_str());
|
LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot open file. Player will lose their progress.",
|
||||||
|
GetName().c_str(), SourceFile.c_str()
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (f.Write(JsonData.c_str(), JsonData.size()) != (int)JsonData.size())
|
if (f.Write(JsonData.c_str(), JsonData.size()) != (int)JsonData.size())
|
||||||
{
|
{
|
||||||
LOGERROR("ERROR WRITING PLAYER JSON TO FILE \"%s\"", SourceFile.c_str());
|
LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot save data. Player will lose their progress. ",
|
||||||
|
GetName().c_str(), SourceFile.c_str()
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1827,7 +1897,7 @@ bool cPlayer::SaveToDisk()
|
|||||||
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
|
cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetName(), GetName(), &m_Stats);
|
||||||
if (!StatSerializer.Save())
|
if (!StatSerializer.Save())
|
||||||
{
|
{
|
||||||
LOGERROR("Could not save stats for player %s", GetName().c_str());
|
LOGWARNING("Could not save stats for player %s", GetName().c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1895,16 +1965,13 @@ void cPlayer::TickBurning(cChunk & a_Chunk)
|
|||||||
void cPlayer::HandleFood(void)
|
void cPlayer::HandleFood(void)
|
||||||
{
|
{
|
||||||
// Ref.: http://www.minecraftwiki.net/wiki/Hunger
|
// Ref.: http://www.minecraftwiki.net/wiki/Hunger
|
||||||
|
|
||||||
if (IsGameModeCreative())
|
if (IsGameModeCreative())
|
||||||
{
|
{
|
||||||
// Hunger is disabled for Creative
|
// Hunger is disabled for Creative
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember the food level before processing, for later comparison
|
|
||||||
int LastFoodLevel = m_FoodLevel;
|
|
||||||
|
|
||||||
// Heal or damage, based on the food level, using the m_FoodTickTimer:
|
// Heal or damage, based on the food level, using the m_FoodTickTimer:
|
||||||
if ((m_FoodLevel > 17) || (m_FoodLevel <= 0))
|
if ((m_FoodLevel > 17) || (m_FoodLevel <= 0))
|
||||||
{
|
{
|
||||||
@ -1913,11 +1980,11 @@ void cPlayer::HandleFood(void)
|
|||||||
{
|
{
|
||||||
m_FoodTickTimer = 0;
|
m_FoodTickTimer = 0;
|
||||||
|
|
||||||
if (m_FoodLevel >= 17)
|
if ((m_FoodLevel > 17) && (GetHealth() < GetMaxHealth()))
|
||||||
{
|
{
|
||||||
// Regenerate health from food, incur 3 pts of food exhaustion:
|
// Regenerate health from food, incur 3 pts of food exhaustion:
|
||||||
Heal(1);
|
Heal(1);
|
||||||
m_FoodExhaustionLevel += 3;
|
m_FoodExhaustionLevel += 3.0;
|
||||||
}
|
}
|
||||||
else if ((m_FoodLevel <= 0) && (m_Health > 1))
|
else if ((m_FoodLevel <= 0) && (m_Health > 1))
|
||||||
{
|
{
|
||||||
@ -1926,7 +1993,7 @@ void cPlayer::HandleFood(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply food poisoning food exhaustion:
|
// Apply food poisoning food exhaustion:
|
||||||
if (m_FoodPoisonedTicksRemaining > 0)
|
if (m_FoodPoisonedTicksRemaining > 0)
|
||||||
{
|
{
|
||||||
@ -1939,24 +2006,19 @@ void cPlayer::HandleFood(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply food exhaustion that has accumulated:
|
// Apply food exhaustion that has accumulated:
|
||||||
if (m_FoodExhaustionLevel >= 4)
|
if (m_FoodExhaustionLevel >= 4.0)
|
||||||
{
|
{
|
||||||
m_FoodExhaustionLevel -= 4;
|
m_FoodExhaustionLevel -= 4.0;
|
||||||
|
|
||||||
if (m_FoodSaturationLevel >= 1)
|
if (m_FoodSaturationLevel >= 1.0)
|
||||||
{
|
{
|
||||||
m_FoodSaturationLevel -= 1;
|
m_FoodSaturationLevel -= 1.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_FoodLevel = std::max(m_FoodLevel - 1, 0);
|
SetFoodLevel(m_FoodLevel - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_FoodLevel != LastFoodLevel)
|
|
||||||
{
|
|
||||||
SendHealth();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2079,6 +2141,11 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (m_bIsTeleporting)
|
||||||
|
{
|
||||||
|
m_bIsTeleporting = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If riding anything, apply no food exhaustion
|
// If riding anything, apply no food exhaustion
|
||||||
if (m_AttachedTo != NULL)
|
if (m_AttachedTo != NULL)
|
||||||
@ -2143,3 +2210,19 @@ void cPlayer::Detach()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cPlayer::GetUUIDFileName(const AString & a_UUID)
|
||||||
|
{
|
||||||
|
ASSERT(a_UUID.size() == 36);
|
||||||
|
|
||||||
|
AString res("players/");
|
||||||
|
res.append(a_UUID, 0, 2);
|
||||||
|
res.push_back('/');
|
||||||
|
res.append(a_UUID, 2, AString::npos);
|
||||||
|
res.append(".json");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
cPlayer(cClientHandle * a_Client, const AString & a_PlayerName);
|
cPlayer(cClientHandle * a_Client, const AString & a_PlayerName);
|
||||||
|
|
||||||
virtual ~cPlayer();
|
virtual ~cPlayer();
|
||||||
|
|
||||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
@ -124,6 +125,9 @@ public:
|
|||||||
inline double GetStance(void) const { return GetPosY() + 1.62; } // tolua_export // TODO: Proper stance when crouching etc.
|
inline double GetStance(void) const { return GetPosY() + 1.62; } // tolua_export // TODO: Proper stance when crouching etc.
|
||||||
inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export
|
inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export
|
||||||
inline const cInventory & GetInventory(void) const { return m_Inventory; }
|
inline const cInventory & GetInventory(void) const { return m_Inventory; }
|
||||||
|
|
||||||
|
/** Gets the contents of the player's associated enderchest */
|
||||||
|
cItemGrid & GetEnderChestContents(void) { return m_EnderChestContents; }
|
||||||
|
|
||||||
inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export
|
inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); } // tolua_export
|
||||||
|
|
||||||
@ -334,7 +338,15 @@ public:
|
|||||||
bool MoveToWorld(const char * a_WorldName); // tolua_export
|
bool MoveToWorld(const char * a_WorldName); // tolua_export
|
||||||
|
|
||||||
bool SaveToDisk(void);
|
bool SaveToDisk(void);
|
||||||
|
|
||||||
|
/** Loads the player data from the disk file.
|
||||||
|
Returns true on success, false on failure. */
|
||||||
bool LoadFromDisk(void);
|
bool LoadFromDisk(void);
|
||||||
|
|
||||||
|
/** Loads the player data from the specified file.
|
||||||
|
Returns true on success, false on failure. */
|
||||||
|
bool LoadFromFile(const AString & a_FileName);
|
||||||
|
|
||||||
void LoadPermissionsFromDisk(void); // tolua_export
|
void LoadPermissionsFromDisk(void); // tolua_export
|
||||||
|
|
||||||
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
|
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
|
||||||
@ -449,7 +461,13 @@ protected:
|
|||||||
float m_LastGroundHeight;
|
float m_LastGroundHeight;
|
||||||
bool m_bTouchGround;
|
bool m_bTouchGround;
|
||||||
double m_Stance;
|
double m_Stance;
|
||||||
|
|
||||||
|
/** Stores the player's inventory, consisting of crafting grid, hotbar, and main slots */
|
||||||
cInventory m_Inventory;
|
cInventory m_Inventory;
|
||||||
|
|
||||||
|
/** An item grid that stores the player specific enderchest contents */
|
||||||
|
cItemGrid m_EnderChestContents;
|
||||||
|
|
||||||
cWindow * m_CurrentWindow;
|
cWindow * m_CurrentWindow;
|
||||||
cWindow * m_InventoryWindow;
|
cWindow * m_InventoryWindow;
|
||||||
|
|
||||||
@ -510,6 +528,22 @@ protected:
|
|||||||
|
|
||||||
cStatManager m_Stats;
|
cStatManager m_Stats;
|
||||||
|
|
||||||
|
/** Flag representing whether the player is currently in a bed
|
||||||
|
Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
|
||||||
|
bool m_bIsInBed;
|
||||||
|
|
||||||
|
/** How long till the player's inventory will be saved
|
||||||
|
Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */
|
||||||
|
unsigned int m_TicksUntilNextSave;
|
||||||
|
|
||||||
|
/** Flag used by food handling system to determine whether a teleport has just happened
|
||||||
|
Will not apply food penalties if found to be true; will set to false after processing
|
||||||
|
*/
|
||||||
|
bool m_bIsTeleporting;
|
||||||
|
|
||||||
|
/** The UUID of the player, as read from the ClientHandle.
|
||||||
|
If no ClientHandle is given, the UUID is initialized to empty. */
|
||||||
|
AString m_UUID;
|
||||||
|
|
||||||
|
|
||||||
/** Sets the speed and sends it to the client, so that they are forced to move so. */
|
/** Sets the speed and sends it to the client, so that they are forced to move so. */
|
||||||
@ -538,14 +572,9 @@ protected:
|
|||||||
/** Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) */
|
/** Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) */
|
||||||
void ApplyFoodExhaustionFromMovement();
|
void ApplyFoodExhaustionFromMovement();
|
||||||
|
|
||||||
/** Flag representing whether the player is currently in a bed
|
/** Returns the filename for the player data based on the UUID given.
|
||||||
Set by a right click on unoccupied bed, unset by a time fast forward or teleport */
|
This can be used both for online and offline UUIDs. */
|
||||||
bool m_bIsInBed;
|
AString GetUUIDFileName(const AString & a_UUID);
|
||||||
|
|
||||||
/** How long till the player's inventory will be saved
|
|
||||||
Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */
|
|
||||||
unsigned int m_TicksUntilNextSave;
|
|
||||||
|
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "FireChargeEntity.h"
|
#include "FireChargeEntity.h"
|
||||||
#include "FireworkEntity.h"
|
#include "FireworkEntity.h"
|
||||||
#include "GhastFireballEntity.h"
|
#include "GhastFireballEntity.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -67,16 +68,17 @@ protected:
|
|||||||
|
|
||||||
if (cBlockInfo::IsSolid(a_BlockType))
|
if (cBlockInfo::IsSolid(a_BlockType))
|
||||||
{
|
{
|
||||||
// The projectile hit a solid block
|
// The projectile hit a solid block, calculate the exact hit coords:
|
||||||
// Calculate the exact hit coords:
|
cBoundingBox bb(a_BlockX, a_BlockX + 1, a_BlockY, a_BlockY + 1, a_BlockZ, a_BlockZ + 1); // Bounding box of the block hit
|
||||||
cBoundingBox bb(a_BlockX, a_BlockX + 1, a_BlockY, a_BlockY + 1, a_BlockZ, a_BlockZ + 1);
|
const Vector3d LineStart = m_Projectile->GetPosition(); // Start point for the imaginary line that goes through the block hit
|
||||||
Vector3d Line1 = m_Projectile->GetPosition();
|
const Vector3d LineEnd = LineStart + m_Projectile->GetSpeed(); // End point for the imaginary line that goes through the block hit
|
||||||
Vector3d Line2 = Line1 + m_Projectile->GetSpeed();
|
double LineCoeff = 0; // Used to calculate where along the line an intersection with the bounding box occurs
|
||||||
double LineCoeff = 0;
|
eBlockFace Face; // Face hit
|
||||||
eBlockFace Face;
|
|
||||||
if (bb.CalcLineIntersection(Line1, Line2, LineCoeff, Face))
|
if (bb.CalcLineIntersection(LineStart, LineEnd, LineCoeff, Face))
|
||||||
{
|
{
|
||||||
Vector3d Intersection = Line1 + m_Projectile->GetSpeed() * LineCoeff;
|
Vector3d Intersection = LineStart + m_Projectile->GetSpeed() * LineCoeff; // Point where projectile goes into the hit block
|
||||||
|
|
||||||
if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile, a_BlockX, a_BlockY, a_BlockZ, Face, &Intersection))
|
if (cPluginManager::Get()->CallHookProjectileHitBlock(*m_Projectile, a_BlockX, a_BlockY, a_BlockZ, Face, &Intersection))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -140,7 +142,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
(a_Entity == m_Projectile) || // Do not check collisions with self
|
(a_Entity == m_Projectile) || // Do not check collisions with self
|
||||||
(a_Entity == m_Projectile->GetCreator()) // Do not check whoever shot the projectile
|
(a_Entity->GetUniqueID() == m_Projectile->GetCreatorUniqueID()) // Do not check whoever shot the projectile
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// TODO: Don't check creator only for the first 5 ticks
|
// TODO: Don't check creator only for the first 5 ticks
|
||||||
@ -161,7 +163,12 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Some entities don't interact with the projectiles (pickups, falling blocks)
|
if (!a_Entity->IsMob() && !a_Entity->IsMinecart() && !a_Entity->IsPlayer() && !a_Entity->IsBoat())
|
||||||
|
{
|
||||||
|
// Not an entity that interacts with a projectile
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, *a_Entity))
|
if (cPluginManager::Get()->CallHookProjectileHitEntity(*m_Projectile, *a_Entity))
|
||||||
{
|
{
|
||||||
// A plugin disagreed.
|
// A plugin disagreed.
|
||||||
@ -209,7 +216,10 @@ protected:
|
|||||||
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
|
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
|
||||||
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
|
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
|
||||||
m_ProjectileKind(a_Kind),
|
m_ProjectileKind(a_Kind),
|
||||||
m_Creator(a_Creator),
|
m_CreatorData(
|
||||||
|
((a_Creator != NULL) ? a_Creator->GetUniqueID() : -1),
|
||||||
|
((a_Creator != NULL) ? (a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : "") : "")
|
||||||
|
),
|
||||||
m_IsInGround(false)
|
m_IsInGround(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -221,7 +231,7 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a
|
|||||||
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
|
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
|
||||||
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
|
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
|
||||||
m_ProjectileKind(a_Kind),
|
m_ProjectileKind(a_Kind),
|
||||||
m_Creator(a_Creator),
|
m_CreatorData(a_Creator->GetUniqueID(), a_Creator->IsPlayer() ? ((cPlayer *)a_Creator)->GetName() : ""),
|
||||||
m_IsInGround(false)
|
m_IsInGround(false)
|
||||||
{
|
{
|
||||||
SetSpeed(a_Speed);
|
SetSpeed(a_Speed);
|
||||||
@ -298,7 +308,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
|
|||||||
case pkEgg: return "Egg";
|
case pkEgg: return "Egg";
|
||||||
case pkGhastFireball: return "Fireball";
|
case pkGhastFireball: return "Fireball";
|
||||||
case pkFireCharge: return "SmallFireball";
|
case pkFireCharge: return "SmallFireball";
|
||||||
case pkEnderPearl: return "ThrownEnderPearl";
|
case pkEnderPearl: return "ThrownEnderpearl";
|
||||||
case pkExpBottle: return "ThrownExpBottle";
|
case pkExpBottle: return "ThrownExpBottle";
|
||||||
case pkSplashPotion: return "ThrownPotion";
|
case pkSplashPotion: return "ThrownPotion";
|
||||||
case pkWitherSkull: return "WitherSkull";
|
case pkWitherSkull: return "WitherSkull";
|
||||||
@ -316,8 +326,9 @@ AString cProjectileEntity::GetMCAClassName(void) const
|
|||||||
void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
|
||||||
if (GetProjectileKind() != pkArrow) // See cArrow::Tick
|
// TODO: see BroadcastMovementUpdate; RelativeMove packet jerkiness affects projectiles too (cause of sympton described in cArrowEntity::Tick())
|
||||||
|
if (GetProjectileKind() != pkArrow)
|
||||||
{
|
{
|
||||||
BroadcastMovementUpdate();
|
BroadcastMovementUpdate();
|
||||||
}
|
}
|
||||||
@ -335,19 +346,10 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3d PerTickSpeed = GetSpeed() / 20;
|
const Vector3d PerTickSpeed = GetSpeed() / 20;
|
||||||
Vector3d Pos = GetPosition();
|
const Vector3d Pos = GetPosition();
|
||||||
|
const Vector3d NextPos = Pos + PerTickSpeed;
|
||||||
// Trace the tick's worth of movement as a line:
|
|
||||||
Vector3d NextPos = Pos + PerTickSpeed;
|
|
||||||
cProjectileTracerCallback TracerCallback(this);
|
|
||||||
if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
|
|
||||||
{
|
|
||||||
// Something has been hit, abort all other processing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff
|
|
||||||
|
|
||||||
// Test for entity collisions:
|
// Test for entity collisions:
|
||||||
cProjectileEntityCollisionCallback EntityCollisionCallback(this, Pos, NextPos);
|
cProjectileEntityCollisionCallback EntityCollisionCallback(this, Pos, NextPos);
|
||||||
a_Chunk.ForEachEntity(EntityCollisionCallback);
|
a_Chunk.ForEachEntity(EntityCollisionCallback);
|
||||||
@ -364,10 +366,19 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
HitPos.x, HitPos.y, HitPos.z,
|
HitPos.x, HitPos.y, HitPos.z,
|
||||||
EntityCollisionCallback.GetMinCoeff()
|
EntityCollisionCallback.GetMinCoeff()
|
||||||
);
|
);
|
||||||
|
|
||||||
OnHitEntity(*(EntityCollisionCallback.GetHitEntity()), HitPos);
|
OnHitEntity(*(EntityCollisionCallback.GetHitEntity()), HitPos);
|
||||||
}
|
}
|
||||||
// TODO: Test the entities in the neighboring chunks, too
|
// TODO: Test the entities in the neighboring chunks, too
|
||||||
|
|
||||||
|
// Trace the tick's worth of movement as a line:
|
||||||
|
cProjectileTracerCallback TracerCallback(this);
|
||||||
|
if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
|
||||||
|
{
|
||||||
|
// Something has been hit, abort all other processing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The tracer also checks the blocks for slowdown blocks - water and lava - and stores it for later in its SlowdownCoeff
|
||||||
|
|
||||||
// Update the position:
|
// Update the position:
|
||||||
SetPosition(NextPos);
|
SetPosition(NextPos);
|
||||||
|
@ -66,8 +66,15 @@ public:
|
|||||||
/// Returns the kind of the projectile (fast class identification)
|
/// Returns the kind of the projectile (fast class identification)
|
||||||
eKind GetProjectileKind(void) const { return m_ProjectileKind; }
|
eKind GetProjectileKind(void) const { return m_ProjectileKind; }
|
||||||
|
|
||||||
/// Returns the entity who created this projectile; may be NULL
|
/** Returns the unique ID of the entity who created this projectile
|
||||||
cEntity * GetCreator(void) { return m_Creator; }
|
May return an ID <0
|
||||||
|
*/
|
||||||
|
int GetCreatorUniqueID(void) { return m_CreatorData.m_UniqueID; }
|
||||||
|
|
||||||
|
/** Returns the name of the player that created the projectile
|
||||||
|
Will be empty for non-player creators
|
||||||
|
*/
|
||||||
|
AString GetCreatorName(void) const { return m_CreatorData.m_Name; }
|
||||||
|
|
||||||
/// Returns the string that is used as the entity type (class name) in MCA files
|
/// Returns the string that is used as the entity type (class name) in MCA files
|
||||||
AString GetMCAClassName(void) const;
|
AString GetMCAClassName(void) const;
|
||||||
@ -81,10 +88,29 @@ public:
|
|||||||
void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; }
|
void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
/** A structure that stores the Entity ID and Playername of the projectile's creator
|
||||||
|
Used to migitate invalid pointers caused by the creator being destroyed
|
||||||
|
*/
|
||||||
|
struct CreatorData
|
||||||
|
{
|
||||||
|
CreatorData(int a_UniqueID, const AString & a_Name) :
|
||||||
|
m_UniqueID(a_UniqueID),
|
||||||
|
m_Name(a_Name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const int m_UniqueID;
|
||||||
|
AString m_Name;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The type of projectile I am */
|
||||||
eKind m_ProjectileKind;
|
eKind m_ProjectileKind;
|
||||||
|
|
||||||
/// The entity who has created this projectile; may be NULL (e. g. for dispensers)
|
/** The structure for containing the entity ID and name who has created this projectile
|
||||||
cEntity * m_Creator;
|
The ID and/or name may be NULL (e.g. for dispensers/mobs)
|
||||||
|
*/
|
||||||
|
CreatorData m_CreatorData;
|
||||||
|
|
||||||
/// True if the projectile has hit the ground and is stuck there
|
/// True if the projectile has hit the ground and is stuck there
|
||||||
bool m_IsInGround;
|
bool m_IsInGround;
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
|
|
||||||
cThrownEggEntity::cThrownEggEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
|
cThrownEggEntity::cThrownEggEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
|
||||||
super(pkEgg, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
|
super(pkEgg, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25),
|
||||||
|
m_DestroyTimer(-1)
|
||||||
{
|
{
|
||||||
SetSpeed(a_Speed);
|
SetSpeed(a_Speed);
|
||||||
}
|
}
|
||||||
@ -21,7 +22,7 @@ void cThrownEggEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_H
|
|||||||
{
|
{
|
||||||
TrySpawnChicken(a_HitPos);
|
TrySpawnChicken(a_HitPos);
|
||||||
|
|
||||||
Destroy();
|
m_DestroyTimer = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ void cThrownEggEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_Hit
|
|||||||
TrySpawnChicken(a_HitPos);
|
TrySpawnChicken(a_HitPos);
|
||||||
a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
|
a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
|
||||||
|
|
||||||
Destroy(true);
|
m_DestroyTimer = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,8 +30,29 @@ protected:
|
|||||||
// cProjectileEntity overrides:
|
// cProjectileEntity overrides:
|
||||||
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
|
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
|
||||||
virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
|
virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
|
||||||
|
virtual void Tick (float a_Dt, cChunk & a_Chunk) override
|
||||||
|
{
|
||||||
|
if (m_DestroyTimer > 0)
|
||||||
|
{
|
||||||
|
m_DestroyTimer--;
|
||||||
|
if (m_DestroyTimer == 0)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Randomly decides whether to spawn a chicken where the egg lands.
|
// Randomly decides whether to spawn a chicken where the egg lands.
|
||||||
void TrySpawnChicken(const Vector3d & a_HitPos);
|
void TrySpawnChicken(const Vector3d & a_HitPos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Time in ticks to wait for the hit animation to begin before destroying */
|
||||||
|
int m_DestroyTimer;
|
||||||
|
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||||
|
|
||||||
#include "ThrownEnderPearlEntity.h"
|
#include "ThrownEnderPearlEntity.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cThrownEnderPearlEntity::cThrownEnderPearlEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
|
cThrownEnderPearlEntity::cThrownEnderPearlEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
|
||||||
super(pkEnderPearl, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
|
super(pkEnderPearl, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25),
|
||||||
|
m_DestroyTimer(-1)
|
||||||
{
|
{
|
||||||
SetSpeed(a_Speed);
|
SetSpeed(a_Speed);
|
||||||
}
|
}
|
||||||
@ -21,7 +23,7 @@ void cThrownEnderPearlEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockF
|
|||||||
// TODO: Tweak a_HitPos based on block face.
|
// TODO: Tweak a_HitPos based on block face.
|
||||||
TeleportCreator(a_HitPos);
|
TeleportCreator(a_HitPos);
|
||||||
|
|
||||||
Destroy();
|
m_DestroyTimer = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +38,7 @@ void cThrownEnderPearlEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d
|
|||||||
TeleportCreator(a_HitPos);
|
TeleportCreator(a_HitPos);
|
||||||
a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
|
a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
|
||||||
|
|
||||||
Destroy(true);
|
m_DestroyTimer = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -45,10 +47,34 @@ void cThrownEnderPearlEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d
|
|||||||
|
|
||||||
void cThrownEnderPearlEntity::TeleportCreator(const Vector3d & a_HitPos)
|
void cThrownEnderPearlEntity::TeleportCreator(const Vector3d & a_HitPos)
|
||||||
{
|
{
|
||||||
// Teleport the creator here, make them take 5 damage:
|
if (m_CreatorData.m_Name.empty())
|
||||||
if (m_Creator != NULL)
|
|
||||||
{
|
{
|
||||||
m_Creator->TeleportToCoords(a_HitPos.x + 0.5, a_HitPos.y + 1.7, a_HitPos.z + 0.5);
|
return;
|
||||||
m_Creator->TakeDamage(dtEnderPearl, this, 5, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class cProjectileCreatorCallbackForPlayers : public cPlayerListCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cProjectileCreatorCallbackForPlayers(cEntity * a_Attacker, Vector3i a_HitPos) :
|
||||||
|
m_Attacker(a_Attacker),
|
||||||
|
m_HitPos(a_HitPos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cPlayer * a_Entity) override
|
||||||
|
{
|
||||||
|
// Teleport the creator here, make them take 5 damage:
|
||||||
|
a_Entity->TeleportToCoords(m_HitPos.x, m_HitPos.y + 0.2, m_HitPos.z);
|
||||||
|
a_Entity->TakeDamage(dtEnderPearl, m_Attacker, 5, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
cEntity * m_Attacker;
|
||||||
|
Vector3i m_HitPos;
|
||||||
|
};
|
||||||
|
|
||||||
|
cProjectileCreatorCallbackForPlayers PCCFP(this, a_HitPos);
|
||||||
|
GetWorld()->FindAndDoWithPlayer(m_CreatorData.m_Name, PCCFP);
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,29 @@ protected:
|
|||||||
// cProjectileEntity overrides:
|
// cProjectileEntity overrides:
|
||||||
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
|
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
|
||||||
virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
|
virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
|
||||||
|
virtual void Tick (float a_Dt, cChunk & a_Chunk) override
|
||||||
|
{
|
||||||
|
if (m_DestroyTimer > 0)
|
||||||
|
{
|
||||||
|
m_DestroyTimer--;
|
||||||
|
if (m_DestroyTimer == 0)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Teleports the creator where the ender pearl lands.
|
/** Teleports the creator where the ender pearl lands */
|
||||||
void TeleportCreator(const Vector3d & a_HitPos);
|
void TeleportCreator(const Vector3d & a_HitPos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Time in ticks to wait for the hit animation to begin before destroying */
|
||||||
|
int m_DestroyTimer;
|
||||||
|
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
|
|
||||||
cThrownSnowballEntity::cThrownSnowballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
|
cThrownSnowballEntity::cThrownSnowballEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d & a_Speed) :
|
||||||
super(pkSnowball, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25)
|
super(pkSnowball, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25),
|
||||||
|
m_DestroyTimer(-1)
|
||||||
{
|
{
|
||||||
SetSpeed(a_Speed);
|
SetSpeed(a_Speed);
|
||||||
}
|
}
|
||||||
@ -19,7 +20,7 @@ cThrownSnowballEntity::cThrownSnowballEntity(cEntity * a_Creator, double a_X, do
|
|||||||
|
|
||||||
void cThrownSnowballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
|
void cThrownSnowballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace)
|
||||||
{
|
{
|
||||||
Destroy();
|
m_DestroyTimer = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -40,5 +41,5 @@ void cThrownSnowballEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d &
|
|||||||
// TODO: If entity is Ender Crystal, destroy it
|
// TODO: If entity is Ender Crystal, destroy it
|
||||||
a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
|
a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
|
||||||
|
|
||||||
Destroy(true);
|
m_DestroyTimer = 5;
|
||||||
}
|
}
|
||||||
|
@ -30,5 +30,26 @@ protected:
|
|||||||
// cProjectileEntity overrides:
|
// cProjectileEntity overrides:
|
||||||
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
|
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) override;
|
||||||
virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
|
virtual void OnHitEntity (cEntity & a_EntityHit, const Vector3d & a_HitPos) override;
|
||||||
|
virtual void Tick (float a_Dt, cChunk & a_Chunk) override
|
||||||
|
{
|
||||||
|
if (m_DestroyTimer > 0)
|
||||||
|
{
|
||||||
|
m_DestroyTimer--;
|
||||||
|
if (m_DestroyTimer == 0)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** Time in ticks to wait for the hit animation to begin before destroying */
|
||||||
|
int m_DestroyTimer;
|
||||||
|
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
@ -58,9 +58,9 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
|
|||||||
"o: 50: 4\n" /* torch */
|
"o: 50: 4\n" /* torch */
|
||||||
"p: 13: 0\n" /* gravel */
|
"p: 13: 0\n" /* gravel */
|
||||||
"q: 5: 0\n" /* wood */
|
"q: 5: 0\n" /* wood */
|
||||||
"r: 96:12\n" /* trapdoor */
|
"r: 96: 8\n" /* trapdoor */
|
||||||
"s:128: 5\n" /* sandstonestairs */
|
"s:128: 5\n" /* sandstonestairs */
|
||||||
"t:107: 0\n" /* fencegate */
|
"t:107: 2\n" /* fencegate */
|
||||||
"u:128: 4\n" /* sandstonestairs */
|
"u:128: 4\n" /* sandstonestairs */
|
||||||
"v:134: 3\n" /* 134 */
|
"v:134: 3\n" /* 134 */
|
||||||
"w: 85: 0\n" /* fence */
|
"w: 85: 0\n" /* fence */
|
||||||
@ -288,7 +288,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
|
|||||||
"d: 13: 0\n" /* gravel */
|
"d: 13: 0\n" /* gravel */
|
||||||
"e: 5: 0\n" /* wood */
|
"e: 5: 0\n" /* wood */
|
||||||
"f:128: 5\n" /* sandstonestairs */
|
"f:128: 5\n" /* sandstonestairs */
|
||||||
"g:107: 0\n" /* fencegate */
|
"g:107: 2\n" /* fencegate */
|
||||||
"h:128: 4\n" /* sandstonestairs */
|
"h:128: 4\n" /* sandstonestairs */
|
||||||
"i:134: 1\n" /* 134 */
|
"i:134: 1\n" /* 134 */
|
||||||
"j:134: 3\n" /* 134 */
|
"j:134: 3\n" /* 134 */
|
||||||
@ -298,7 +298,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
|
|||||||
"n:134: 5\n" /* 134 */
|
"n:134: 5\n" /* 134 */
|
||||||
"o:134: 7\n" /* 134 */
|
"o:134: 7\n" /* 134 */
|
||||||
"p:134: 4\n" /* 134 */
|
"p:134: 4\n" /* 134 */
|
||||||
"q:107: 5\n" /* fencegate */
|
"q:107: 1\n" /* fencegate */
|
||||||
"r: 64: 1\n" /* wooddoorblock */
|
"r: 64: 1\n" /* wooddoorblock */
|
||||||
"s: 65: 3\n" /* ladder */
|
"s: 65: 3\n" /* ladder */
|
||||||
"t: 50: 3\n" /* torch */
|
"t: 50: 3\n" /* torch */
|
||||||
@ -2195,7 +2195,7 @@ const cPrefab::sDef g_AlchemistVillagePrefabs[] =
|
|||||||
0,
|
0,
|
||||||
|
|
||||||
// MoveToGround:
|
// MoveToGround:
|
||||||
false,
|
true,
|
||||||
}, // LittleHouse8
|
}, // LittleHouse8
|
||||||
|
|
||||||
|
|
||||||
|
@ -294,7 +294,7 @@ const cPrefab::sDef g_JapaneseVillagePrefabs[] =
|
|||||||
0,
|
0,
|
||||||
|
|
||||||
// MoveToGround:
|
// MoveToGround:
|
||||||
false,
|
true,
|
||||||
}, // Farm
|
}, // Farm
|
||||||
|
|
||||||
|
|
||||||
|
@ -356,6 +356,8 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
|
|||||||
"e: 8: 0\n" /* water */
|
"e: 8: 0\n" /* water */
|
||||||
"f: 50: 5\n" /* torch */
|
"f: 50: 5\n" /* torch */
|
||||||
"g: 59: 7\n" /* crops */
|
"g: 59: 7\n" /* crops */
|
||||||
|
"h: 59: 0\n" /* crops */
|
||||||
|
"i: 59: 1\n" /* crops */
|
||||||
"m: 19: 0\n" /* sponge */,
|
"m: 19: 0\n" /* sponge */,
|
||||||
|
|
||||||
// Block data:
|
// Block data:
|
||||||
@ -403,12 +405,12 @@ const cPrefab::sDef g_PlainsVillagePrefabs[] =
|
|||||||
/* * 012345678901234 */
|
/* * 012345678901234 */
|
||||||
/* 0 */ "f.....f.f.....f"
|
/* 0 */ "f.....f.f.....f"
|
||||||
/* 1 */ ".gg.gg...gg.gg."
|
/* 1 */ ".gg.gg...gg.gg."
|
||||||
/* 2 */ ".g...g...gg.gg."
|
/* 2 */ ".gh.hg...gg.gg."
|
||||||
/* 3 */ ".g.......gg.gg."
|
/* 3 */ ".gh.ih...gg.gg."
|
||||||
/* 4 */ ".gg..g...gg.gg."
|
/* 4 */ ".gg.hg...gg.gg."
|
||||||
/* 5 */ ".gg..g...gg.gg."
|
/* 5 */ ".gg.hg...gg.gg."
|
||||||
/* 6 */ "..g..g...gg.gg."
|
/* 6 */ ".ig.hg...gg.gg."
|
||||||
/* 7 */ "..g.g....gg.gg."
|
/* 7 */ ".hg.gh...gg.gg."
|
||||||
/* 8 */ "f.....f.f.....f"
|
/* 8 */ "f.....f.f.....f"
|
||||||
|
|
||||||
// Level 4
|
// Level 4
|
||||||
|
@ -71,9 +71,24 @@
|
|||||||
|
|
||||||
#define FORMATSTRING(formatIndex, va_argsIndex) __attribute__((format (printf, formatIndex, va_argsIndex)))
|
#define FORMATSTRING(formatIndex, va_argsIndex) __attribute__((format (printf, formatIndex, va_argsIndex)))
|
||||||
|
|
||||||
#define SIZE_T_FMT "%zu"
|
#if defined(_WIN32)
|
||||||
#define SIZE_T_FMT_PRECISION(x) "%" #x "zu"
|
// We're compiling on MinGW, which uses an old MSVCRT library that has no support for size_t printfing.
|
||||||
#define SIZE_T_FMT_HEX "%zx"
|
// We need direct size formats:
|
||||||
|
#if defined(_WIN64)
|
||||||
|
#define SIZE_T_FMT "%I64u"
|
||||||
|
#define SIZE_T_FMT_PRECISION(x) "%" #x "I64u"
|
||||||
|
#define SIZE_T_FMT_HEX "%I64x"
|
||||||
|
#else
|
||||||
|
#define SIZE_T_FMT "%u"
|
||||||
|
#define SIZE_T_FMT_PRECISION(x) "%" #x "u"
|
||||||
|
#define SIZE_T_FMT_HEX "%x"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// We're compiling on Linux, so we can use libc's size_t printf format:
|
||||||
|
#define SIZE_T_FMT "%zu"
|
||||||
|
#define SIZE_T_FMT_PRECISION(x) "%" #x "zu"
|
||||||
|
#define SIZE_T_FMT_HEX "%zx"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define NORETURN __attribute((__noreturn__))
|
#define NORETURN __attribute((__noreturn__))
|
||||||
|
|
||||||
|
@ -179,6 +179,8 @@ bool cHTTPServer::Initialize(const AString & a_PortsIPv4, const AString & a_Port
|
|||||||
|
|
||||||
// Open up requested ports:
|
// Open up requested ports:
|
||||||
bool HasAnyPort;
|
bool HasAnyPort;
|
||||||
|
m_ListenThreadIPv4.SetReuseAddr(true);
|
||||||
|
m_ListenThreadIPv6.SetReuseAddr(true);
|
||||||
HasAnyPort = m_ListenThreadIPv4.Initialize(a_PortsIPv4);
|
HasAnyPort = m_ListenThreadIPv4.Initialize(a_PortsIPv4);
|
||||||
HasAnyPort = m_ListenThreadIPv6.Initialize(a_PortsIPv6) || HasAnyPort;
|
HasAnyPort = m_ListenThreadIPv6.Initialize(a_PortsIPv6) || HasAnyPort;
|
||||||
if (!HasAnyPort)
|
if (!HasAnyPort)
|
||||||
|
@ -55,7 +55,7 @@ public:
|
|||||||
// Too little force, ignore the shot
|
// Too little force, ignore the shot
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Force = std::max(Force, 1.0);
|
Force = std::min(Force, 1.0);
|
||||||
|
|
||||||
// Create the arrow entity:
|
// Create the arrow entity:
|
||||||
cArrowEntity * Arrow = new cArrowEntity(*a_Player, Force * 2);
|
cArrowEntity * Arrow = new cArrowEntity(*a_Player, Force * 2);
|
||||||
@ -70,16 +70,7 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cFastRandom Random;
|
a_Player->GetWorld()->BroadcastSoundEffect("random.bow", (int)a_Player->GetPosX() * 8, (int)a_Player->GetPosY() * 8, (int)a_Player->GetPosZ() * 8, 0.5, (float)Force);
|
||||||
a_Player->GetWorld()->BroadcastSoundEffect(
|
|
||||||
"random.bow",
|
|
||||||
(int)std::floor(a_Player->GetPosX() * 8.0),
|
|
||||||
(int)std::floor(a_Player->GetPosY() * 8.0),
|
|
||||||
(int)std::floor(a_Player->GetPosZ() * 8.0),
|
|
||||||
1.0F,
|
|
||||||
1.0F / (Random.NextFloat(1.0F) * 0.4F + 1.2F) + (float)Force * 0.5F
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!a_Player->IsGameModeCreative())
|
if (!a_Player->IsGameModeCreative())
|
||||||
{
|
{
|
||||||
a_Player->UseEquippedItem();
|
a_Player->UseEquippedItem();
|
||||||
|
@ -41,7 +41,7 @@ public:
|
|||||||
|
|
||||||
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
|
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
|
||||||
{
|
{
|
||||||
if (a_BlockFace > 0)
|
if (a_BlockFace != BLOCK_FACE_NONE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -95,29 +95,15 @@ public:
|
|||||||
|
|
||||||
bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock)
|
bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock)
|
||||||
{
|
{
|
||||||
if (a_BlockFace < 0)
|
if (a_BlockFace != BLOCK_FACE_NONE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLOCKTYPE CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
BLOCKTYPE CurrentBlock;
|
||||||
bool CanWashAway = cFluidSimulator::CanWashAway(CurrentBlock);
|
Vector3i BlockPos;
|
||||||
if (!CanWashAway)
|
if (!GetPlacementCoordsFromTrace(a_World, a_Player, BlockPos, CurrentBlock))
|
||||||
{
|
{
|
||||||
// The block pointed at cannot be washed away, so put fluid on top of it / on its sides
|
|
||||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
|
||||||
CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!CanWashAway &&
|
|
||||||
(CurrentBlock != E_BLOCK_AIR) &&
|
|
||||||
(CurrentBlock != E_BLOCK_WATER) &&
|
|
||||||
(CurrentBlock != E_BLOCK_STATIONARY_WATER) &&
|
|
||||||
(CurrentBlock != E_BLOCK_LAVA) &&
|
|
||||||
(CurrentBlock != E_BLOCK_STATIONARY_LAVA)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Cannot place water here
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +124,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wash away anything that was there prior to placing:
|
// Wash away anything that was there prior to placing:
|
||||||
if (CanWashAway)
|
if (cFluidSimulator::CanWashAway(CurrentBlock))
|
||||||
{
|
{
|
||||||
cBlockHandler * Handler = BlockHandler(CurrentBlock);
|
cBlockHandler * Handler = BlockHandler(CurrentBlock);
|
||||||
if (Handler->DoesDropOnUnsuitable())
|
if (Handler->DoesDropOnUnsuitable())
|
||||||
@ -149,13 +135,13 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FluidBlock, 0);
|
a_World->SetBlock(BlockPos.x, BlockPos.y, BlockPos.z, a_FluidBlock, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & BlockPos)
|
bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos)
|
||||||
{
|
{
|
||||||
class cCallbacks :
|
class cCallbacks :
|
||||||
public cBlockTracer::cCallbacks
|
public cBlockTracer::cCallbacks
|
||||||
@ -198,8 +184,49 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BlockPos.Set(Callbacks.m_Pos.x, Callbacks.m_Pos.y, Callbacks.m_Pos.z);
|
a_BlockPos = Callbacks.m_Pos;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GetPlacementCoordsFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos, BLOCKTYPE & a_BlockType)
|
||||||
|
{
|
||||||
|
class cCallbacks :
|
||||||
|
public cBlockTracer::cCallbacks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vector3i m_Pos;
|
||||||
|
BLOCKTYPE m_ReplacedBlock;
|
||||||
|
|
||||||
|
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
|
||||||
|
{
|
||||||
|
if (a_BlockType != E_BLOCK_AIR)
|
||||||
|
{
|
||||||
|
m_ReplacedBlock = a_BlockType;
|
||||||
|
if (!cFluidSimulator::CanWashAway(a_BlockType))
|
||||||
|
{
|
||||||
|
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, (eBlockFace)a_EntryFace); // Was an unwashawayable block, can't overwrite it!
|
||||||
|
}
|
||||||
|
m_Pos.Set(a_BlockX, a_BlockY, a_BlockZ); // (Block could be washed away, replace it)
|
||||||
|
return true; // Abort tracing
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} Callbacks;
|
||||||
|
|
||||||
|
cLineBlockTracer Tracer(*a_World, Callbacks);
|
||||||
|
Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
|
||||||
|
Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
|
||||||
|
|
||||||
|
// cTracer::Trace returns true when whole line was traversed. By returning true when we hit something, we ensure that this never happens if liquid could be placed
|
||||||
|
// Use this to judge whether the position is valid
|
||||||
|
if (!Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z))
|
||||||
|
{
|
||||||
|
a_BlockPos = Callbacks.m_Pos;
|
||||||
|
a_BlockType = Callbacks.m_ReplacedBlock;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "ItemSign.h"
|
#include "ItemSign.h"
|
||||||
#include "ItemMobHead.h"
|
#include "ItemMobHead.h"
|
||||||
#include "ItemSpawnEgg.h"
|
#include "ItemSpawnEgg.h"
|
||||||
|
#include "ItemString.h"
|
||||||
#include "ItemSugarcane.h"
|
#include "ItemSugarcane.h"
|
||||||
#include "ItemSword.h"
|
#include "ItemSword.h"
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ cItemHandler * cItemHandler::m_ItemHandler[2268];
|
|||||||
|
|
||||||
cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
|
cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
|
||||||
{
|
{
|
||||||
if (a_ItemType < 0)
|
if ((a_ItemType < 0) || ((unsigned long)a_ItemType >= ARRAYCOUNT(m_ItemHandler)))
|
||||||
{
|
{
|
||||||
// Either nothing (-1), or bad value, both cases should return the air handler
|
// Either nothing (-1), or bad value, both cases should return the air handler
|
||||||
if (a_ItemType < -1)
|
if (a_ItemType < -1)
|
||||||
@ -129,6 +130,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
|
|||||||
case E_ITEM_HEAD: return new cItemMobHeadHandler(a_ItemType);
|
case E_ITEM_HEAD: return new cItemMobHeadHandler(a_ItemType);
|
||||||
case E_ITEM_SNOWBALL: return new cItemSnowballHandler();
|
case E_ITEM_SNOWBALL: return new cItemSnowballHandler();
|
||||||
case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType);
|
case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType);
|
||||||
|
case E_ITEM_STRING: return new cItemStringHandler(a_ItemType);
|
||||||
case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType);
|
case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType);
|
||||||
|
|
||||||
case E_ITEM_WOODEN_HOE:
|
case E_ITEM_WOODEN_HOE:
|
||||||
|
39
src/Items/ItemString.h
Normal file
39
src/Items/ItemString.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ItemHandler.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cItemStringHandler :
|
||||||
|
public cItemHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cItemStringHandler(int a_ItemType) :
|
||||||
|
cItemHandler(a_ItemType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsPlaceable(void) override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool GetPlacementBlockTypeMeta(
|
||||||
|
cWorld * a_World, cPlayer * a_Player,
|
||||||
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||||
|
int a_CursorX, int a_CursorY, int a_CursorZ,
|
||||||
|
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||||
|
) override
|
||||||
|
{
|
||||||
|
a_BlockType = E_BLOCK_TRIPWIRE;
|
||||||
|
a_BlockMeta = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -200,8 +200,8 @@ bool cMap::UpdatePixel(unsigned int a_X, unsigned int a_Z)
|
|||||||
int BlockX = m_CenterX + ((a_X - (m_Width / 2)) * PixelWidth);
|
int BlockX = m_CenterX + ((a_X - (m_Width / 2)) * PixelWidth);
|
||||||
int BlockZ = m_CenterZ + ((a_Z - (m_Height / 2)) * PixelWidth);
|
int BlockZ = m_CenterZ + ((a_Z - (m_Height / 2)) * PixelWidth);
|
||||||
|
|
||||||
int ChunkX, ChunkY, ChunkZ;
|
int ChunkX, ChunkZ;
|
||||||
m_World->BlockToChunk(BlockX, 0, BlockZ, ChunkX, ChunkY, ChunkZ);
|
cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
|
||||||
|
|
||||||
int RelX = BlockX - (ChunkX * cChunkDef::Width);
|
int RelX = BlockX - (ChunkX * cChunkDef::Width);
|
||||||
int RelZ = BlockZ - (ChunkZ * cChunkDef::Width);
|
int RelZ = BlockZ - (ChunkZ * cChunkDef::Width);
|
||||||
|
@ -67,9 +67,27 @@ void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
|||||||
}
|
}
|
||||||
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER);
|
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_GUNPOWDER);
|
||||||
|
|
||||||
if ((a_Killer != NULL) && (a_Killer->IsProjectile()))
|
if ((a_Killer != NULL) && a_Killer->IsProjectile() && (((cProjectileEntity *)a_Killer)->GetCreatorUniqueID() >= 0))
|
||||||
{
|
{
|
||||||
if (((cMonster *)((cProjectileEntity *)a_Killer)->GetCreator())->GetMobType() == mtSkeleton)
|
class cProjectileCreatorCallback : public cEntityCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cProjectileCreatorCallback(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
|
{
|
||||||
|
if (a_Entity->IsMob() && ((cMonster *)a_Entity)->GetMobType() == mtSkeleton)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cProjectileCreatorCallback PCC;
|
||||||
|
if (GetWorld()->DoWithEntityByID(((cProjectileEntity *)a_Killer)->GetCreatorUniqueID(), PCC))
|
||||||
{
|
{
|
||||||
// 12 music discs. TickRand starts from 0 to 11. Disk IDs start at 2256, so add that. There.
|
// 12 music discs. TickRand starts from 0 to 11. Disk IDs start at 2256, so add that. There.
|
||||||
AddRandomDropItem(a_Drops, 1, 1, (short)m_World->GetTickRandomNumber(11) + 2256);
|
AddRandomDropItem(a_Drops, 1, 1, (short)m_World->GetTickRandomNumber(11) + 2256);
|
||||||
|
@ -46,8 +46,8 @@ static const struct
|
|||||||
{cMonster::mtSheep, "sheep"},
|
{cMonster::mtSheep, "sheep"},
|
||||||
{cMonster::mtSilverfish, "silverfish"},
|
{cMonster::mtSilverfish, "silverfish"},
|
||||||
{cMonster::mtSkeleton, "skeleton"},
|
{cMonster::mtSkeleton, "skeleton"},
|
||||||
{cMonster::mtSnowGolem, "snowgolem"},
|
|
||||||
{cMonster::mtSlime, "slime"},
|
{cMonster::mtSlime, "slime"},
|
||||||
|
{cMonster::mtSnowGolem, "snowgolem"},
|
||||||
{cMonster::mtSpider, "spider"},
|
{cMonster::mtSpider, "spider"},
|
||||||
{cMonster::mtSquid, "squid"},
|
{cMonster::mtSquid, "squid"},
|
||||||
{cMonster::mtVillager, "villager"},
|
{cMonster::mtVillager, "villager"},
|
||||||
|
@ -49,11 +49,10 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
|||||||
|
|
||||||
void cSkeleton::MoveToPosition(const Vector3f & a_Position)
|
void cSkeleton::MoveToPosition(const Vector3f & a_Position)
|
||||||
{
|
{
|
||||||
// If the destination is in the sun and if it is not night AND the skeleton isn't on fire then block the movement.
|
// If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement
|
||||||
if (
|
if (
|
||||||
!IsOnFire() &&
|
!IsOnFire() &&
|
||||||
(m_World->GetTimeOfDay() < 13187) &&
|
(m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8)
|
||||||
(m_World->GetBlockSkyLight((int) a_Position.x, (int) a_Position.y, (int) a_Position.z) == 15)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_bMovingToDestination = false;
|
m_bMovingToDestination = false;
|
||||||
|
@ -44,11 +44,10 @@ void cZombie::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
|||||||
|
|
||||||
void cZombie::MoveToPosition(const Vector3f & a_Position)
|
void cZombie::MoveToPosition(const Vector3f & a_Position)
|
||||||
{
|
{
|
||||||
// If the destination is in the sun and if it is not night AND the zombie isn't on fire then block the movement.
|
// If the destination is sufficiently skylight challenged AND the skeleton isn't on fire then block the movement
|
||||||
if (
|
if (
|
||||||
!IsOnFire() &&
|
!IsOnFire() &&
|
||||||
(m_World->GetTimeOfDay() < 13187) &&
|
(m_World->GetBlockSkyLight((int)floor(a_Position.x), (int)floor(a_Position.y), (int)floor(a_Position.z)) - m_World->GetSkyDarkness() > 8)
|
||||||
(m_World->GetBlockSkyLight((int)a_Position.x, (int)a_Position.y, (int)a_Position.z) == 15)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_bMovingToDestination = false;
|
m_bMovingToDestination = false;
|
||||||
|
@ -18,7 +18,7 @@ cEvent::cEvent(void)
|
|||||||
m_Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
m_Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
if (m_Event == NULL)
|
if (m_Event == NULL)
|
||||||
{
|
{
|
||||||
LOGERROR("cEvent: cannot create event, GLE = %d. Aborting server.", GetLastError());
|
LOGERROR("cEvent: cannot create event, GLE = %u. Aborting server.", (unsigned)GetLastError());
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
#else // *nix
|
#else // *nix
|
||||||
@ -86,7 +86,7 @@ void cEvent::Wait(void)
|
|||||||
DWORD res = WaitForSingleObject(m_Event, INFINITE);
|
DWORD res = WaitForSingleObject(m_Event, INFINITE);
|
||||||
if (res != WAIT_OBJECT_0)
|
if (res != WAIT_OBJECT_0)
|
||||||
{
|
{
|
||||||
LOGWARN("cEvent: waiting for the event failed: %d, GLE = %d. Continuing, but server may be unstable.", res, GetLastError());
|
LOGWARN("cEvent: waiting for the event failed: %u, GLE = %u. Continuing, but server may be unstable.", (unsigned)res, (unsigned)GetLastError());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int res = sem_wait(m_Event);
|
int res = sem_wait(m_Event);
|
||||||
@ -107,7 +107,7 @@ void cEvent::Set(void)
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!SetEvent(m_Event))
|
if (!SetEvent(m_Event))
|
||||||
{
|
{
|
||||||
LOGWARN("cEvent: Could not set cEvent: GLE = %d", GetLastError());
|
LOGWARN("cEvent: Could not set cEvent: GLE = %u", (unsigned)GetLastError());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int res = sem_post(m_Event);
|
int res = sem_post(m_Event);
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <share.h> // for _SH_DENYWRITE
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ bool cIsThread::Start(void)
|
|||||||
m_Handle = CreateThread(NULL, 0, thrExecute, this, CREATE_SUSPENDED, &m_ThreadID);
|
m_Handle = CreateThread(NULL, 0, thrExecute, this, CREATE_SUSPENDED, &m_ThreadID);
|
||||||
if (m_Handle == NULL)
|
if (m_Handle == NULL)
|
||||||
{
|
{
|
||||||
LOGERROR("ERROR: Could not create thread \"%s\", GLE = %d!", m_ThreadName.c_str(), GetLastError());
|
LOGERROR("ERROR: Could not create thread \"%s\", GLE = %u!", m_ThreadName.c_str(), (unsigned)GetLastError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ResumeThread(m_Handle);
|
ResumeThread(m_Handle);
|
||||||
|
@ -262,7 +262,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
|||||||
AString HexDump;
|
AString HexDump;
|
||||||
if (Response.compare(0, prefix.size(), prefix))
|
if (Response.compare(0, prefix.size(), prefix))
|
||||||
{
|
{
|
||||||
LOGINFO("User \"%s\" failed to auth, bad http status line received", a_UserName.c_str());
|
LOGINFO("User %s failed to auth, bad http status line received", a_UserName.c_str());
|
||||||
LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
|||||||
size_t idxHeadersEnd = Response.find("\r\n\r\n");
|
size_t idxHeadersEnd = Response.find("\r\n\r\n");
|
||||||
if (idxHeadersEnd == AString::npos)
|
if (idxHeadersEnd == AString::npos)
|
||||||
{
|
{
|
||||||
LOGINFO("User \"%s\" failed to authenticate, bad http response header received", a_UserName.c_str());
|
LOGINFO("User %s failed to authenticate, bad http response header received", a_UserName.c_str());
|
||||||
LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
LOG("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) = 0;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) = 0;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) = 0;
|
||||||
virtual void SendRespawn (const cWorld & a_World) = 0;
|
virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) = 0;
|
||||||
virtual void SendExperience (void) = 0;
|
virtual void SendExperience (void) = 0;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) = 0;
|
||||||
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;
|
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) = 0;
|
||||||
|
@ -833,12 +833,12 @@ void cProtocol125::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol125::SendRespawn(const cWorld & a_World)
|
void cProtocol125::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSPacket);
|
cCSLock Lock(m_CSPacket);
|
||||||
if (m_LastSentDimension == a_World.GetDimension())
|
if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks)
|
||||||
{
|
{
|
||||||
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do
|
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cPlayer * Player = m_Client->GetPlayer();
|
cPlayer * Player = m_Client->GetPlayer();
|
||||||
|
@ -72,7 +72,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
|
||||||
virtual void SendExperience (void) override;
|
virtual void SendExperience (void) override;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
||||||
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
||||||
|
@ -158,10 +158,10 @@ void cProtocol161::SendPlayerMaxSpeed(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol161::SendRespawn(const cWorld & a_World)
|
void cProtocol161::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
|
||||||
{
|
{
|
||||||
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
|
// Besides sending the respawn, we need to also send the player max speed, otherwise the client reverts to super-fast
|
||||||
super::SendRespawn(a_World);
|
super::SendRespawn(a_World, a_ShouldIgnoreDimensionChecks);
|
||||||
SendPlayerMaxSpeed();
|
SendPlayerMaxSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ protected:
|
|||||||
virtual void SendGameMode (eGameMode a_GameMode) override;
|
virtual void SendGameMode (eGameMode a_GameMode) override;
|
||||||
virtual void SendHealth (void) override;
|
virtual void SendHealth (void) override;
|
||||||
virtual void SendPlayerMaxSpeed(void) override;
|
virtual void SendPlayerMaxSpeed(void) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
|
||||||
virtual void SendWindowOpen (const cWindow & a_Window) override;
|
virtual void SendWindowOpen (const cWindow & a_Window) override;
|
||||||
|
|
||||||
virtual int ParseEntityAction (void) override;
|
virtual int ParseEntityAction (void) override;
|
||||||
|
@ -986,11 +986,11 @@ void cProtocol172::SendRemoveEntityEffect(const cEntity & a_Entity, int a_Effect
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocol172::SendRespawn(const cWorld & a_World)
|
void cProtocol172::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
|
||||||
{
|
{
|
||||||
if (m_LastSentDimension == a_World.GetDimension())
|
if ((m_LastSentDimension == a_World.GetDimension()) && !a_ShouldIgnoreDimensionChecks)
|
||||||
{
|
{
|
||||||
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do
|
// Must not send a respawn for the world with the same dimension, the client goes cuckoo if we do (unless we are respawning from death)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1221,10 +1221,9 @@ void cProtocol172::SendStatistics(const cStatManager & a_Manager)
|
|||||||
cPacketizer Pkt(*this, 0x37);
|
cPacketizer Pkt(*this, 0x37);
|
||||||
Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
|
Pkt.WriteVarInt(statCount); // TODO 2014-05-11 xdot: Optimization: Send "dirty" statistics only
|
||||||
|
|
||||||
for (unsigned int i = 0; i < (unsigned int)statCount; ++i)
|
for (size_t i = 0; i < (size_t)statCount; ++i)
|
||||||
{
|
{
|
||||||
StatValue Value = a_Manager.GetValue((eStatistic) i);
|
StatValue Value = a_Manager.GetValue((eStatistic) i);
|
||||||
|
|
||||||
const AString & StatName = cStatInfo::GetName((eStatistic) i);
|
const AString & StatName = cStatInfo::GetName((eStatistic) i);
|
||||||
|
|
||||||
Pkt.WriteString(StatName);
|
Pkt.WriteString(StatName);
|
||||||
@ -2334,7 +2333,7 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
|
|||||||
|
|
||||||
for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
|
for (int loretag = NBT.GetFirstChild(displaytag); loretag >= 0; loretag = NBT.GetNextSibling(loretag)) // Loop through array of strings
|
||||||
{
|
{
|
||||||
AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a newline, used internally by MCS to display a new line in the client; don't forget to c_str ;)
|
AppendPrintf(Lore, "%s`", NBT.GetString(loretag).c_str()); // Append the lore with a grave accent/backtick, used internally by MCS to display a new line in the client; don't forget to c_str ;)
|
||||||
}
|
}
|
||||||
|
|
||||||
a_Item.m_Lore = Lore;
|
a_Item.m_Lore = Lore;
|
||||||
|
@ -104,7 +104,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
|
||||||
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
|
virtual void SendSoundEffect (const AString & a_SoundName, int a_SrcX, int a_SrcY, int a_SrcZ, float a_Volume, float a_Pitch) override; // a_Src coords are Block * 8
|
||||||
virtual void SendExperience (void) override;
|
virtual void SendExperience (void) override;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
||||||
|
@ -556,10 +556,10 @@ void cProtocolRecognizer::SendRemoveEntityEffect(const cEntity & a_Entity, int a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProtocolRecognizer::SendRespawn(const cWorld & a_World)
|
void cProtocolRecognizer::SendRespawn(const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks)
|
||||||
{
|
{
|
||||||
ASSERT(m_Protocol != NULL);
|
ASSERT(m_Protocol != NULL);
|
||||||
m_Protocol->SendRespawn(a_World);
|
m_Protocol->SendRespawn(a_World, a_ShouldIgnoreDimensionChecks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ public:
|
|||||||
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
virtual void SendPlayerSpawn (const cPlayer & a_Player) override;
|
||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
||||||
virtual void SendRespawn (const cWorld & a_World) override;
|
virtual void SendRespawn (const cWorld & a_World, bool a_ShouldIgnoreDimensionChecks = false) override;
|
||||||
virtual void SendExperience (void) override;
|
virtual void SendExperience (void) override;
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
||||||
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
||||||
|
@ -258,6 +258,9 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
|
|||||||
m_ServerID.resize(16, '0');
|
m_ServerID.resize(16, '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_ShouldLoadOfflinePlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false);
|
||||||
|
m_ShouldLoadNamedPlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadNamedPlayerData", true);
|
||||||
|
|
||||||
m_ClientViewDistance = a_SettingsIni.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE);
|
m_ClientViewDistance = a_SettingsIni.GetValueSetI("Server", "DefaultViewDistance", cClientHandle::DEFAULT_VIEW_DISTANCE);
|
||||||
if (m_ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE)
|
if (m_ClientViewDistance < cClientHandle::MIN_VIEW_DISTANCE)
|
||||||
{
|
{
|
||||||
|
20
src/Server.h
20
src/Server.h
@ -112,8 +112,18 @@ public: // tolua_export
|
|||||||
cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
cRsaPrivateKey & GetPrivateKey(void) { return m_PrivateKey; }
|
||||||
const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; }
|
const AString & GetPublicKeyDER(void) const { return m_PublicKeyDER; }
|
||||||
|
|
||||||
|
/** Returns true if authentication has been turned on in server settings. */
|
||||||
bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; }
|
bool ShouldAuthenticate(void) const { return m_ShouldAuthenticate; }
|
||||||
|
|
||||||
|
/** Returns true if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found.
|
||||||
|
Loaded from the settings.ini [PlayerData].LoadOfflinePlayerData setting. */
|
||||||
|
bool ShouldLoadOfflinePlayerData(void) const { return m_ShouldLoadOfflinePlayerData; }
|
||||||
|
|
||||||
|
/** Returns true if old-style playernames should be used to load data for players whose regular datafiles cannot be found.
|
||||||
|
This allows a seamless transition from name-based to UUID-based player storage.
|
||||||
|
Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
|
||||||
|
bool ShouldLoadNamedPlayerData(void) const { return m_ShouldLoadNamedPlayerData; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class cRoot; // so cRoot can create and destroy cServer
|
friend class cRoot; // so cRoot can create and destroy cServer
|
||||||
@ -204,6 +214,16 @@ private:
|
|||||||
This setting is the same as the "online-mode" setting in Vanilla. */
|
This setting is the same as the "online-mode" setting in Vanilla. */
|
||||||
bool m_ShouldAuthenticate;
|
bool m_ShouldAuthenticate;
|
||||||
|
|
||||||
|
/** True if offline UUIDs should be used to load data for players whose normal UUIDs cannot be found.
|
||||||
|
This allows transitions from an offline (no-auth) server to an online one.
|
||||||
|
Loaded from the settings.ini [PlayerData].LoadOfflinePlayerData setting. */
|
||||||
|
bool m_ShouldLoadOfflinePlayerData;
|
||||||
|
|
||||||
|
/** True if old-style playernames should be used to load data for players whose regular datafiles cannot be found.
|
||||||
|
This allows a seamless transition from name-based to UUID-based player storage.
|
||||||
|
Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
|
||||||
|
bool m_ShouldLoadNamedPlayerData;
|
||||||
|
|
||||||
|
|
||||||
cServer(void);
|
cServer(void);
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user