Merge branch 'master' into Inventory
This commit is contained in:
commit
1eedccc56a
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@ nbproject/
|
|||||||
ipch/
|
ipch/
|
||||||
Win32/
|
Win32/
|
||||||
MCServer/MCServer
|
MCServer/MCServer
|
||||||
|
MCServer/itemblacklist
|
||||||
ChunkWorxSave.ini
|
ChunkWorxSave.ini
|
||||||
doxy/
|
doxy/
|
||||||
Profiling
|
Profiling
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -25,3 +25,6 @@
|
|||||||
[submodule "lib/SQLiteCpp"]
|
[submodule "lib/SQLiteCpp"]
|
||||||
path = lib/SQLiteCpp
|
path = lib/SQLiteCpp
|
||||||
url = https://github.com/mc-server/SQLiteCpp.git
|
url = https://github.com/mc-server/SQLiteCpp.git
|
||||||
|
[submodule "lib/libevent"]
|
||||||
|
path = lib/libevent
|
||||||
|
url = https://github.com/mc-server/libevent.git
|
||||||
|
@ -13,6 +13,9 @@ before_install:
|
|||||||
install:
|
install:
|
||||||
# g++4.8 and clang
|
# g++4.8 and clang
|
||||||
- sudo apt-get install -qq g++-4.8
|
- sudo apt-get install -qq g++-4.8
|
||||||
|
|
||||||
|
# lua, needed for style checking and possibly later on for bindings generation
|
||||||
|
- sudo apt-get install -qq lua5.1
|
||||||
|
|
||||||
# g++4.8
|
# g++4.8
|
||||||
- if [ "$CXX" == "g++" ]; then export CXX="g++-4.8"; export CC="gcc-4.8"; fi
|
- if [ "$CXX" == "g++" ]; then export CXX="g++-4.8"; export CC="gcc-4.8"; fi
|
||||||
|
@ -7,6 +7,9 @@ export MCSERVER_BUILD_ID=$TRAVIS_JOB_NUMBER
|
|||||||
export MCSERVER_BUILD_DATETIME=`date`
|
export MCSERVER_BUILD_DATETIME=`date`
|
||||||
|
|
||||||
cmake . -DBUILD_TOOLS=1 -DSELF_TEST=1;
|
cmake . -DBUILD_TOOLS=1 -DSELF_TEST=1;
|
||||||
|
cd src
|
||||||
|
lua CheckBasicStyle.lua
|
||||||
|
cd ..
|
||||||
make -j 2;
|
make -j 2;
|
||||||
make -j 2 test;
|
make -j 2 test;
|
||||||
cd MCServer/;
|
cd MCServer/;
|
||||||
|
@ -95,6 +95,24 @@ set(SQLITECPP_BUILD_EXAMPLES OFF CACHE BOOL "Build examples."
|
|||||||
set(SQLITECPP_BUILD_TESTS OFF CACHE BOOL "Build and run tests." FORCE)
|
set(SQLITECPP_BUILD_TESTS OFF CACHE BOOL "Build and run tests." FORCE)
|
||||||
set(SQLITECPP_INTERNAL_SQLITE OFF CACHE BOOL "Add the internal SQLite3 source to the project." FORCE)
|
set(SQLITECPP_INTERNAL_SQLITE OFF CACHE BOOL "Add the internal SQLite3 source to the project." FORCE)
|
||||||
|
|
||||||
|
# Set options for LibEvent, disable all their tests and benchmarks:
|
||||||
|
set(EVENT__DISABLE_OPENSSL YES CACHE BOOL "Disable OpenSSL in LibEvent" FORCE)
|
||||||
|
set(EVENT__DISABLE_BENCHMARK YES CACHE BOOL "Disable LibEvent benchmarks" FORCE)
|
||||||
|
set(EVENT__DISABLE_TESTS YES CACHE BOOL "Disable LibEvent tests" FORCE)
|
||||||
|
set(EVENT__DISABLE_REGRESS YES CACHE BOOL "Disable LibEvent regression tests" FORCE)
|
||||||
|
set(EVENT__DISABLE_SAMPLES YES CACHE BOOL "Disable LibEvent samples" FORCE)
|
||||||
|
|
||||||
|
# Check that the libraries are present:
|
||||||
|
if (NOT EXISTS ${CMAKE_SOURCE_DIR}/lib/SQLiteCpp/CMakeLists.txt)
|
||||||
|
message(FATAL_ERROR "SQLiteCpp is missing in folder lib/SQLiteCpp. Have you initialized the submodules / downloaded the extra libraries?")
|
||||||
|
endif()
|
||||||
|
if (NOT EXISTS ${CMAKE_SOURCE_DIR}/lib/polarssl/CMakeLists.txt)
|
||||||
|
message(FATAL_ERROR "PolarSSL is missing in folder lib/polarssl. Have you initialized the submodules / downloaded the extra libraries?")
|
||||||
|
endif()
|
||||||
|
if (NOT EXISTS ${CMAKE_SOURCE_DIR}/lib/libevent/CMakeLists.txt)
|
||||||
|
message(FATAL_ERROR "LibEvent is missing in folder lib/libevent. Have you initialized and updated the submodules / downloaded the extra libraries?")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Include all the libraries:
|
# Include all the libraries:
|
||||||
add_subdirectory(lib/jsoncpp/)
|
add_subdirectory(lib/jsoncpp/)
|
||||||
add_subdirectory(lib/zlib/)
|
add_subdirectory(lib/zlib/)
|
||||||
@ -104,6 +122,7 @@ add_subdirectory(lib/sqlite/)
|
|||||||
add_subdirectory(lib/SQLiteCpp/)
|
add_subdirectory(lib/SQLiteCpp/)
|
||||||
add_subdirectory(lib/expat/)
|
add_subdirectory(lib/expat/)
|
||||||
add_subdirectory(lib/luaexpat/)
|
add_subdirectory(lib/luaexpat/)
|
||||||
|
add_subdirectory(lib/libevent/)
|
||||||
|
|
||||||
# Add proper include directories so that SQLiteCpp can find SQLite3:
|
# Add proper include directories so that SQLiteCpp can find SQLite3:
|
||||||
get_property(SQLITECPP_INCLUDES DIRECTORY "lib/SQLiteCpp/" PROPERTY INCLUDE_DIRECTORIES)
|
get_property(SQLITECPP_INCLUDES DIRECTORY "lib/SQLiteCpp/" PROPERTY INCLUDE_DIRECTORIES)
|
||||||
@ -111,6 +130,9 @@ set(SQLITECPP_INCLUDES "${SQLITECPP_INCLUDES}" "${CMAKE_CURRENT_SOURCE_DIR}/lib/
|
|||||||
set_property(DIRECTORY lib/SQLiteCpp/ PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")
|
set_property(DIRECTORY lib/SQLiteCpp/ PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")
|
||||||
set_property(TARGET SQLiteCpp PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")
|
set_property(TARGET SQLiteCpp PROPERTY INCLUDE_DIRECTORIES "${SQLITECPP_INCLUDES}")
|
||||||
|
|
||||||
|
# Add proper includes for LibEvent's event-config.h header:
|
||||||
|
include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS})
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_subdirectory(lib/luaproxy/)
|
add_subdirectory(lib/luaproxy/)
|
||||||
endif()
|
endif()
|
||||||
@ -118,13 +140,14 @@ 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
|
||||||
# (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those)
|
# (PolarSSL also has test and example programs in their CMakeLists.txt, we don't want those)
|
||||||
include(lib/polarssl.cmake)
|
include(lib/polarssl.cmake EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
set_exe_flags()
|
set_exe_flags()
|
||||||
|
|
||||||
add_subdirectory (src)
|
add_subdirectory (src)
|
||||||
|
|
||||||
if(${SELF_TEST})
|
if(${SELF_TEST})
|
||||||
|
message("Tests enabled")
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_subdirectory (tests)
|
add_subdirectory (tests)
|
||||||
endif()
|
endif()
|
||||||
|
@ -69,9 +69,9 @@ After doing so, run the command `xcodebuild lib/polarssl/POLARSSL.xcodeproj` in
|
|||||||
|
|
||||||
## Linux, FreeBSD etc. ##
|
## Linux, FreeBSD etc. ##
|
||||||
|
|
||||||
Install git, cmake and gcc or clang, using your platform's package manager:
|
Install git, make, cmake and gcc or clang, using your platform's package manager:
|
||||||
```
|
```
|
||||||
sudo apt-get install git cmake gcc g++
|
sudo apt-get install git make cmake gcc g++
|
||||||
```
|
```
|
||||||
|
|
||||||
### Getting the sources ###
|
### Getting the sources ###
|
||||||
|
@ -1840,7 +1840,9 @@ a_Player:OpenWindow(Window);
|
|||||||
MoveToWorld = { Params = "WorldName", Return = "bool", Return = "Moves the player to the specified world. Returns true if successful." },
|
MoveToWorld = { Params = "WorldName", Return = "bool", Return = "Moves the player to the specified world. Returns true if successful." },
|
||||||
OpenWindow = { Params = "{{cWindow|Window}}", Return = "", Notes = "Opens the specified UI window for the player." },
|
OpenWindow = { Params = "{{cWindow|Window}}", Return = "", Notes = "Opens the specified UI window for the player." },
|
||||||
PermissionMatches = { Params = "Permission, Template", Return = "bool", Notes = "(STATIC) Returns true if the specified permission matches the specified template. The template may contain wildcards." },
|
PermissionMatches = { Params = "Permission, Template", Return = "bool", Notes = "(STATIC) Returns true if the specified permission matches the specified template. The template may contain wildcards." },
|
||||||
|
PlaceBlock = { Params = "BlockX, BlockY, BlockZ, BlockType, BlockMeta", Return = "bool", Notes = "Places a block while impersonating the player. The {{OnPlayerPlacingBlock|HOOK_PLAYER_PLACING_BLOCK}} hook is called before the placement, and if it succeeds, the block is placed and the {{OnPlayerPlacedBlock|HOOK_PLAYER_PLACED_BLOCK}} hook is called. Returns true iff the block is successfully placed. Assumes that the block is in a currently loaded chunk." },
|
||||||
Respawn = { Params = "", Return = "", Notes = "Restores the health, extinguishes fire, makes visible and sends the Respawn packet." },
|
Respawn = { Params = "", Return = "", Notes = "Restores the health, extinguishes fire, makes visible and sends the Respawn packet." },
|
||||||
|
SendBlocksAround = { Params = "BlockX, BlockY, BlockZ, [Range]", Return = "", Notes = "Sends all the world's blocks in Range from the specified coords to the player, as a BlockChange packet. Range defaults to 1 (only one block sent)." },
|
||||||
SendMessage = { Params = "Message", Return = "", Notes = "Sends the specified message to the player." },
|
SendMessage = { Params = "Message", Return = "", Notes = "Sends the specified message to the player." },
|
||||||
SendMessageFailure = { Params = "Message", Return = "", Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For a command that failed to run because of insufficient permissions, etc." },
|
SendMessageFailure = { Params = "Message", Return = "", Notes = "Prepends Rose [INFO] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For a command that failed to run because of insufficient permissions, etc." },
|
||||||
SendMessageFatal = { Params = "Message", Return = "", Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For something serious, such as a plugin crash, etc." },
|
SendMessageFatal = { Params = "Message", Return = "", Notes = "Prepends Red [FATAL] / colours entire text (depending on ShouldUseChatPrefixes()) and sends message to player. For something serious, such as a plugin crash, etc." },
|
||||||
|
@ -12,7 +12,11 @@ return
|
|||||||
Use the {{cPlayer}}:GetWorld() function to get the world to which the block belongs.</p>
|
Use the {{cPlayer}}:GetWorld() function to get the world to which the block belongs.</p>
|
||||||
<p>
|
<p>
|
||||||
See also the {{OnPlayerPlacingBlock|HOOK_PLAYER_PLACING_BLOCK}} hook for a similar hook called
|
See also the {{OnPlayerPlacingBlock|HOOK_PLAYER_PLACING_BLOCK}} hook for a similar hook called
|
||||||
before the placement.
|
before the placement.</p>
|
||||||
|
<p>
|
||||||
|
If the client action results in multiple blocks being placed (such as a bed or a door), each separate
|
||||||
|
block is reported through this hook. All the blocks are already present in the world before the first
|
||||||
|
instance of this hook is called.
|
||||||
]],
|
]],
|
||||||
Params =
|
Params =
|
||||||
{
|
{
|
||||||
@ -20,10 +24,6 @@ return
|
|||||||
{ Name = "BlockX", Type = "number", Notes = "X-coord of the block" },
|
{ Name = "BlockX", Type = "number", Notes = "X-coord of the block" },
|
||||||
{ Name = "BlockY", Type = "number", Notes = "Y-coord of the block" },
|
{ Name = "BlockY", Type = "number", Notes = "Y-coord of the block" },
|
||||||
{ Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" },
|
{ Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" },
|
||||||
{ Name = "BlockFace", Type = "number", Notes = "Face of the existing block upon which the player interacted. One of the BLOCK_FACE_ constants" },
|
|
||||||
{ Name = "CursorX", Type = "number", Notes = "X-coord of the cursor within the block face (0 .. 15)" },
|
|
||||||
{ Name = "CursorY", Type = "number", Notes = "Y-coord of the cursor within the block face (0 .. 15)" },
|
|
||||||
{ Name = "CursorZ", Type = "number", Notes = "Z-coord of the cursor within the block face (0 .. 15)" },
|
|
||||||
{ Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block" },
|
{ Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block" },
|
||||||
{ Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block" },
|
{ Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block" },
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,11 @@ return
|
|||||||
Use the {{cPlayer}}:GetWorld() function to get the world to which the block belongs.</p>
|
Use the {{cPlayer}}:GetWorld() function to get the world to which the block belongs.</p>
|
||||||
<p>
|
<p>
|
||||||
See also the {{OnPlayerPlacedBlock|HOOK_PLAYER_PLACED_BLOCK}} hook for a similar hook called after
|
See also the {{OnPlayerPlacedBlock|HOOK_PLAYER_PLACED_BLOCK}} hook for a similar hook called after
|
||||||
the placement.
|
the placement.</p>
|
||||||
|
<p>
|
||||||
|
If the client action results in multiple blocks being placed (such as a bed or a door), each separate
|
||||||
|
block is reported through this hook and only if all of them succeed, all the blocks are placed. If
|
||||||
|
any one of the calls are refused by the plugin, all the blocks are refused and reverted on the client.
|
||||||
]],
|
]],
|
||||||
Params =
|
Params =
|
||||||
{
|
{
|
||||||
@ -23,10 +27,6 @@ return
|
|||||||
{ Name = "BlockX", Type = "number", Notes = "X-coord of the block" },
|
{ Name = "BlockX", Type = "number", Notes = "X-coord of the block" },
|
||||||
{ Name = "BlockY", Type = "number", Notes = "Y-coord of the block" },
|
{ Name = "BlockY", Type = "number", Notes = "Y-coord of the block" },
|
||||||
{ Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" },
|
{ Name = "BlockZ", Type = "number", Notes = "Z-coord of the block" },
|
||||||
{ Name = "BlockFace", Type = "number", Notes = "Face of the existing block upon which the player is interacting. One of the BLOCK_FACE_ constants" },
|
|
||||||
{ Name = "CursorX", Type = "number", Notes = "X-coord of the cursor within the block face (0 .. 15)" },
|
|
||||||
{ Name = "CursorY", Type = "number", Notes = "Y-coord of the cursor within the block face (0 .. 15)" },
|
|
||||||
{ Name = "CursorZ", Type = "number", Notes = "Z-coord of the cursor within the block face (0 .. 15)" },
|
|
||||||
{ Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block" },
|
{ Name = "BlockType", Type = "BLOCKTYPE", Notes = "The block type of the block" },
|
||||||
{ Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block" },
|
{ Name = "BlockMeta", Type = "NIBBLETYPE", Notes = "The block meta of the block" },
|
||||||
},
|
},
|
||||||
|
@ -7,7 +7,10 @@ return
|
|||||||
Desc = [[
|
Desc = [[
|
||||||
A plugin may implement an OnServerPing() function and register it as a Hook to process pings from
|
A plugin may implement an OnServerPing() function and register it as a Hook to process pings from
|
||||||
clients in the server server list. It can change the logged in players and player capacity, as well
|
clients in the server server list. It can change the logged in players and player capacity, as well
|
||||||
as the server description and the favicon, that are displayed to the client in the server list.
|
as the server description and the favicon, that are displayed to the client in the server list.</p>
|
||||||
|
<p>
|
||||||
|
The client handle already has its protocol version assigned to it, so the plugin can check that; however,
|
||||||
|
there's no username associated with the client yet, and no player object.
|
||||||
]],
|
]],
|
||||||
Params = {
|
Params = {
|
||||||
{ Name = "ClientHandle", Type = "{{cClientHandle}}", Notes = "The client handle that pinged the server" },
|
{ Name = "ClientHandle", Type = "{{cClientHandle}}", Notes = "The client handle that pinged the server" },
|
||||||
|
@ -1,56 +1,14 @@
|
|||||||
[Spider]
|
[Bat]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
AttackDamage=2.0
|
AttackDamage=0.0
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=16
|
MaxHealth=6
|
||||||
|
|
||||||
[Chicken]
|
[Blaze]
|
||||||
AttackRange=2.0
|
AttackRange=15.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
AttackDamage=1.0
|
AttackDamage=6.0
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=4
|
|
||||||
|
|
||||||
[Cow]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=1.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=10
|
|
||||||
|
|
||||||
[Pig]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=1.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=10
|
|
||||||
|
|
||||||
[Sheep]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=1.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=8
|
|
||||||
|
|
||||||
[Squid]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=1.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=10
|
|
||||||
|
|
||||||
[Enderman]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=4.0
|
|
||||||
SightDistance=64.0
|
|
||||||
MaxHealth=40
|
|
||||||
|
|
||||||
[ZombiePigman]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=7.0
|
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=20
|
MaxHealth=20
|
||||||
IsFireproof=1
|
IsFireproof=1
|
||||||
@ -62,6 +20,20 @@ AttackDamage=2.0
|
|||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=12
|
MaxHealth=12
|
||||||
|
|
||||||
|
[Chicken]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=0.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=4
|
||||||
|
|
||||||
|
[Cow]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=0.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=10
|
||||||
|
|
||||||
[Creeper]
|
[Creeper]
|
||||||
AttackRange=3.0
|
AttackRange=3.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
@ -69,6 +41,21 @@ AttackDamage=0.0
|
|||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=20
|
MaxHealth=20
|
||||||
|
|
||||||
|
[EnderDragon]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=6.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=200
|
||||||
|
|
||||||
|
[Enderman]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=4.0
|
||||||
|
SightDistance=64.0
|
||||||
|
MaxHealth=40
|
||||||
|
|
||||||
|
|
||||||
[Ghast]
|
[Ghast]
|
||||||
AttackRange=50.0
|
AttackRange=50.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
@ -77,6 +64,77 @@ SightDistance=50.0
|
|||||||
MaxHealth=10
|
MaxHealth=10
|
||||||
IsFireproof=1
|
IsFireproof=1
|
||||||
|
|
||||||
|
[Giant]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=6.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=100
|
||||||
|
|
||||||
|
[Guardian]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=9.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=30
|
||||||
|
|
||||||
|
[Horse]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=6.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=30
|
||||||
|
|
||||||
|
[IronGolem]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=6.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=100
|
||||||
|
|
||||||
|
[MagmaCube]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=6.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=16
|
||||||
|
IsFireproof=1
|
||||||
|
|
||||||
|
[Mooshroom]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=0.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=10
|
||||||
|
|
||||||
|
[Ocelot]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=0.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=10
|
||||||
|
|
||||||
|
[Pig]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=0.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=10
|
||||||
|
|
||||||
|
[Rabbit]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=0.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=10
|
||||||
|
|
||||||
|
[Sheep]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=0.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=8
|
||||||
|
|
||||||
[Silverfish]
|
[Silverfish]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
@ -97,27 +155,26 @@ AttackDamage=4.0
|
|||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=16
|
MaxHealth=16
|
||||||
|
|
||||||
[Zombie]
|
[SnowGolem]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
AttackDamage=4.0
|
AttackDamage=0.0
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=20
|
MaxHealth=4
|
||||||
|
|
||||||
[Wolf]
|
[Spider]
|
||||||
|
AttackRange=2.0
|
||||||
|
AttackRate=1
|
||||||
|
AttackDamage=2.0
|
||||||
|
SightDistance=25.0
|
||||||
|
MaxHealth=16
|
||||||
|
|
||||||
|
[Squid]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
AttackDamage=4.0
|
AttackDamage=0.0
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=20
|
MaxHealth=10
|
||||||
|
|
||||||
[Blaze]
|
|
||||||
AttackRange=15.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=6.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=20
|
|
||||||
IsFireproof=1
|
|
||||||
|
|
||||||
[Villager]
|
[Villager]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
@ -125,7 +182,6 @@ AttackRate=1
|
|||||||
AttackDamage=0.0
|
AttackDamage=0.0
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=20
|
MaxHealth=20
|
||||||
IsFireproof=0
|
|
||||||
|
|
||||||
[Witch]
|
[Witch]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
@ -134,61 +190,24 @@ AttackDamage=0.0
|
|||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=26
|
MaxHealth=26
|
||||||
|
|
||||||
|
[Wolf]
|
||||||
[Ocelot]
|
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
AttackDamage=0.0
|
AttackDamage=4.0
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=10
|
MaxHealth=20
|
||||||
|
|
||||||
[Mooshroom]
|
[Zombie]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
AttackDamage=0.0
|
AttackDamage=4.0
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=10
|
MaxHealth=20
|
||||||
|
|
||||||
[MagmaCube]
|
[ZombiePigman]
|
||||||
AttackRange=2.0
|
AttackRange=2.0
|
||||||
AttackRate=1
|
AttackRate=1
|
||||||
AttackDamage=6.0
|
AttackDamage=7.0
|
||||||
SightDistance=25.0
|
SightDistance=25.0
|
||||||
MaxHealth=16
|
MaxHealth=20
|
||||||
IsFireproof=1
|
IsFireproof=1
|
||||||
|
|
||||||
[Horse]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=6.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=30
|
|
||||||
|
|
||||||
[EnderDragon]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=6.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=200
|
|
||||||
|
|
||||||
[Giant]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=6.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=100
|
|
||||||
|
|
||||||
[IronGolem]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=6.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=100
|
|
||||||
|
|
||||||
[Bat]
|
|
||||||
AttackRange=2.0
|
|
||||||
AttackRate=1
|
|
||||||
AttackDamage=0.0
|
|
||||||
SightDistance=25.0
|
|
||||||
MaxHealth=6
|
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ function ShowPage(WebAdmin, TemplateRequest)
|
|||||||
SiteContent = {}
|
SiteContent = {}
|
||||||
local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path)
|
local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path)
|
||||||
local Title = "MCServer WebAdmin"
|
local Title = "MCServer WebAdmin"
|
||||||
|
local NumPlayers = cRoot:Get():GetServer():GetNumPlayers()
|
||||||
local MemoryUsageKiB = cRoot:GetPhysicalRAMUsage()
|
local MemoryUsageKiB = cRoot:GetPhysicalRAMUsage()
|
||||||
local NumChunks = cRoot:Get():GetTotalChunkCount()
|
local NumChunks = cRoot:Get():GetTotalChunkCount()
|
||||||
local PluginPage = WebAdmin:GetPage(TemplateRequest.Request)
|
local PluginPage = WebAdmin:GetPage(TemplateRequest.Request)
|
||||||
@ -102,6 +103,7 @@ function ShowPage(WebAdmin, TemplateRequest)
|
|||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<ul class="menu top_links">
|
<ul class="menu top_links">
|
||||||
<li><a>Server Name: <strong>]] .. cRoot:Get():GetServer():GetServerID() .. [[</strong></a></li>
|
<li><a>Server Name: <strong>]] .. cRoot:Get():GetServer():GetServerID() .. [[</strong></a></li>
|
||||||
|
<li><a>Players online: <strong>]] .. NumPlayers .. [[</strong></a></li>
|
||||||
<li><a>Memory: <strong>]] .. MemoryUsageKiB / 1024 .. [[MB</strong></a></li>
|
<li><a>Memory: <strong>]] .. MemoryUsageKiB / 1024 .. [[MB</strong></a></li>
|
||||||
<li><a>Chunks: <strong>]] .. NumChunks .. [[</strong></a></li>
|
<li><a>Chunks: <strong>]] .. NumChunks .. [[</strong></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -9,8 +9,7 @@ We currently support Release 1.7 and 1.8 (not beta) Minecraft protocol versions.
|
|||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
Hosted MCServer is available DIY on DigitalOcean: [![Install on DigitalOcean](http://doinstall.bearbin.net/button.svg)](http://doinstall.bearbin.net/install?url=https://github.com/mc-server/MCServer) and [Gamososm](https://gamocosm.com) also offers MCServer support.
|
||||||
[![Install on DigitalOcean](http://doinstall.bearbin.net/button.svg)](http://doinstall.bearbin.net/install?url=https://github.com/mc-server/MCServer)
|
|
||||||
|
|
||||||
For Linux there is an easy installation method, just run this in your terminal:
|
For Linux there is an easy installation method, just run this in your terminal:
|
||||||
|
|
||||||
|
@ -26,11 +26,13 @@ struct
|
|||||||
{entEnderman, "Enderman"},
|
{entEnderman, "Enderman"},
|
||||||
{entGhast, "Ghast"},
|
{entGhast, "Ghast"},
|
||||||
{entGiant, "Giant"},
|
{entGiant, "Giant"},
|
||||||
|
{entGuardian, "Guardian"},
|
||||||
{entLavaSlime, "LavaSlime"},
|
{entLavaSlime, "LavaSlime"},
|
||||||
{entMushroomCow, "MushroomCow"},
|
{entMushroomCow, "MushroomCow"},
|
||||||
{entOzelot, "Ozelot"},
|
{entOzelot, "Ozelot"},
|
||||||
{entPig, "Pig"},
|
{entPig, "Pig"},
|
||||||
{entPigZombie, "PigZombie"},
|
{entPigZombie, "PigZombie"},
|
||||||
|
{entRabbit, "Rabbit"},
|
||||||
{entSheep, "Sheep"},
|
{entSheep, "Sheep"},
|
||||||
{entSilverfish, "Slverfish"},
|
{entSilverfish, "Slverfish"},
|
||||||
{entSkeleton, "Skeleton"},
|
{entSkeleton, "Skeleton"},
|
||||||
|
@ -25,11 +25,13 @@ enum eEntityType
|
|||||||
entEnderman,
|
entEnderman,
|
||||||
entGhast,
|
entGhast,
|
||||||
entGiant,
|
entGiant,
|
||||||
|
entGuardian,
|
||||||
entLavaSlime,
|
entLavaSlime,
|
||||||
entMushroomCow,
|
entMushroomCow,
|
||||||
entOzelot,
|
entOzelot,
|
||||||
entPig,
|
entPig,
|
||||||
entPigZombie,
|
entPigZombie,
|
||||||
|
entRabbit,
|
||||||
entSheep,
|
entSheep,
|
||||||
entSilverfish,
|
entSilverfish,
|
||||||
entSkeleton,
|
entSkeleton,
|
||||||
|
@ -53,6 +53,7 @@ source_group("Shared" FILES ${SHARED_SRC} ${SHARED_HDR})
|
|||||||
|
|
||||||
set(SHARED_OSS_SRC
|
set(SHARED_OSS_SRC
|
||||||
../../src/OSSupport/CriticalSection.cpp
|
../../src/OSSupport/CriticalSection.cpp
|
||||||
|
../../src/OSSupport/Event.cpp
|
||||||
../../src/OSSupport/File.cpp
|
../../src/OSSupport/File.cpp
|
||||||
../../src/OSSupport/IsThread.cpp
|
../../src/OSSupport/IsThread.cpp
|
||||||
../../src/OSSupport/StackTrace.cpp
|
../../src/OSSupport/StackTrace.cpp
|
||||||
@ -60,6 +61,7 @@ set(SHARED_OSS_SRC
|
|||||||
|
|
||||||
set(SHARED_OSS_HDR
|
set(SHARED_OSS_HDR
|
||||||
../../src/OSSupport/CriticalSection.h
|
../../src/OSSupport/CriticalSection.h
|
||||||
|
../../src/OSSupport/Event.h
|
||||||
../../src/OSSupport/File.h
|
../../src/OSSupport/File.h
|
||||||
../../src/OSSupport/IsThread.h
|
../../src/OSSupport/IsThread.h
|
||||||
../../src/OSSupport/StackTrace.h
|
../../src/OSSupport/StackTrace.h
|
||||||
|
@ -201,6 +201,7 @@ typedef unsigned char Byte;
|
|||||||
// Common headers (without macros):
|
// Common headers (without macros):
|
||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
#include "OSSupport/CriticalSection.h"
|
#include "OSSupport/CriticalSection.h"
|
||||||
|
#include "OSSupport/Event.h"
|
||||||
#include "OSSupport/IsThread.h"
|
#include "OSSupport/IsThread.h"
|
||||||
#include "OSSupport/File.h"
|
#include "OSSupport/File.h"
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ bool cMCADefrag::cThread::ReadChunk(cFile & a_File, const Byte * a_LocationRaw)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_CompressedChunkDataSize = (Buf[0] << 24) | (Buf[1] << 16) | (Buf[2] << 8) | Buf[3];
|
m_CompressedChunkDataSize = (Buf[0] << 24) | (Buf[1] << 16) | (Buf[2] << 8) | Buf[3];
|
||||||
if (m_CompressedChunkDataSize > SizeInSectors)
|
if ((m_CompressedChunkDataSize > SizeInSectors) || (m_CompressedChunkDataSize < 0))
|
||||||
{
|
{
|
||||||
LOGWARNING("Invalid chunk data - SizeInSectors (%d) smaller that RealSize (%d)", SizeInSectors, m_CompressedChunkDataSize);
|
LOGWARNING("Invalid chunk data - SizeInSectors (%d) smaller that RealSize (%d)", SizeInSectors, m_CompressedChunkDataSize);
|
||||||
return false;
|
return false;
|
||||||
|
@ -55,12 +55,14 @@ set(SHARED_HDR
|
|||||||
)
|
)
|
||||||
set(SHARED_OSS_SRC
|
set(SHARED_OSS_SRC
|
||||||
../../src/OSSupport/CriticalSection.cpp
|
../../src/OSSupport/CriticalSection.cpp
|
||||||
|
../../src/OSSupport/Event.cpp
|
||||||
../../src/OSSupport/File.cpp
|
../../src/OSSupport/File.cpp
|
||||||
../../src/OSSupport/IsThread.cpp
|
../../src/OSSupport/IsThread.cpp
|
||||||
../../src/OSSupport/StackTrace.cpp
|
../../src/OSSupport/StackTrace.cpp
|
||||||
)
|
)
|
||||||
set(SHARED_OSS_HDR
|
set(SHARED_OSS_HDR
|
||||||
../../src/OSSupport/CriticalSection.h
|
../../src/OSSupport/CriticalSection.h
|
||||||
|
../../src/OSSupport/Event.h
|
||||||
../../src/OSSupport/File.h
|
../../src/OSSupport/File.h
|
||||||
../../src/OSSupport/IsThread.h
|
../../src/OSSupport/IsThread.h
|
||||||
../../src/OSSupport/StackTrace.h
|
../../src/OSSupport/StackTrace.h
|
||||||
|
@ -100,13 +100,11 @@
|
|||||||
CLIENTENCRYPTSEND(ToClient.data(), ToClient.size()); \
|
CLIENTENCRYPTSEND(ToClient.data(), ToClient.size()); \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
/* case csWaitingForEncryption: \
|
case csWaitingForEncryption: \
|
||||||
{ \
|
{ \
|
||||||
Log("Waiting for client encryption, queued %u bytes", ToClient.size()); \
|
|
||||||
m_ClientEncryptionBuffer.append(ToClient.data(), ToClient.size()); \
|
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
*/ \
|
\
|
||||||
} \
|
} \
|
||||||
DebugSleep(50); \
|
DebugSleep(50); \
|
||||||
}
|
}
|
||||||
@ -141,8 +139,14 @@ typedef unsigned char Byte;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// fwd declarations, to avoid clang warnings:
|
||||||
|
AString PrintableAbsIntTriplet(int a_X, int a_Y, int a_Z, double a_Divisor = 32);
|
||||||
|
|
||||||
AString PrintableAbsIntTriplet(int a_X, int a_Y, int a_Z, double a_Divisor = 32)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString PrintableAbsIntTriplet(int a_X, int a_Y, int a_Z, double a_Divisor)
|
||||||
{
|
{
|
||||||
return Printf("<%d, %d, %d> ~ {%.02f, %.02f, %.02f}",
|
return Printf("<%d, %d, %d> ~ {%.02f, %.02f, %.02f}",
|
||||||
a_X, a_Y, a_Z,
|
a_X, a_Y, a_Z,
|
||||||
@ -298,7 +302,7 @@ void cConnection::Log(const char * a_Format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cConnection::DataLog(const void * a_Data, int a_Size, const char * a_Format, ...)
|
void cConnection::DataLog(const void * a_Data, size_t a_Size, const char * a_Format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, a_Format);
|
va_start(args, a_Format);
|
||||||
@ -359,14 +363,14 @@ bool cConnection::ConnectToServer(void)
|
|||||||
bool cConnection::RelayFromServer(void)
|
bool cConnection::RelayFromServer(void)
|
||||||
{
|
{
|
||||||
char Buffer[64 KiB];
|
char Buffer[64 KiB];
|
||||||
int res = recv(m_ServerSocket, Buffer, sizeof(Buffer), 0);
|
int res = static_cast<int>(recv(m_ServerSocket, Buffer, sizeof(Buffer), 0)); // recv returns int on windows, ssize_t on linux
|
||||||
if (res <= 0)
|
if (res <= 0)
|
||||||
{
|
{
|
||||||
Log("Server closed the socket: %d; %d; aborting connection", res, SocketError);
|
Log("Server closed the socket: %d; %d; aborting connection", res, SocketError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataLog(Buffer, res, "Received %d bytes from the SERVER", res);
|
DataLog(Buffer, static_cast<size_t>(res), "Received %d bytes from the SERVER", res);
|
||||||
|
|
||||||
switch (m_ServerState)
|
switch (m_ServerState)
|
||||||
{
|
{
|
||||||
@ -377,15 +381,15 @@ bool cConnection::RelayFromServer(void)
|
|||||||
}
|
}
|
||||||
case csEncryptedUnderstood:
|
case csEncryptedUnderstood:
|
||||||
{
|
{
|
||||||
m_ServerDecryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
|
m_ServerDecryptor.ProcessData(reinterpret_cast<Byte *>(Buffer), reinterpret_cast<Byte *>(Buffer), static_cast<size_t>(res));
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
DataLog(Buffer, static_cast<size_t>(res), "Decrypted %d bytes from the SERVER", res);
|
||||||
return DecodeServersPackets(Buffer, res);
|
return DecodeServersPackets(Buffer, res);
|
||||||
}
|
}
|
||||||
case csEncryptedUnknown:
|
case csEncryptedUnknown:
|
||||||
{
|
{
|
||||||
m_ServerDecryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
|
m_ServerDecryptor.ProcessData(reinterpret_cast<Byte *>(Buffer), reinterpret_cast<Byte *>(Buffer), static_cast<size_t>(res));
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the SERVER", res);
|
DataLog(Buffer, static_cast<size_t>(res), "Decrypted %d bytes from the SERVER", res);
|
||||||
return CLIENTSEND(Buffer, res);
|
return CLIENTSEND(Buffer, static_cast<size_t>(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT(!"Unhandled server state while relaying from server");
|
ASSERT(!"Unhandled server state while relaying from server");
|
||||||
@ -399,14 +403,14 @@ bool cConnection::RelayFromServer(void)
|
|||||||
bool cConnection::RelayFromClient(void)
|
bool cConnection::RelayFromClient(void)
|
||||||
{
|
{
|
||||||
char Buffer[64 KiB];
|
char Buffer[64 KiB];
|
||||||
int res = recv(m_ClientSocket, Buffer, sizeof(Buffer), 0);
|
int res = static_cast<int>(recv(m_ClientSocket, Buffer, sizeof(Buffer), 0)); // recv returns int on Windows, ssize_t on Linux
|
||||||
if (res <= 0)
|
if (res <= 0)
|
||||||
{
|
{
|
||||||
Log("Client closed the socket: %d; %d; aborting connection", res, SocketError);
|
Log("Client closed the socket: %d; %d; aborting connection", res, SocketError);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataLog(Buffer, res, "Received %d bytes from the CLIENT", res);
|
DataLog(Buffer, static_cast<size_t>(res), "Received %d bytes from the CLIENT", res);
|
||||||
|
|
||||||
switch (m_ClientState)
|
switch (m_ClientState)
|
||||||
{
|
{
|
||||||
@ -421,9 +425,9 @@ bool cConnection::RelayFromClient(void)
|
|||||||
}
|
}
|
||||||
case csEncryptedUnknown:
|
case csEncryptedUnknown:
|
||||||
{
|
{
|
||||||
DataLog(Buffer, res, "Decrypted %d bytes from the CLIENT", res);
|
DataLog(Buffer, static_cast<size_t>(res), "Decrypted %d bytes from the CLIENT", res);
|
||||||
m_ServerEncryptor.ProcessData((Byte *)Buffer, (Byte *)Buffer, res);
|
m_ServerEncryptor.ProcessData(reinterpret_cast<Byte *>(Buffer), reinterpret_cast<Byte *>(Buffer), static_cast<size_t>(res));
|
||||||
return SERVERSEND(Buffer, res);
|
return SERVERSEND(Buffer, static_cast<size_t>(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT(!"Unhandled server state while relaying from client");
|
ASSERT(!"Unhandled server state while relaying from client");
|
||||||
@ -446,9 +450,9 @@ double cConnection::GetRelativeTime(void)
|
|||||||
|
|
||||||
bool cConnection::SendData(SOCKET a_Socket, const char * a_Data, size_t a_Size, const char * a_Peer)
|
bool cConnection::SendData(SOCKET a_Socket, const char * a_Data, size_t a_Size, const char * a_Peer)
|
||||||
{
|
{
|
||||||
DataLog(a_Data, a_Size, "Sending data to %s, %u bytes", a_Peer, (unsigned)a_Size);
|
DataLog(a_Data, a_Size, "Sending data to %s, %u bytes", a_Peer, static_cast<unsigned>(a_Size));
|
||||||
|
|
||||||
int res = send(a_Socket, a_Data, (int)a_Size, 0);
|
int res = static_cast<int>(send(a_Socket, a_Data, a_Size, 0)); // Windows uses int for a_Size, Linux uses size_t; but Windows doesn't complain. Return type is int on Windows and ssize_t on Linux
|
||||||
if (res <= 0)
|
if (res <= 0)
|
||||||
{
|
{
|
||||||
Log("%s closed the socket: %d, %d; aborting connection", a_Peer, res, SocketError);
|
Log("%s closed the socket: %d, %d; aborting connection", a_Peer, res, SocketError);
|
||||||
@ -511,7 +515,7 @@ bool cConnection::SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Enc
|
|||||||
|
|
||||||
bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size)
|
bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size)
|
||||||
{
|
{
|
||||||
if (!m_ClientBuffer.Write(a_Data, a_Size))
|
if (!m_ClientBuffer.Write(a_Data, static_cast<size_t>(a_Size)))
|
||||||
{
|
{
|
||||||
Log("Too much queued data for the server, aborting connection");
|
Log("Too much queued data for the server, aborting connection");
|
||||||
return false;
|
return false;
|
||||||
@ -529,10 +533,12 @@ bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
UInt32 PacketType, PacketReadSoFar;
|
UInt32 PacketType, PacketReadSoFar;
|
||||||
PacketReadSoFar = m_ClientBuffer.GetReadableSpace();
|
PacketReadSoFar = static_cast<UInt32>(m_ClientBuffer.GetReadableSpace());
|
||||||
VERIFY(m_ClientBuffer.ReadVarInt(PacketType));
|
VERIFY(m_ClientBuffer.ReadVarInt(PacketType));
|
||||||
PacketReadSoFar -= m_ClientBuffer.GetReadableSpace();
|
PacketReadSoFar -= m_ClientBuffer.GetReadableSpace();
|
||||||
Log("Decoding client's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ClientBuffer.GetReadableSpace(), PacketType, PacketLen);
|
Log("Decoding client's packets, there are now %u bytes in the queue; next packet is 0x%02x, %u bytes long",
|
||||||
|
static_cast<unsigned>(m_ClientBuffer.GetReadableSpace()), PacketType, PacketLen
|
||||||
|
);
|
||||||
switch (m_ClientProtocolState)
|
switch (m_ClientProtocolState)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
@ -619,7 +625,7 @@ bool cConnection::DecodeClientsPackets(const char * a_Data, int a_Size)
|
|||||||
|
|
||||||
bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size)
|
bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size)
|
||||||
{
|
{
|
||||||
if (!m_ServerBuffer.Write(a_Data, a_Size))
|
if (!m_ServerBuffer.Write(a_Data, static_cast<size_t>(a_Size)))
|
||||||
{
|
{
|
||||||
Log("Too much queued data for the client, aborting connection");
|
Log("Too much queued data for the client, aborting connection");
|
||||||
return false;
|
return false;
|
||||||
@ -655,7 +661,7 @@ bool cConnection::DecodeServersPackets(const char * a_Data, int a_Size)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
UInt32 PacketType, PacketReadSoFar;
|
UInt32 PacketType, PacketReadSoFar;
|
||||||
PacketReadSoFar = m_ServerBuffer.GetReadableSpace();
|
PacketReadSoFar = static_cast<UInt32>(m_ServerBuffer.GetReadableSpace());
|
||||||
VERIFY(m_ServerBuffer.ReadVarInt(PacketType));
|
VERIFY(m_ServerBuffer.ReadVarInt(PacketType));
|
||||||
PacketReadSoFar -= m_ServerBuffer.GetReadableSpace();
|
PacketReadSoFar -= m_ServerBuffer.GetReadableSpace();
|
||||||
Log("Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ServerBuffer.GetReadableSpace(), PacketType, PacketLen);
|
Log("Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%0x, %u bytes long", m_ServerBuffer.GetReadableSpace(), PacketType, PacketLen);
|
||||||
@ -1111,7 +1117,7 @@ bool cConnection::HandleClientPlayerPositionLook(void)
|
|||||||
bool cConnection::HandleClientPluginMessage(void)
|
bool cConnection::HandleClientPluginMessage(void)
|
||||||
{
|
{
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, ChannelName);
|
HANDLE_CLIENT_PACKET_READ(ReadVarUTF8String, AString, ChannelName);
|
||||||
HANDLE_CLIENT_PACKET_READ(ReadBEShort, short, Length);
|
HANDLE_CLIENT_PACKET_READ(ReadBEUInt16, UInt16, Length);
|
||||||
AString Data;
|
AString Data;
|
||||||
if (!m_ClientBuffer.ReadString(Data, Length))
|
if (!m_ClientBuffer.ReadString(Data, Length))
|
||||||
{
|
{
|
||||||
@ -1119,7 +1125,7 @@ bool cConnection::HandleClientPluginMessage(void)
|
|||||||
}
|
}
|
||||||
Log("Received a PACKET_PLUGIN_MESSAGE from the client");
|
Log("Received a PACKET_PLUGIN_MESSAGE from the client");
|
||||||
Log(" ChannelName = \"%s\"", ChannelName.c_str());
|
Log(" ChannelName = \"%s\"", ChannelName.c_str());
|
||||||
DataLog(Data.data(), Length, " Data: %d bytes", Length);
|
DataLog(Data.data(), Length, " Data: %u bytes", Length);
|
||||||
COPY_TO_SERVER();
|
COPY_TO_SERVER();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1288,13 +1294,13 @@ bool cConnection::HandleServerLoginEncryptionKeyRequest(void)
|
|||||||
{
|
{
|
||||||
// Read the packet from the server:
|
// Read the packet from the server:
|
||||||
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ServerID);
|
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ServerID);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, PublicKeyLength);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, PublicKeyLength);
|
||||||
AString PublicKey;
|
AString PublicKey;
|
||||||
if (!m_ServerBuffer.ReadString(PublicKey, PublicKeyLength))
|
if (!m_ServerBuffer.ReadString(PublicKey, PublicKeyLength))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, NonceLength);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, NonceLength);
|
||||||
AString Nonce;
|
AString Nonce;
|
||||||
if (!m_ServerBuffer.ReadString(Nonce, NonceLength))
|
if (!m_ServerBuffer.ReadString(Nonce, NonceLength))
|
||||||
{
|
{
|
||||||
@ -1392,6 +1398,9 @@ bool cConnection::HandleServerBlockChange(void)
|
|||||||
HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, BlockType);
|
HANDLE_SERVER_PACKET_READ(ReadVarInt, UInt32, BlockType);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadChar, char, BlockMeta);
|
HANDLE_SERVER_PACKET_READ(ReadChar, char, BlockMeta);
|
||||||
Log("Received a PACKET_BLOCK_CHANGE from the server");
|
Log("Received a PACKET_BLOCK_CHANGE from the server");
|
||||||
|
Log(" Pos = {%d, %d, %d}", BlockX, BlockY, BlockZ);
|
||||||
|
Log(" BlockType = %d (0x%x", BlockType, BlockType);
|
||||||
|
Log(" BlockMeta = %d", BlockMeta);
|
||||||
COPY_TO_CLIENT();
|
COPY_TO_CLIENT();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1461,12 +1470,12 @@ bool cConnection::HandleServerCompass(void)
|
|||||||
bool cConnection::HandleServerDestroyEntities(void)
|
bool cConnection::HandleServerDestroyEntities(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadByte, Byte, NumEntities);
|
HANDLE_SERVER_PACKET_READ(ReadByte, Byte, NumEntities);
|
||||||
if (!m_ServerBuffer.SkipRead((int)NumEntities * 4))
|
if (!m_ServerBuffer.SkipRead(static_cast<size_t>(NumEntities) * 4))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Log("Received PACKET_DESTROY_ENTITIES from the server:");
|
Log("Received PACKET_DESTROY_ENTITIES from the server:");
|
||||||
Log(" NumEntities = %d", NumEntities);
|
Log(" NumEntities = %u", NumEntities);
|
||||||
COPY_TO_CLIENT();
|
COPY_TO_CLIENT();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1687,15 +1696,15 @@ bool cConnection::HandleServerEntityVelocity(void)
|
|||||||
|
|
||||||
bool cConnection::HandleServerExplosion(void)
|
bool cConnection::HandleServerExplosion(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosX);
|
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosX);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosY);
|
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosY);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosZ);
|
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, PosZ);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Force);
|
HANDLE_SERVER_PACKET_READ(ReadBEFloat, float, Force);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, NumRecords);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, NumRecords);
|
||||||
std::vector<sCoords> Records;
|
std::vector<sCoords> Records;
|
||||||
Records.reserve(NumRecords);
|
Records.reserve(NumRecords);
|
||||||
int PosXI = (int)PosX, PosYI = (int)PosY, PosZI = (int)PosZ;
|
int PosXI = (int)PosX, PosYI = (int)PosY, PosZI = (int)PosZ;
|
||||||
for (int i = 0; i < NumRecords; i++)
|
for (UInt32 i = 0; i < NumRecords; i++)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadChar, char, rx);
|
HANDLE_SERVER_PACKET_READ(ReadChar, char, rx);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadChar, char, ry);
|
HANDLE_SERVER_PACKET_READ(ReadChar, char, ry);
|
||||||
@ -1708,10 +1717,10 @@ bool cConnection::HandleServerExplosion(void)
|
|||||||
Log("Received a PACKET_EXPLOSION from the server:");
|
Log("Received a PACKET_EXPLOSION from the server:");
|
||||||
Log(" Pos = {%.02f, %.02f, %.02f}", PosX, PosY, PosZ);
|
Log(" Pos = {%.02f, %.02f, %.02f}", PosX, PosY, PosZ);
|
||||||
Log(" Force = %.02f", Force);
|
Log(" Force = %.02f", Force);
|
||||||
Log(" NumRecords = %d", NumRecords);
|
Log(" NumRecords = %u", NumRecords);
|
||||||
for (int i = 0; i < NumRecords; i++)
|
for (UInt32 i = 0; i < NumRecords; i++)
|
||||||
{
|
{
|
||||||
Log(" Records[%d] = {%d, %d, %d}", i, Records[i].x, Records[i].y, Records[i].z);
|
Log(" Records[%u] = {%d, %d, %d}", i, Records[i].x, Records[i].y, Records[i].z);
|
||||||
}
|
}
|
||||||
Log(" Player motion = <%.02f, %.02f, %.02f>", PlayerMotionX, PlayerMotionY, PlayerMotionZ);
|
Log(" Player motion = <%.02f, %.02f, %.02f>", PlayerMotionX, PlayerMotionY, PlayerMotionZ);
|
||||||
COPY_TO_CLIENT();
|
COPY_TO_CLIENT();
|
||||||
@ -1822,8 +1831,8 @@ bool cConnection::HandleServerKick(void)
|
|||||||
Reason.append(Split[5]);
|
Reason.append(Split[5]);
|
||||||
AString ReasonBE16 = UTF8ToRawBEUTF16(Reason.data(), Reason.size());
|
AString ReasonBE16 = UTF8ToRawBEUTF16(Reason.data(), Reason.size());
|
||||||
AString PacketStart("\xff");
|
AString PacketStart("\xff");
|
||||||
PacketStart.push_back((ReasonBE16.size() / 2) / 256);
|
PacketStart.push_back(static_cast<char>((ReasonBE16.size() / 2) / 256));
|
||||||
PacketStart.push_back((ReasonBE16.size() / 2) % 256);
|
PacketStart.push_back(static_cast<char>((ReasonBE16.size() / 2) % 256));
|
||||||
CLIENTSEND(PacketStart.data(), PacketStart.size());
|
CLIENTSEND(PacketStart.data(), PacketStart.size());
|
||||||
CLIENTSEND(ReasonBE16.data(), ReasonBE16.size());
|
CLIENTSEND(ReasonBE16.data(), ReasonBE16.size());
|
||||||
return true;
|
return true;
|
||||||
@ -1847,12 +1856,12 @@ bool cConnection::HandleServerKick(void)
|
|||||||
|
|
||||||
bool cConnection::HandleServerMapChunk(void)
|
bool cConnection::HandleServerMapChunk(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkX);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkX);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkZ);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkZ);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadChar, char, IsContiguous);
|
HANDLE_SERVER_PACKET_READ(ReadChar, char, IsContiguous);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, PrimaryBitmap);
|
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, PrimaryBitmap);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, AdditionalBitmap);
|
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, AdditionalBitmap);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, CompressedSize);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CompressedSize);
|
||||||
AString CompressedData;
|
AString CompressedData;
|
||||||
if (!m_ServerBuffer.ReadString(CompressedData, CompressedSize))
|
if (!m_ServerBuffer.ReadString(CompressedData, CompressedSize))
|
||||||
{
|
{
|
||||||
@ -1860,7 +1869,7 @@ bool cConnection::HandleServerMapChunk(void)
|
|||||||
}
|
}
|
||||||
Log("Received a PACKET_MAP_CHUNK from the server:");
|
Log("Received a PACKET_MAP_CHUNK from the server:");
|
||||||
Log(" ChunkPos = [%d, %d]", ChunkX, ChunkZ);
|
Log(" ChunkPos = [%d, %d]", ChunkX, ChunkZ);
|
||||||
Log(" Compressed size = %d (0x%x)", CompressedSize, CompressedSize);
|
Log(" Compressed size = %u (0x%x)", CompressedSize, CompressedSize);
|
||||||
|
|
||||||
// TODO: Save the compressed data into a file for later analysis
|
// TODO: Save the compressed data into a file for later analysis
|
||||||
|
|
||||||
@ -1874,9 +1883,9 @@ bool cConnection::HandleServerMapChunk(void)
|
|||||||
|
|
||||||
bool cConnection::HandleServerMapChunkBulk(void)
|
bool cConnection::HandleServerMapChunkBulk(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, ChunkCount);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, ChunkCount);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, CompressedSize);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, CompressedSize);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBool, bool, IsSkyLightSent);
|
HANDLE_SERVER_PACKET_READ(ReadBool, bool, IsSkyLightSent);
|
||||||
AString CompressedData;
|
AString CompressedData;
|
||||||
if (!m_ServerBuffer.ReadString(CompressedData, CompressedSize))
|
if (!m_ServerBuffer.ReadString(CompressedData, CompressedSize))
|
||||||
{
|
{
|
||||||
@ -1898,8 +1907,8 @@ bool cConnection::HandleServerMapChunkBulk(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log("Received a PACKET_MAP_CHUNK_BULK from the server:");
|
Log("Received a PACKET_MAP_CHUNK_BULK from the server:");
|
||||||
Log(" ChunkCount = %d", ChunkCount);
|
Log(" ChunkCount = %u", ChunkCount);
|
||||||
Log(" Compressed size = %d (0x%x)", CompressedSize, CompressedSize);
|
Log(" Compressed size = %u (0x%x)", CompressedSize, CompressedSize);
|
||||||
Log(" IsSkyLightSent = %s", IsSkyLightSent ? "true" : "false");
|
Log(" IsSkyLightSent = %s", IsSkyLightSent ? "true" : "false");
|
||||||
|
|
||||||
// Log individual chunk coords:
|
// Log individual chunk coords:
|
||||||
@ -1923,10 +1932,10 @@ bool cConnection::HandleServerMapChunkBulk(void)
|
|||||||
|
|
||||||
bool cConnection::HandleServerMultiBlockChange(void)
|
bool cConnection::HandleServerMultiBlockChange(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkX);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkX);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkZ);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, ChunkZ);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, NumBlocks);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, NumBlocks);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, DataSize);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt32, UInt32, DataSize);
|
||||||
AString BlockChangeData;
|
AString BlockChangeData;
|
||||||
if (!m_ServerBuffer.ReadString(BlockChangeData, DataSize))
|
if (!m_ServerBuffer.ReadString(BlockChangeData, DataSize))
|
||||||
{
|
{
|
||||||
@ -1934,7 +1943,7 @@ bool cConnection::HandleServerMultiBlockChange(void)
|
|||||||
}
|
}
|
||||||
Log("Received a PACKET_MULTI_BLOCK_CHANGE packet from the server:");
|
Log("Received a PACKET_MULTI_BLOCK_CHANGE packet from the server:");
|
||||||
Log(" Chunk = [%d, %d]", ChunkX, ChunkZ);
|
Log(" Chunk = [%d, %d]", ChunkX, ChunkZ);
|
||||||
Log(" NumBlocks = %d", NumBlocks);
|
Log(" NumBlocks = %u", NumBlocks);
|
||||||
COPY_TO_CLIENT();
|
COPY_TO_CLIENT();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2035,7 +2044,7 @@ bool cConnection::HandleServerPlayerPositionLook(void)
|
|||||||
bool cConnection::HandleServerPluginMessage(void)
|
bool cConnection::HandleServerPluginMessage(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ChannelName);
|
HANDLE_SERVER_PACKET_READ(ReadVarUTF8String, AString, ChannelName);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, Length);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, Length);
|
||||||
AString Data;
|
AString Data;
|
||||||
if (!m_ServerBuffer.ReadString(Data, Length))
|
if (!m_ServerBuffer.ReadString(Data, Length))
|
||||||
{
|
{
|
||||||
@ -2043,7 +2052,7 @@ bool cConnection::HandleServerPluginMessage(void)
|
|||||||
}
|
}
|
||||||
Log("Received a PACKET_PLUGIN_MESSAGE from the server");
|
Log("Received a PACKET_PLUGIN_MESSAGE from the server");
|
||||||
Log(" ChannelName = \"%s\"", ChannelName.c_str());
|
Log(" ChannelName = \"%s\"", ChannelName.c_str());
|
||||||
DataLog(Data.data(), Length, " Data: %d bytes", Length);
|
DataLog(Data.data(), Length, " Data: %u bytes", Length);
|
||||||
COPY_TO_CLIENT();
|
COPY_TO_CLIENT();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2530,11 +2539,11 @@ bool cConnection::HandleServerUpdateSign(void)
|
|||||||
|
|
||||||
bool cConnection::HandleServerUpdateTileEntity(void)
|
bool cConnection::HandleServerUpdateTileEntity(void)
|
||||||
{
|
{
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockX);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockX);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, BlockY);
|
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, BlockY);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockZ);
|
HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockZ);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadByte, Byte, Action);
|
HANDLE_SERVER_PACKET_READ(ReadByte, Byte, Action);
|
||||||
HANDLE_SERVER_PACKET_READ(ReadBEShort, short, DataLength);
|
HANDLE_SERVER_PACKET_READ(ReadBEUInt16, UInt16, DataLength);
|
||||||
|
|
||||||
AString Data;
|
AString Data;
|
||||||
if ((DataLength > 0) && !m_ServerBuffer.ReadString(Data, DataLength))
|
if ((DataLength > 0) && !m_ServerBuffer.ReadString(Data, DataLength))
|
||||||
@ -2548,7 +2557,7 @@ bool cConnection::HandleServerUpdateTileEntity(void)
|
|||||||
|
|
||||||
// Save metadata to a file:
|
// Save metadata to a file:
|
||||||
AString fnam;
|
AString fnam;
|
||||||
Printf(fnam, "%s_item_%08x.nbt", m_LogNameBase.c_str(), m_ItemIdx++);
|
Printf(fnam, "%s_tile_%08x.nbt", m_LogNameBase.c_str(), m_ItemIdx++);
|
||||||
FILE * f = fopen(fnam.c_str(), "wb");
|
FILE * f = fopen(fnam.c_str(), "wb");
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
{
|
{
|
||||||
@ -2686,10 +2695,10 @@ bool cConnection::ParseSlot(cByteBuffer & a_Buffer, AString & a_ItemDesc)
|
|||||||
}
|
}
|
||||||
char ItemCount;
|
char ItemCount;
|
||||||
short ItemDamage;
|
short ItemDamage;
|
||||||
short MetadataLength;
|
UInt16 MetadataLength;
|
||||||
a_Buffer.ReadChar(ItemCount);
|
a_Buffer.ReadChar(ItemCount); // We already know we can read these bytes - we checked before.
|
||||||
a_Buffer.ReadBEShort(ItemDamage);
|
a_Buffer.ReadBEShort(ItemDamage);
|
||||||
a_Buffer.ReadBEShort(MetadataLength);
|
a_Buffer.ReadBEUInt16(MetadataLength);
|
||||||
Printf(a_ItemDesc, "%d:%d * %d", ItemType, ItemDamage, ItemCount);
|
Printf(a_ItemDesc, "%d:%d * %d", ItemType, ItemDamage, ItemCount);
|
||||||
if (MetadataLength <= 0)
|
if (MetadataLength <= 0)
|
||||||
{
|
{
|
||||||
@ -2697,13 +2706,13 @@ bool cConnection::ParseSlot(cByteBuffer & a_Buffer, AString & a_ItemDesc)
|
|||||||
}
|
}
|
||||||
AString Metadata;
|
AString Metadata;
|
||||||
Metadata.resize(MetadataLength);
|
Metadata.resize(MetadataLength);
|
||||||
if (!a_Buffer.ReadBuf((void *)Metadata.data(), MetadataLength))
|
if (!a_Buffer.ReadBuf(const_cast<char *>(Metadata.data()), MetadataLength))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AString MetaHex;
|
AString MetaHex;
|
||||||
CreateHexDump(MetaHex, Metadata.data(), Metadata.size(), 16);
|
CreateHexDump(MetaHex, Metadata.data(), Metadata.size(), 16);
|
||||||
AppendPrintf(a_ItemDesc, "; %d bytes of meta:\n%s", MetadataLength, MetaHex.c_str());
|
AppendPrintf(a_ItemDesc, "; %u bytes of meta:\n%s", MetadataLength, MetaHex.c_str());
|
||||||
|
|
||||||
// Save metadata to a file:
|
// Save metadata to a file:
|
||||||
AString fnam;
|
AString fnam;
|
||||||
@ -2725,17 +2734,19 @@ bool cConnection::ParseSlot(cByteBuffer & a_Buffer, AString & a_ItemDesc)
|
|||||||
|
|
||||||
bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
|
bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
|
||||||
{
|
{
|
||||||
char x;
|
Byte x;
|
||||||
if (!a_Buffer.ReadChar(x))
|
if (!a_Buffer.ReadByte(x))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
a_Metadata.push_back(x);
|
a_Metadata.push_back(static_cast<char>(x));
|
||||||
while (x != 0x7f)
|
while (x != 0x7f)
|
||||||
{
|
{
|
||||||
// int Index = ((unsigned)((unsigned char)x)) & 0x1f; // Lower 5 bits = index
|
// int Index = static_cast<unsigned>(x) & 0x1f; // Lower 5 bits = index
|
||||||
int Type = ((unsigned)((unsigned char)x)) >> 5; // Upper 3 bits = type
|
int Type = static_cast<unsigned>(x) >> 5; // Upper 3 bits = type
|
||||||
int Length = 0;
|
|
||||||
|
// Get the length of the data for this item:
|
||||||
|
UInt32 Length = 0;
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case 0: Length = 1; break; // Byte
|
case 0: Length = 1; break; // Byte
|
||||||
@ -2745,12 +2756,12 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
|
|||||||
case 4: // UTF-8 string with VarInt length
|
case 4: // UTF-8 string with VarInt length
|
||||||
{
|
{
|
||||||
UInt32 Len;
|
UInt32 Len;
|
||||||
int rs = a_Buffer.GetReadableSpace();
|
int rs = static_cast<int>(a_Buffer.GetReadableSpace());
|
||||||
if (!a_Buffer.ReadVarInt(Len))
|
if (!a_Buffer.ReadVarInt(Len))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rs = rs - a_Buffer.GetReadableSpace();
|
rs = rs - static_cast<int>(a_Buffer.GetReadableSpace());
|
||||||
cByteBuffer LenBuf(8);
|
cByteBuffer LenBuf(8);
|
||||||
LenBuf.WriteVarInt(Len);
|
LenBuf.WriteVarInt(Len);
|
||||||
AString VarLen;
|
AString VarLen;
|
||||||
@ -2759,18 +2770,18 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
|
|||||||
Length = Len;
|
Length = Len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5:
|
case 5: // Item, in "slot" format
|
||||||
{
|
{
|
||||||
int Before = a_Buffer.GetReadableSpace();
|
size_t Before = a_Buffer.GetReadableSpace();
|
||||||
AString ItemDesc;
|
AString ItemDesc;
|
||||||
if (!ParseSlot(a_Buffer, ItemDesc))
|
if (!ParseSlot(a_Buffer, ItemDesc))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int After = a_Buffer.GetReadableSpace();
|
size_t After = a_Buffer.GetReadableSpace();
|
||||||
a_Buffer.ResetRead();
|
a_Buffer.ResetRead();
|
||||||
a_Buffer.SkipRead(a_Buffer.GetReadableSpace() - Before);
|
a_Buffer.SkipRead(a_Buffer.GetReadableSpace() - Before);
|
||||||
Length = Before - After;
|
Length = static_cast<UInt32>(Before - After);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6: Length = 12; break; // 3 * int
|
case 6: Length = 12; break; // 3 * int
|
||||||
@ -2781,17 +2792,19 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // switch (Type)
|
} // switch (Type)
|
||||||
|
|
||||||
|
// Read the data in this item:
|
||||||
AString data;
|
AString data;
|
||||||
if (!a_Buffer.ReadString(data, Length))
|
if (!a_Buffer.ReadString(data, Length))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
a_Metadata.append(data);
|
a_Metadata.append(data);
|
||||||
if (!a_Buffer.ReadChar(x))
|
if (!a_Buffer.ReadByte(x))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
a_Metadata.push_back(x);
|
a_Metadata.push_back(static_cast<char>(x));
|
||||||
} // while (x != 0x7f)
|
} // while (x != 0x7f)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2803,58 +2816,62 @@ bool cConnection::ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata)
|
|||||||
void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount)
|
void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount)
|
||||||
{
|
{
|
||||||
AString Indent(a_IndentCount, ' ');
|
AString Indent(a_IndentCount, ' ');
|
||||||
int pos = 0;
|
size_t pos = 0;
|
||||||
while (a_Metadata[pos] != 0x7f)
|
while (a_Metadata[pos] != 0x7f)
|
||||||
{
|
{
|
||||||
int Index = ((unsigned)((unsigned char)a_Metadata[pos])) & 0x1f; // Lower 5 bits = index
|
unsigned Index = static_cast<unsigned>(static_cast<unsigned char>(a_Metadata[pos])) & 0x1f; // Lower 5 bits = index
|
||||||
int Type = ((unsigned)((unsigned char)a_Metadata[pos])) >> 5; // Upper 3 bits = type
|
unsigned Type = static_cast<unsigned>(static_cast<unsigned char>(a_Metadata[pos])) >> 5; // Upper 3 bits = type
|
||||||
// int Length = 0;
|
// int Length = 0;
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
{
|
||||||
Log("%sbyte[%d] = %d", Indent.c_str(), Index, a_Metadata[pos + 1]);
|
Log("%sbyte[%u] = %d", Indent.c_str(), Index, a_Metadata[pos + 1]);
|
||||||
pos += 1;
|
pos += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
Log("%sshort[%d] = %d", Indent.c_str(), Index, (a_Metadata[pos + 1] << 8) | a_Metadata[pos + 2]);
|
Log("%sshort[%u] = %d", Indent.c_str(), Index, (a_Metadata[pos + 1] << 8) | a_Metadata[pos + 2]);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
Log("%sint[%d] = %d", Indent.c_str(), Index, (a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4]);
|
Log("%sint[%u] = %d", Indent.c_str(), Index, (a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4]);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
Log("%sfloat[%d] = 0x%x", Indent.c_str(), Index, (a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4]);
|
Log("%sfloat[%u] = 0x%x", Indent.c_str(), Index, (a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4]);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: // UTF-8 string with VarInt length
|
case 4: // UTF-8 string with VarInt length
|
||||||
{
|
{
|
||||||
cByteBuffer bb(10);
|
cByteBuffer bb(10);
|
||||||
int RestLen = (int)a_Metadata.size() - pos - 1;
|
size_t RestLen = a_Metadata.size() - pos - 1;
|
||||||
if (RestLen > 8)
|
if (RestLen > 8)
|
||||||
{
|
{
|
||||||
RestLen = 8;
|
RestLen = 8;
|
||||||
}
|
}
|
||||||
bb.Write(a_Metadata.data() + pos + 1, RestLen);
|
bb.Write(a_Metadata.data() + pos + 1, RestLen);
|
||||||
UInt32 Length;
|
UInt32 Length;
|
||||||
int rs = bb.GetReadableSpace();
|
size_t rs = bb.GetReadableSpace();
|
||||||
bb.ReadVarInt(Length);
|
if (!bb.ReadVarInt(Length))
|
||||||
|
{
|
||||||
|
Log("Invalid metadata value, was supposed to be a varint-prefixed string, but cannot read the varint");
|
||||||
|
break;
|
||||||
|
}
|
||||||
rs = rs - bb.GetReadableSpace();
|
rs = rs - bb.GetReadableSpace();
|
||||||
Log("%sstring[%d] = \"%*s\"", Indent.c_str(), Index, Length, a_Metadata.c_str() + pos + rs + 1);
|
Log("%sstring[%u] = \"%*s\"", Indent.c_str(), Index, Length, a_Metadata.c_str() + pos + rs + 1);
|
||||||
pos += Length + rs + 2;
|
pos += Length + rs + 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5:
|
case 5:
|
||||||
{
|
{
|
||||||
int BytesLeft = a_Metadata.size() - pos - 1;
|
size_t BytesLeft = a_Metadata.size() - pos - 1;
|
||||||
cByteBuffer bb(BytesLeft);
|
cByteBuffer bb(BytesLeft);
|
||||||
bb.Write(a_Metadata.data() + pos + 1, BytesLeft);
|
bb.Write(a_Metadata.data() + pos + 1, BytesLeft);
|
||||||
AString ItemDesc;
|
AString ItemDesc;
|
||||||
@ -2863,16 +2880,16 @@ void cConnection::LogMetadata(const AString & a_Metadata, size_t a_IndentCount)
|
|||||||
ASSERT(!"Cannot parse item description from metadata");
|
ASSERT(!"Cannot parse item description from metadata");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// int After = bb.GetReadableSpace();
|
// size_t After = bb.GetReadableSpace();
|
||||||
int BytesConsumed = BytesLeft - bb.GetReadableSpace();
|
size_t BytesConsumed = BytesLeft - bb.GetReadableSpace();
|
||||||
|
|
||||||
Log("%sslot[%d] = %s (%d bytes)", Indent.c_str(), Index, ItemDesc.c_str(), BytesConsumed);
|
Log("%sslot[%u] = %s (%u bytes)", Indent.c_str(), Index, ItemDesc.c_str(), static_cast<unsigned>(BytesConsumed));
|
||||||
pos += BytesConsumed;
|
pos += BytesConsumed;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6:
|
case 6:
|
||||||
{
|
{
|
||||||
Log("%spos[%d] = <%d, %d, %d>", Indent.c_str(), Index,
|
Log("%spos[%u] = <%d, %d, %d>", Indent.c_str(), Index,
|
||||||
(a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4],
|
(a_Metadata[pos + 1] << 24) | (a_Metadata[pos + 2] << 16) | (a_Metadata[pos + 3] << 8) | a_Metadata[pos + 4],
|
||||||
(a_Metadata[pos + 5] << 24) | (a_Metadata[pos + 6] << 16) | (a_Metadata[pos + 7] << 8) | a_Metadata[pos + 8],
|
(a_Metadata[pos + 5] << 24) | (a_Metadata[pos + 6] << 16) | (a_Metadata[pos + 7] << 8) | a_Metadata[pos + 8],
|
||||||
(a_Metadata[pos + 9] << 24) | (a_Metadata[pos + 10] << 16) | (a_Metadata[pos + 11] << 8) | a_Metadata[pos + 12]
|
(a_Metadata[pos + 9] << 24) | (a_Metadata[pos + 10] << 16) | (a_Metadata[pos + 11] << 8) | a_Metadata[pos + 12]
|
||||||
@ -2931,7 +2948,7 @@ void cConnection::SendEncryptionKeyResponse(const AString & a_ServerPublicKey, c
|
|||||||
DataLog(EncryptedSecret, sizeof(EncryptedSecret), "Encrypted secret (%u bytes)", (unsigned)sizeof(EncryptedSecret));
|
DataLog(EncryptedSecret, sizeof(EncryptedSecret), "Encrypted secret (%u bytes)", (unsigned)sizeof(EncryptedSecret));
|
||||||
DataLog(EncryptedNonce, sizeof(EncryptedNonce), "Encrypted nonce (%u bytes)", (unsigned)sizeof(EncryptedNonce));
|
DataLog(EncryptedNonce, sizeof(EncryptedNonce), "Encrypted nonce (%u bytes)", (unsigned)sizeof(EncryptedNonce));
|
||||||
cByteBuffer Len(5);
|
cByteBuffer Len(5);
|
||||||
Len.WriteVarInt(ToServer.GetReadableSpace());
|
Len.WriteVarInt(static_cast<UInt32>(ToServer.GetReadableSpace()));
|
||||||
SERVERSEND(Len);
|
SERVERSEND(Len);
|
||||||
SERVERSEND(ToServer);
|
SERVERSEND(ToServer);
|
||||||
m_ServerState = csEncryptedUnderstood;
|
m_ServerState = csEncryptedUnderstood;
|
||||||
|
@ -58,7 +58,7 @@ public:
|
|||||||
void Run(void);
|
void Run(void);
|
||||||
|
|
||||||
void Log(const char * a_Format, ...);
|
void Log(const char * a_Format, ...);
|
||||||
void DataLog(const void * a_Data, int a_Size, const char * a_Format, ...);
|
void DataLog(const void * a_Data, size_t a_Size, const char * a_Format, ...);
|
||||||
void LogFlush(void);
|
void LogFlush(void);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -38,13 +38,41 @@ int cServer::Init(short a_ListenPort, short a_ConnectPort)
|
|||||||
m_PublicKeyDER = m_PrivateKey.GetPubKeyDER();
|
m_PublicKeyDER = m_PrivateKey.GetPubKeyDER();
|
||||||
|
|
||||||
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
m_ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (m_ListenSocket < 0)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
int err = WSAGetLastError();
|
||||||
|
#else
|
||||||
|
int err = errno;
|
||||||
|
#endif
|
||||||
|
printf("Failed to create listener socket: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
sockaddr_in local;
|
sockaddr_in local;
|
||||||
memset(&local, 0, sizeof(local));
|
memset(&local, 0, sizeof(local));
|
||||||
local.sin_family = AF_INET;
|
local.sin_family = AF_INET;
|
||||||
local.sin_addr.s_addr = 0; // All interfaces
|
local.sin_addr.s_addr = 130; // INADDR_ANY; // All interfaces
|
||||||
local.sin_port = htons(a_ListenPort);
|
local.sin_port = htons(a_ListenPort);
|
||||||
bind(m_ListenSocket, (sockaddr *)&local, sizeof(local));
|
if (!bind(m_ListenSocket, (sockaddr *)&local, sizeof(local)))
|
||||||
listen(m_ListenSocket, 1);
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
int err = WSAGetLastError();
|
||||||
|
#else
|
||||||
|
int err = errno;
|
||||||
|
#endif
|
||||||
|
printf("Failed to bind listener socket: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
if (listen(m_ListenSocket, 1) != 0)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
int err = WSAGetLastError();
|
||||||
|
#else
|
||||||
|
int err = errno;
|
||||||
|
#endif
|
||||||
|
printf("Failed to listen on socket: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
printf("Listening on port %d, connecting to localhost:%d\n", a_ListenPort, a_ConnectPort);
|
printf("Listening on port %d, connecting to localhost:%d\n", a_ListenPort, a_ConnectPort);
|
||||||
|
|
||||||
|
8
app.yml
8
app.yml
@ -3,9 +3,7 @@ image: ubuntu-14-04-x64
|
|||||||
config:
|
config:
|
||||||
#cloud-config
|
#cloud-config
|
||||||
packages:
|
packages:
|
||||||
- curl
|
- git
|
||||||
- screen
|
|
||||||
runcmd:
|
runcmd:
|
||||||
- mkdir /minecraft
|
- cd /tmp && git clone https://github.com/cuberite/mcserver-ocean.git
|
||||||
- cd /minecraft && curl -s https://raw.githubusercontent.com/mc-server/MCServer/master/easyinstall.sh | sh
|
- cd /tmp/mcserver-ocean && ./initialinstall.sh
|
||||||
- cd /minecraft/MCServer && screen -S mcserver -d -m ./MCServer
|
|
||||||
|
@ -7,7 +7,7 @@ case $PLATFORM in
|
|||||||
"i686") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20x86/lastSuccessfulBuild/artifact/MCServer.tar" ;;
|
"i686") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20x86/lastSuccessfulBuild/artifact/MCServer.tar" ;;
|
||||||
"x86_64") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20x64/lastSuccessfulBuild/artifact/MCServer.tar" ;;
|
"x86_64") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20x64/lastSuccessfulBuild/artifact/MCServer.tar" ;;
|
||||||
# Assume that all arm devices are a raspi for now.
|
# Assume that all arm devices are a raspi for now.
|
||||||
"arm*") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20armhf/lastSuccessfulBuild/artifact/MCServer.tar"
|
"arm*") DOWNLOADURL="http://builds.cuberite.org/job/MCServer%20Linux%20armhf/lastSuccessfulBuild/artifact/MCServer/MCServer.tar"
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo "Downloading precompiled binaries."
|
echo "Downloading precompiled binaries."
|
||||||
|
1
lib/libevent
Submodule
1
lib/libevent
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 0b49ae34594533daa82c06a506078de9e336a013
|
@ -839,6 +839,13 @@ void cLuaState::Push(void * a_Ptr)
|
|||||||
m_NumCurrentFunctionArgs += 1;
|
m_NumCurrentFunctionArgs += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cLuaState::Push(std::chrono::milliseconds a_Value)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
|
tolua_pushnumber(m_LuaState, static_cast<lua_Number>(a_Value.count()));
|
||||||
|
m_NumCurrentFunctionArgs += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -217,6 +217,7 @@ public:
|
|||||||
void Push(Vector3d * a_Vector);
|
void Push(Vector3d * a_Vector);
|
||||||
void Push(Vector3i * a_Vector);
|
void Push(Vector3i * a_Vector);
|
||||||
void Push(void * a_Ptr);
|
void Push(void * a_Ptr);
|
||||||
|
void Push(std::chrono::milliseconds a_time);
|
||||||
|
|
||||||
/** Retrieve value at a_StackPos, if it is a valid bool. If not, a_Value is unchanged */
|
/** Retrieve value at a_StackPos, if it is a valid bool. If not, a_Value is unchanged */
|
||||||
void GetStackValue(int a_StackPos, bool & a_Value);
|
void GetStackValue(int a_StackPos, bool & a_Value);
|
||||||
|
@ -76,8 +76,8 @@ public:
|
|||||||
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 OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0;
|
virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) = 0;
|
||||||
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
|
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) = 0;
|
||||||
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
|
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) = 0;
|
||||||
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0;
|
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) = 0;
|
||||||
virtual bool OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) = 0;
|
virtual bool OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) = 0;
|
||||||
virtual bool OnPlayerShooting (cPlayer & a_Player) = 0;
|
virtual bool OnPlayerShooting (cPlayer & a_Player) = 0;
|
||||||
@ -104,7 +104,7 @@ public:
|
|||||||
virtual bool OnWeatherChanged (cWorld & a_World) = 0;
|
virtual bool OnWeatherChanged (cWorld & a_World) = 0;
|
||||||
virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) = 0;
|
virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) = 0;
|
||||||
virtual bool OnWorldStarted (cWorld & a_World) = 0;
|
virtual bool OnWorldStarted (cWorld & a_World) = 0;
|
||||||
virtual bool OnWorldTick (cWorld & a_World, float a_Dt, int a_LastTickDurationMSec) = 0;
|
virtual bool OnWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) = 0;
|
||||||
|
|
||||||
/** Handles the command split into a_Split, issued by player a_Player.
|
/** Handles the command split into a_Split, issued by player a_Player.
|
||||||
Command permissions have already been checked.
|
Command permissions have already been checked.
|
||||||
|
@ -857,14 +857,19 @@ bool cPluginLua::OnPlayerMoving(cPlayer & a_Player, const Vector3d & a_OldPositi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginLua::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
bool cPluginLua::OnPlayerPlacedBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
bool res = false;
|
bool res = false;
|
||||||
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACED_BLOCK];
|
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACED_BLOCK];
|
||||||
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_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
|
m_LuaState.Call((int)(**itr), &a_Player,
|
||||||
|
a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(),
|
||||||
|
a_BlockChange.m_BlockType, a_BlockChange.m_BlockMeta,
|
||||||
|
cLuaState::Return,
|
||||||
|
res
|
||||||
|
);
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -877,14 +882,19 @@ bool cPluginLua::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a_Blo
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginLua::OnPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
bool cPluginLua::OnPlayerPlacingBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
bool res = false;
|
bool res = false;
|
||||||
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACING_BLOCK];
|
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_PLAYER_PLACING_BLOCK];
|
||||||
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_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta, cLuaState::Return, res);
|
m_LuaState.Call((int)(**itr), &a_Player,
|
||||||
|
a_BlockChange.GetX(), a_BlockChange.GetY(), a_BlockChange.GetZ(),
|
||||||
|
a_BlockChange.m_BlockType, a_BlockChange.m_BlockMeta,
|
||||||
|
cLuaState::Return,
|
||||||
|
res
|
||||||
|
);
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -1420,7 +1430,7 @@ bool cPluginLua::OnWorldStarted(cWorld & a_World)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginLua::OnWorldTick(cWorld & a_World, float a_Dt, int a_LastTickDurationMSec)
|
bool cPluginLua::OnWorldTick(cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CriticalSection);
|
cCSLock Lock(m_CriticalSection);
|
||||||
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WORLD_TICK];
|
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_WORLD_TICK];
|
||||||
|
@ -100,8 +100,8 @@ public:
|
|||||||
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
|
virtual bool OnPlayerJoined (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;
|
||||||
virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) override;
|
virtual bool OnPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition) override;
|
||||||
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
|
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) override;
|
||||||
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
|
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange) override;
|
||||||
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
|
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
|
||||||
virtual bool OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) override;
|
virtual bool OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity) override;
|
||||||
virtual bool OnPlayerShooting (cPlayer & a_Player) override;
|
virtual bool OnPlayerShooting (cPlayer & a_Player) override;
|
||||||
@ -128,7 +128,7 @@ public:
|
|||||||
virtual bool OnWeatherChanged (cWorld & a_World) override;
|
virtual bool OnWeatherChanged (cWorld & a_World) override;
|
||||||
virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) override;
|
virtual bool OnWeatherChanging (cWorld & a_World, eWeather & a_NewWeather) override;
|
||||||
virtual bool OnWorldStarted (cWorld & a_World) override;
|
virtual bool OnWorldStarted (cWorld & a_World) override;
|
||||||
virtual bool OnWorldTick (cWorld & a_World, float a_Dt, int a_LastTickDurationMSec) override;
|
virtual bool OnWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec) override;
|
||||||
|
|
||||||
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player) override;
|
virtual bool HandleCommand(const AStringVector & a_Split, cPlayer & a_Player) override;
|
||||||
|
|
||||||
|
@ -771,7 +771,7 @@ bool cPluginManager::CallHookPlayerFoodLevelChange(cPlayer & a_Player, int a_New
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
VERIFY_HOOK;
|
VERIFY_HOOK;
|
||||||
@ -847,7 +847,7 @@ bool cPluginManager::CallHookPlayerLeftClick(cPlayer & a_Player, int a_BlockX, i
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition)
|
bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition)
|
||||||
{
|
{
|
||||||
FIND_HOOK(HOOK_PLAYER_MOVING);
|
FIND_HOOK(HOOK_PLAYER_MOVING);
|
||||||
VERIFY_HOOK;
|
VERIFY_HOOK;
|
||||||
@ -866,14 +866,14 @@ bool cPluginManager::CallHookPlayerMoving(cPlayer & a_Player, const Vector3d a_O
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::CallHookPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
bool cPluginManager::CallHookPlayerPlacedBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange)
|
||||||
{
|
{
|
||||||
FIND_HOOK(HOOK_PLAYER_PLACED_BLOCK);
|
FIND_HOOK(HOOK_PLAYER_PLACED_BLOCK);
|
||||||
VERIFY_HOOK;
|
VERIFY_HOOK;
|
||||||
|
|
||||||
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
||||||
{
|
{
|
||||||
if ((*itr)->OnPlayerPlacedBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta))
|
if ((*itr)->OnPlayerPlacedBlock(a_Player, a_BlockChange))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -885,14 +885,14 @@ bool cPluginManager::CallHookPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::CallHookPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
bool cPluginManager::CallHookPlayerPlacingBlock(cPlayer & a_Player, const sSetBlock & a_BlockChange)
|
||||||
{
|
{
|
||||||
FIND_HOOK(HOOK_PLAYER_PLACING_BLOCK);
|
FIND_HOOK(HOOK_PLAYER_PLACING_BLOCK);
|
||||||
VERIFY_HOOK;
|
VERIFY_HOOK;
|
||||||
|
|
||||||
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
||||||
{
|
{
|
||||||
if ((*itr)->OnPlayerPlacingBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta))
|
if ((*itr)->OnPlayerPlacingBlock(a_Player, a_BlockChange))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1394,7 +1394,7 @@ bool cPluginManager::CallHookWorldStarted(cWorld & a_World)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPluginManager::CallHookWorldTick(cWorld & a_World, float a_Dt, int a_LastTickDurationMSec)
|
bool cPluginManager::CallHookWorldTick(cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec)
|
||||||
{
|
{
|
||||||
FIND_HOOK(HOOK_WORLD_TICK);
|
FIND_HOOK(HOOK_WORLD_TICK);
|
||||||
VERIFY_HOOK;
|
VERIFY_HOOK;
|
||||||
|
@ -203,14 +203,14 @@ public:
|
|||||||
bool CallHookPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
bool CallHookPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||||
bool CallHookPlayerDestroyed (cPlayer & a_Player);
|
bool CallHookPlayerDestroyed (cPlayer & a_Player);
|
||||||
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 CallHookPlayerFoodLevelChange (cPlayer & a_Player, int a_NewFoodLevel);
|
||||||
bool CallHookPlayerJoined (cPlayer & a_Player);
|
bool CallHookPlayerJoined (cPlayer & a_Player);
|
||||||
bool CallHookPlayerMoving (cPlayer & a_Player, const Vector3d a_OldPosition, const Vector3d a_NewPosition);
|
|
||||||
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);
|
||||||
bool CallHookPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
bool CallHookPlayerMoving (cPlayer & a_Player, const Vector3d & a_OldPosition, const Vector3d & a_NewPosition);
|
||||||
bool CallHookPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
bool CallHookPlayerPlacedBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange);
|
||||||
|
bool CallHookPlayerPlacingBlock (cPlayer & a_Player, const sSetBlock & a_BlockChange);
|
||||||
bool CallHookPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
|
bool CallHookPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
|
||||||
bool CallHookPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity);
|
bool CallHookPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a_Entity);
|
||||||
bool CallHookPlayerShooting (cPlayer & a_Player);
|
bool CallHookPlayerShooting (cPlayer & a_Player);
|
||||||
@ -237,7 +237,7 @@ public:
|
|||||||
bool CallHookWeatherChanged (cWorld & a_World);
|
bool CallHookWeatherChanged (cWorld & a_World);
|
||||||
bool CallHookWeatherChanging (cWorld & a_World, eWeather & a_NewWeather);
|
bool CallHookWeatherChanging (cWorld & a_World, eWeather & a_NewWeather);
|
||||||
bool CallHookWorldStarted (cWorld & a_World);
|
bool CallHookWorldStarted (cWorld & a_World);
|
||||||
bool CallHookWorldTick (cWorld & a_World, float a_Dt, int a_LastTickDurationMSec);
|
bool CallHookWorldTick (cWorld & a_World, std::chrono::milliseconds a_Dt, std::chrono::milliseconds a_LastTickDurationMSec);
|
||||||
|
|
||||||
bool DisablePlugin(const AString & a_PluginName); // tolua_export
|
bool DisablePlugin(const AString & a_PluginName); // tolua_export
|
||||||
bool LoadPlugin (const AString & a_PluginName); // tolua_export
|
bool LoadPlugin (const AString & a_PluginName); // tolua_export
|
||||||
|
@ -267,7 +267,7 @@ void cBeaconEntity::GiveEffects(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cBeaconEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// Update the beacon every 4 seconds
|
// Update the beacon every 4 seconds
|
||||||
if ((GetWorld()->GetWorldAge() % 80) == 0)
|
if ((GetWorld()->GetWorldAge() % 80) == 0)
|
||||||
|
@ -30,7 +30,7 @@ public:
|
|||||||
|
|
||||||
// cBlockEntity overrides:
|
// cBlockEntity overrides:
|
||||||
virtual void SendTo(cClientHandle & a_Client) override;
|
virtual void SendTo(cClientHandle & a_Client) override;
|
||||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void UsedBy(cPlayer * a_Player) override;
|
virtual void UsedBy(cPlayer * a_Player) override;
|
||||||
|
|
||||||
/** Modify the beacon level. (It is needed to load the beacon corectly) */
|
/** Modify the beacon level. (It is needed to load the beacon corectly) */
|
||||||
|
@ -110,7 +110,7 @@ public:
|
|||||||
virtual void SendTo(cClientHandle & a_Client) = 0;
|
virtual void SendTo(cClientHandle & a_Client) = 0;
|
||||||
|
|
||||||
/// Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing.
|
/// Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing.
|
||||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk)
|
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
return false;
|
return false;
|
||||||
|
@ -125,7 +125,7 @@ void cCommandBlockEntity::SetRedstonePower(bool a_IsPowered)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cCommandBlockEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
bool cCommandBlockEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
/// Creates a new empty command block entity
|
/// Creates a new empty command block entity
|
||||||
cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
|
cCommandBlockEntity(int a_X, int a_Y, int a_Z, cWorld * a_World);
|
||||||
|
|
||||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ void cDropSpenserEntity::SetRedstonePower(bool a_IsPowered)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cDropSpenserEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
bool cDropSpenserEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
if (!m_ShouldDropSpense)
|
if (!m_ShouldDropSpense)
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
virtual ~cDropSpenserEntity();
|
virtual ~cDropSpenserEntity();
|
||||||
|
|
||||||
// cBlockEntity overrides:
|
// cBlockEntity overrides:
|
||||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ bool cFurnaceEntity::ContinueCooking(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cFurnaceEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
bool cFurnaceEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
// cBlockEntity overrides:
|
// cBlockEntity overrides:
|
||||||
virtual void SendTo(cClientHandle & a_Client) override;
|
virtual void SendTo(cClientHandle & a_Client) override;
|
||||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void UsedBy(cPlayer * a_Player) override;
|
virtual void UsedBy(cPlayer * a_Player) override;
|
||||||
virtual void Destroy() override
|
virtual void Destroy() override
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ bool cHopperEntity::GetOutputBlockPos(NIBBLETYPE a_BlockMeta, int & a_OutputX, i
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cHopperEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
bool cHopperEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
|
Int64 CurrentTick = a_Chunk.GetWorld()->GetWorldAge();
|
||||||
|
@ -48,7 +48,7 @@ protected:
|
|||||||
Int64 m_LastMoveItemsOutTick;
|
Int64 m_LastMoveItemsOutTick;
|
||||||
|
|
||||||
// cBlockEntity overrides:
|
// cBlockEntity overrides:
|
||||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
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;
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ void cMobSpawnerEntity::UpdateActiveState(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cMobSpawnerEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// Update the active flag every 5 seconds
|
// Update the active flag every 5 seconds
|
||||||
if ((m_World->GetWorldAge() % 100) == 0)
|
if ((m_World->GetWorldAge() % 100) == 0)
|
||||||
|
@ -29,7 +29,7 @@ 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;
|
||||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
|
@ -959,6 +959,7 @@ enum
|
|||||||
E_META_SPAWN_EGG_WITHER = 64,
|
E_META_SPAWN_EGG_WITHER = 64,
|
||||||
E_META_SPAWN_EGG_BAT = 65,
|
E_META_SPAWN_EGG_BAT = 65,
|
||||||
E_META_SPAWN_EGG_WITCH = 66,
|
E_META_SPAWN_EGG_WITCH = 66,
|
||||||
|
E_META_SPAWN_EGG_GUARDIAN = 68,
|
||||||
E_META_SPAWN_EGG_PIG = 90,
|
E_META_SPAWN_EGG_PIG = 90,
|
||||||
E_META_SPAWN_EGG_SHEEP = 91,
|
E_META_SPAWN_EGG_SHEEP = 91,
|
||||||
E_META_SPAWN_EGG_COW = 92,
|
E_META_SPAWN_EGG_COW = 92,
|
||||||
@ -970,6 +971,7 @@ enum
|
|||||||
E_META_SPAWN_EGG_OCELOT = 98,
|
E_META_SPAWN_EGG_OCELOT = 98,
|
||||||
E_META_SPAWN_EGG_IRON_GOLEM = 99,
|
E_META_SPAWN_EGG_IRON_GOLEM = 99,
|
||||||
E_META_SPAWN_EGG_HORSE = 100,
|
E_META_SPAWN_EGG_HORSE = 100,
|
||||||
|
E_META_SPAWN_EGG_RABBIT = 101,
|
||||||
E_META_SPAWN_EGG_VILLAGER = 120,
|
E_META_SPAWN_EGG_VILLAGER = 120,
|
||||||
E_META_SPAWN_EGG_ENDER_CRYSTAL = 200,
|
E_META_SPAWN_EGG_ENDER_CRYSTAL = 200,
|
||||||
} ;
|
} ;
|
||||||
|
@ -14,24 +14,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockBedHandler::OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (a_BlockMeta < 8)
|
|
||||||
{
|
|
||||||
Vector3i Direction = MetaDataToDirection(a_BlockMeta);
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, a_BlockMeta | 0x8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
@ -151,7 +133,7 @@ void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface
|
|||||||
cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_WorldInterface);
|
cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_WorldInterface);
|
||||||
a_WorldInterface.ForEachPlayer(Unsetter);
|
a_WorldInterface.ForEachPlayer(Unsetter);
|
||||||
a_WorldInterface.SetTimeOfDay(0);
|
a_WorldInterface.SetTimeOfDay(0);
|
||||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0xB); // Where 0xB = 1011, and zero is to make sure 'occupied' bit is always unset
|
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x0b); // Clear the "occupied" bit of the bed's block
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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;
|
|
||||||
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
|
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override;
|
||||||
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
|
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
|
||||||
|
|
||||||
|
@ -85,18 +85,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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
|
|
||||||
{
|
|
||||||
int Meta = (((int)floor(a_Player->GetYaw() * 4.0 / 360.0 + 0.5) & 0x3) + 2) % 4;
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, m_BlockType, 0x8 | Meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
virtual void OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
||||||
{
|
{
|
||||||
NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
@ -62,50 +62,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Single chest, get meta from rotation only
|
// Single chest, get meta from rotation only
|
||||||
a_BlockMeta = RotationToMetaData(yaw);
|
a_BlockMeta = PlayerYawToMetaData(yaw);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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
|
|
||||||
{
|
|
||||||
// Check if this forms a doublechest, if so, need to adjust the meta:
|
|
||||||
cBlockArea Area;
|
|
||||||
if (!Area.Read(&a_ChunkInterface, a_BlockX - 1, a_BlockX + 1, a_BlockY, a_BlockY, a_BlockZ - 1, a_BlockZ + 1))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
double rot = a_Player->GetYaw(); // FIXME: Rename rot to yaw
|
|
||||||
// Choose meta from player rotation, choose only between 2 or 3
|
|
||||||
NIBBLETYPE NewMeta = ((rot >= -90) && (rot < 90)) ? 2 : 3;
|
|
||||||
if (
|
|
||||||
CheckAndAdjustNeighbor(a_ChunkInterface, Area, 0, 1, NewMeta) ||
|
|
||||||
CheckAndAdjustNeighbor(a_ChunkInterface, Area, 2, 1, NewMeta)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Forming a double chest in the X direction
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Choose meta from player rotation, choose only between 4 or 5
|
|
||||||
NewMeta = (rot < 0) ? 4 : 5;
|
|
||||||
if (
|
|
||||||
CheckAndAdjustNeighbor(a_ChunkInterface, Area, 1, 0, NewMeta) ||
|
|
||||||
CheckAndAdjustNeighbor(a_ChunkInterface, Area, 2, 2, NewMeta)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Forming a double chest in the Z direction
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Single chest, no further processing needed
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||||
{
|
{
|
||||||
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
|
int BlockX = a_RelX + a_Chunk.GetPosX() * cChunkDef::Width;
|
||||||
@ -180,30 +141,30 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Translates player rotation when placing a chest into the chest block metadata. Valid for single chests only
|
/** Translates player yaw when placing a chest into the chest block metadata. Valid for single chests only */
|
||||||
static NIBBLETYPE RotationToMetaData(double a_Rotation)
|
static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
|
||||||
{
|
{
|
||||||
a_Rotation += 90 + 45; // So its not aligned with axis
|
a_Yaw += 90 + 45; // So its not aligned with axis
|
||||||
|
|
||||||
if (a_Rotation > 360.f)
|
if (a_Yaw > 360.f)
|
||||||
{
|
{
|
||||||
a_Rotation -= 360.f;
|
a_Yaw -= 360.f;
|
||||||
}
|
}
|
||||||
if ((a_Rotation >= 0.f) && (a_Rotation < 90.f))
|
if ((a_Yaw >= 0.f) && (a_Yaw < 90.f))
|
||||||
{
|
{
|
||||||
return 0x4;
|
return 0x04;
|
||||||
}
|
}
|
||||||
else if ((a_Rotation >= 180) && (a_Rotation < 270))
|
else if ((a_Yaw >= 180) && (a_Yaw < 270))
|
||||||
{
|
{
|
||||||
return 0x5;
|
return 0x05;
|
||||||
}
|
}
|
||||||
else if ((a_Rotation >= 90) && (a_Rotation < 180))
|
else if ((a_Yaw >= 90) && (a_Yaw < 180))
|
||||||
{
|
{
|
||||||
return 0x2;
|
return 0x02;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 0x3;
|
return 0x03;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ void cBlockDoorHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldIn
|
|||||||
if (OldMeta & 8)
|
if (OldMeta & 8)
|
||||||
{
|
{
|
||||||
// Was upper part of door
|
// Was upper part of door
|
||||||
if (IsDoor(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
|
if (IsDoorBlockType(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)))
|
||||||
{
|
{
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
}
|
}
|
||||||
@ -31,7 +31,7 @@ void cBlockDoorHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldIn
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Was lower part
|
// Was lower part
|
||||||
if (IsDoor(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)))
|
if (IsDoorBlockType(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ)))
|
||||||
{
|
{
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_AIR, 0);
|
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_AIR, 0);
|
||||||
}
|
}
|
||||||
@ -84,52 +84,34 @@ void cBlockDoorHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, c
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockDoorHandler::OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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
|
|
||||||
)
|
|
||||||
{
|
|
||||||
NIBBLETYPE a_TopBlockMeta = 8;
|
|
||||||
if (
|
|
||||||
((a_BlockMeta == 0) && (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1) == m_BlockType)) ||
|
|
||||||
((a_BlockMeta == 1) && (a_ChunkInterface.GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ) == m_BlockType)) ||
|
|
||||||
((a_BlockMeta == 2) && (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1) == m_BlockType)) ||
|
|
||||||
((a_BlockMeta == 3) && (a_ChunkInterface.GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ) == m_BlockType))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
a_TopBlockMeta = 9;
|
|
||||||
}
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, m_BlockType, a_TopBlockMeta);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NIBBLETYPE cBlockDoorHandler::MetaRotateCCW(NIBBLETYPE a_Meta)
|
NIBBLETYPE cBlockDoorHandler::MetaRotateCCW(NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
if (a_Meta & 0x08)
|
if (a_Meta & 0x08)
|
||||||
{
|
{
|
||||||
|
// The meta doesn't change for the top block
|
||||||
return a_Meta;
|
return a_Meta;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Rotate the bottom block
|
||||||
return super::MetaRotateCCW(a_Meta);
|
return super::MetaRotateCCW(a_Meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NIBBLETYPE cBlockDoorHandler::MetaRotateCW(NIBBLETYPE a_Meta)
|
NIBBLETYPE cBlockDoorHandler::MetaRotateCW(NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
if (a_Meta & 0x08)
|
if (a_Meta & 0x08)
|
||||||
{
|
{
|
||||||
|
// The meta doesn't change for the top block
|
||||||
return a_Meta;
|
return a_Meta;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Rotate the bottom block
|
||||||
return super::MetaRotateCW(a_Meta);
|
return super::MetaRotateCW(a_Meta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,8 +120,10 @@ NIBBLETYPE cBlockDoorHandler::MetaRotateCW(NIBBLETYPE a_Meta)
|
|||||||
|
|
||||||
NIBBLETYPE cBlockDoorHandler::MetaMirrorXY(NIBBLETYPE a_Meta)
|
NIBBLETYPE cBlockDoorHandler::MetaMirrorXY(NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
// Top bit (0x08) contains door panel type (Top/Bottom panel) Only Bottom panels contain position data
|
/*
|
||||||
// Return a_Meta if panel is a top panel (0x08 bit is set to 1)
|
Top bit (0x08) contains door block position (Top / Bottom). Only Bottom blocks contain position data
|
||||||
|
Return a_Meta if panel is a top panel (0x08 bit is set to 1)
|
||||||
|
*/
|
||||||
|
|
||||||
// Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored
|
// Note: Currently, you can not properly mirror the hinges on a double door. The orientation of the door is stored
|
||||||
// in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
|
// in only the bottom tile while the hinge position is in the top tile. This function only operates on one tile at a time,
|
||||||
|
@ -101,14 +101,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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;
|
|
||||||
|
|
||||||
|
|
||||||
virtual bool IsUseable(void) override
|
virtual bool IsUseable(void) override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -117,11 +109,20 @@ public:
|
|||||||
|
|
||||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||||
{
|
{
|
||||||
return ((a_RelY > 0) && (a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ) != E_BLOCK_AIR));
|
return ((a_RelY > 0) && CanBeOn(a_Chunk.GetBlock(a_RelX, a_RelY - 1, a_RelZ)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CanReplaceBlock(BLOCKTYPE a_BlockType)
|
/** Returns true if door can be placed on the specified block type. */
|
||||||
|
static bool CanBeOn(BLOCKTYPE a_BlockType)
|
||||||
|
{
|
||||||
|
// Vanilla refuses to place doors on transparent blocks
|
||||||
|
// We need to keep the door compatible with itself, otherwise the top half drops while the bottom half stays
|
||||||
|
return !cBlockInfo::IsTransparent(a_BlockType) || IsDoorBlockType(a_BlockType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool CanReplaceBlock(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
@ -170,8 +171,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns a vector pointing one block in the direction the door is facing (where the outside is). */
|
||||||
|
inline static Vector3i GetRelativeDirectionToOutside(NIBBLETYPE a_BlockMeta)
|
||||||
|
{
|
||||||
|
switch (a_BlockMeta & 0x03)
|
||||||
|
{
|
||||||
|
case 0: return Vector3i(-1, 0, 0); // Facing West / XM
|
||||||
|
case 1: return Vector3i( 0, 0, -1); // Facing North / ZM
|
||||||
|
case 2: return Vector3i( 1, 0, 0); // Facing East / XP
|
||||||
|
default: return Vector3i( 0, 0, 1); // Facing South / ZP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Returns true if the specified blocktype is any kind of door */
|
/** Returns true if the specified blocktype is any kind of door */
|
||||||
inline static bool IsDoor(BLOCKTYPE a_Block)
|
inline static bool IsDoorBlockType(BLOCKTYPE a_Block)
|
||||||
{
|
{
|
||||||
switch (a_Block)
|
switch (a_Block)
|
||||||
{
|
{
|
||||||
@ -193,6 +207,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns true iff the door at the specified coords is open.
|
||||||
|
The coords may point to either the top part or the bottom part of the door. */
|
||||||
static NIBBLETYPE IsOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
static NIBBLETYPE IsOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
|
NIBBLETYPE Meta = GetCompleteDoorMeta(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ);
|
||||||
@ -237,7 +253,7 @@ public:
|
|||||||
static void SetOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open)
|
static void SetOpen(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_Open)
|
||||||
{
|
{
|
||||||
BLOCKTYPE Block = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
BLOCKTYPE Block = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
if (!IsDoor(Block))
|
if (!IsDoorBlockType(Block))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,8 @@ class cBlockFireHandler :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cBlockFireHandler(BLOCKTYPE a_BlockType)
|
cBlockFireHandler(BLOCKTYPE a_BlockType)
|
||||||
: cBlockHandler(a_BlockType)
|
: cBlockHandler(a_BlockType),
|
||||||
|
XZP(0), XZM(0), Dir(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ void cBlockHandler::OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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)
|
void cBlockHandler::OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, const sSetBlock & a_BlockChange)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,15 +42,12 @@ public:
|
|||||||
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Called by cWorld::SetBlock() after the block has been set
|
/** Called by cWorld::SetBlock() after the block has been set */
|
||||||
virtual void OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
virtual void OnPlaced(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||||
|
|
||||||
/// Called by cClientHandle::HandlePlaceBlock() after the player has placed a new block. Called after OnPlaced().
|
/** Called by cPlayer::PlaceBlocks() for each block after it has been set to the world. Called after OnPlaced(). */
|
||||||
virtual void OnPlacedByPlayer(
|
virtual void OnPlacedByPlayer(
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player,
|
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, const sSetBlock & a_BlockChange
|
||||||
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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Called before the player has destroyed a block
|
/// Called before the player has destroyed a block
|
||||||
@ -96,7 +93,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
// virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
|
// virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
|
||||||
|
|
||||||
/// Called to check whether this block supports a rclk action. If it returns true, OnUse() is called
|
/** Called to check whether this block supports a rclk action.
|
||||||
|
If it returns true, OnUse() is called */
|
||||||
virtual bool IsUseable(void);
|
virtual bool IsUseable(void);
|
||||||
|
|
||||||
/** Indicates whether the client will click through this block.
|
/** Indicates whether the client will click through this block.
|
||||||
@ -109,20 +107,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool DoesIgnoreBuildCollision(void);
|
virtual bool DoesIgnoreBuildCollision(void);
|
||||||
|
|
||||||
/// <summary>Similar to DoesIgnoreBuildCollision(void), but is used for cases where block meta/player item-in-hand is needed to determine collision (thin snow)</summary>
|
/** Similar to DoesIgnoreBuildCollision(void), but is used for cases where block's meta or
|
||||||
|
player's item-in-hand is needed to determine collision (thin snow) */
|
||||||
virtual bool DoesIgnoreBuildCollision(cPlayer *, NIBBLETYPE a_Meta)
|
virtual bool DoesIgnoreBuildCollision(cPlayer *, NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
UNUSED(a_Meta);
|
UNUSED(a_Meta);
|
||||||
return DoesIgnoreBuildCollision();
|
return DoesIgnoreBuildCollision();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Returns if this block drops if it gets destroyed by an unsuitable situation. Default: true</summary>
|
/** Returns if this block drops if it gets destroyed by an unsuitable situation.
|
||||||
|
Default: true */
|
||||||
virtual bool DoesDropOnUnsuitable(void);
|
virtual bool DoesDropOnUnsuitable(void);
|
||||||
|
|
||||||
/** Called when one of the neighbors gets set; equivalent to MC block update.
|
/** Called when one of the neighbors gets set; equivalent to MC block update.
|
||||||
By default drops if position no more suitable (CanBeAt(), DoesDropOnUnsuitable(), Drop()),
|
By default drops if position no more suitable (CanBeAt(), DoesDropOnUnsuitable(), Drop()),
|
||||||
and wakes up all simulators on the block.
|
and wakes up all simulators on the block. */
|
||||||
*/
|
|
||||||
virtual void Check(cChunkInterface & ChunkInterface, cBlockPluginInterface & a_PluginInterface, int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk);
|
virtual void Check(cChunkInterface & ChunkInterface, cBlockPluginInterface & a_PluginInterface, int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk);
|
||||||
|
|
||||||
/// <summary>Rotates a given block meta counter-clockwise. Default: no change</summary>
|
/// <summary>Rotates a given block meta counter-clockwise. Default: no change</summary>
|
||||||
|
@ -12,16 +12,18 @@ class cBlockMobHeadHandler :
|
|||||||
public cBlockEntityHandler
|
public cBlockEntityHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
cBlockMobHeadHandler(BLOCKTYPE a_BlockType)
|
cBlockMobHeadHandler(BLOCKTYPE a_BlockType):
|
||||||
: cBlockEntityHandler(a_BlockType)
|
cBlockEntityHandler(a_BlockType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||||
{
|
{
|
||||||
// The drop spawn is in OnDestroyed method
|
// The drop spawn is in the OnDestroyedByPlayer method
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
virtual void OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
||||||
{
|
{
|
||||||
if (a_Player->IsGameModeCreative())
|
if (a_Player->IsGameModeCreative())
|
||||||
@ -61,202 +63,6 @@ public:
|
|||||||
|
|
||||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
|
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TrySpawnWither(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ)
|
|
||||||
{
|
|
||||||
if (a_BlockY < 2)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
class cCallback : public cBlockEntityCallback
|
|
||||||
{
|
|
||||||
bool m_IsWither;
|
|
||||||
|
|
||||||
virtual bool Item(cBlockEntity * a_BlockEntity)
|
|
||||||
{
|
|
||||||
if (a_BlockEntity->GetBlockType() != E_BLOCK_HEAD)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cMobHeadEntity * MobHeadEntity = static_cast<cMobHeadEntity*>(a_BlockEntity);
|
|
||||||
|
|
||||||
m_IsWither = (MobHeadEntity->GetType() == SKULL_TYPE_WITHER);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
cCallback () : m_IsWither(false) {}
|
|
||||||
|
|
||||||
bool IsWither(void) const { return m_IsWither; }
|
|
||||||
|
|
||||||
void Reset(void) { m_IsWither = false; }
|
|
||||||
|
|
||||||
} CallbackA, CallbackB;
|
|
||||||
|
|
||||||
class cPlayerCallback : public cPlayerListCallback
|
|
||||||
{
|
|
||||||
Vector3f m_Pos;
|
|
||||||
|
|
||||||
virtual bool Item(cPlayer * a_Player)
|
|
||||||
{
|
|
||||||
// TODO 2014-05-21 xdot: Vanilla minecraft uses an AABB check instead of a radius one
|
|
||||||
double Dist = (a_Player->GetPosition() - m_Pos).Length();
|
|
||||||
if (Dist < 50.0)
|
|
||||||
{
|
|
||||||
// If player is close, award achievement
|
|
||||||
a_Player->AwardAchievement(achSpawnWither);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
cPlayerCallback(const Vector3f & a_Pos) : m_Pos(a_Pos) {}
|
|
||||||
|
|
||||||
} PlayerCallback(Vector3f((float)a_BlockX, (float)a_BlockY, (float)a_BlockZ));
|
|
||||||
|
|
||||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, CallbackA);
|
|
||||||
|
|
||||||
if (!CallbackA.IsWither())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallbackA.Reset();
|
|
||||||
|
|
||||||
BLOCKTYPE BlockY1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
|
|
||||||
BLOCKTYPE BlockY2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ);
|
|
||||||
|
|
||||||
if ((BlockY1 != E_BLOCK_SOULSAND) || (BlockY2 != E_BLOCK_SOULSAND))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX - 1, a_BlockY, a_BlockZ, CallbackA);
|
|
||||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX + 1, a_BlockY, a_BlockZ, CallbackB);
|
|
||||||
|
|
||||||
BLOCKTYPE Block1 = a_ChunkInterface.GetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ);
|
|
||||||
BLOCKTYPE Block2 = a_ChunkInterface.GetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ);
|
|
||||||
|
|
||||||
if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither())
|
|
||||||
{
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
|
|
||||||
// Block entities
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX + 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX - 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
|
|
||||||
// Spawn the wither:
|
|
||||||
a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtWither);
|
|
||||||
|
|
||||||
// Award Achievement
|
|
||||||
a_WorldInterface.ForEachPlayer(PlayerCallback);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallbackA.Reset();
|
|
||||||
CallbackB.Reset();
|
|
||||||
|
|
||||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ - 1, CallbackA);
|
|
||||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ + 1, CallbackB);
|
|
||||||
|
|
||||||
Block1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1);
|
|
||||||
Block2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1);
|
|
||||||
|
|
||||||
if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither())
|
|
||||||
{
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
|
|
||||||
// Block entities
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ + 1, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.SetBlock(a_BlockX, a_BlockY, a_BlockZ - 1, E_BLOCK_AIR, 0);
|
|
||||||
|
|
||||||
// Spawn the wither:
|
|
||||||
a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtWither);
|
|
||||||
|
|
||||||
// Award Achievement
|
|
||||||
a_WorldInterface.ForEachPlayer(PlayerCallback);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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
|
|
||||||
{
|
|
||||||
class cCallback : public cBlockEntityCallback
|
|
||||||
{
|
|
||||||
cPlayer * m_Player;
|
|
||||||
NIBBLETYPE m_OldBlockMeta;
|
|
||||||
NIBBLETYPE m_NewBlockMeta;
|
|
||||||
|
|
||||||
virtual bool Item(cBlockEntity * a_BlockEntity)
|
|
||||||
{
|
|
||||||
if (a_BlockEntity->GetBlockType() != E_BLOCK_HEAD)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cMobHeadEntity * MobHeadEntity = static_cast<cMobHeadEntity*>(a_BlockEntity);
|
|
||||||
|
|
||||||
int Rotation = 0;
|
|
||||||
if (m_NewBlockMeta == 1)
|
|
||||||
{
|
|
||||||
Rotation = (int) floor(m_Player->GetYaw() * 16.0F / 360.0F + 0.5) & 0xF;
|
|
||||||
}
|
|
||||||
|
|
||||||
MobHeadEntity->SetType(static_cast<eMobHeadType>(m_OldBlockMeta));
|
|
||||||
MobHeadEntity->SetRotation(static_cast<eMobHeadRotation>(Rotation));
|
|
||||||
MobHeadEntity->GetWorld()->BroadcastBlockEntity(MobHeadEntity->GetPosX(), MobHeadEntity->GetPosY(), MobHeadEntity->GetPosZ());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
cCallback (cPlayer * a_CBPlayer, NIBBLETYPE a_OldBlockMeta, NIBBLETYPE a_NewBlockMeta) :
|
|
||||||
m_Player(a_CBPlayer),
|
|
||||||
m_OldBlockMeta(a_OldBlockMeta),
|
|
||||||
m_NewBlockMeta(a_NewBlockMeta)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
cCallback Callback(a_Player, a_BlockMeta, static_cast<NIBBLETYPE>(a_BlockFace));
|
|
||||||
|
|
||||||
a_BlockMeta = (NIBBLETYPE)a_BlockFace;
|
|
||||||
a_WorldInterface.DoWithBlockEntityAt(a_BlockX, a_BlockY, a_BlockZ, Callback);
|
|
||||||
a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
|
|
||||||
|
|
||||||
if (a_BlockMeta == SKULL_TYPE_WITHER)
|
|
||||||
{
|
|
||||||
static const Vector3i Coords[] =
|
|
||||||
{
|
|
||||||
Vector3i( 0, 0, 0),
|
|
||||||
Vector3i( 1, 0, 0),
|
|
||||||
Vector3i(-1, 0, 0),
|
|
||||||
Vector3i( 0, 0, 1),
|
|
||||||
Vector3i( 0, 0, -1),
|
|
||||||
};
|
|
||||||
for (size_t i = 0; i < ARRAYCOUNT(Coords); ++i)
|
|
||||||
{
|
|
||||||
if (TrySpawnWither(a_ChunkInterface, a_WorldInterface, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // for i - Coords[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,70 +17,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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
|
|
||||||
{
|
|
||||||
// Check whether the pumpkin is a part of a golem or a snowman
|
|
||||||
|
|
||||||
if (a_BlockY < 2)
|
|
||||||
{
|
|
||||||
// The pumpkin is too low for a golem / snowman
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLOCKTYPE BlockY1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ);
|
|
||||||
BLOCKTYPE BlockY2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ);
|
|
||||||
|
|
||||||
// Check for a snow golem:
|
|
||||||
if ((BlockY1 == E_BLOCK_SNOW_BLOCK) && (BlockY2 == E_BLOCK_SNOW_BLOCK))
|
|
||||||
{
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtSnowGolem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for an iron golem. First check only the body and legs, since those are the same for both orientations:
|
|
||||||
if ((BlockY1 != E_BLOCK_IRON_BLOCK) || (BlockY2 != E_BLOCK_IRON_BLOCK))
|
|
||||||
{
|
|
||||||
// One of the blocks is not an iron, no chance of a golem here
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now check both orientations for hands:
|
|
||||||
if (
|
|
||||||
(a_ChunkInterface.GetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ) == E_BLOCK_IRON_BLOCK) &&
|
|
||||||
(a_ChunkInterface.GetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ) == E_BLOCK_IRON_BLOCK)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Remove the iron blocks:
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
|
|
||||||
// Spawn the golem:
|
|
||||||
a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtIronGolem);
|
|
||||||
}
|
|
||||||
else if (
|
|
||||||
(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1) == E_BLOCK_IRON_BLOCK) &&
|
|
||||||
(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1) == E_BLOCK_IRON_BLOCK)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Remove the iron blocks:
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1, E_BLOCK_AIR, 0);
|
|
||||||
a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0);
|
|
||||||
|
|
||||||
// Spawn the golem:
|
|
||||||
a_WorldInterface.SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, mtIronGolem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual bool GetPlacementBlockTypeMeta(
|
virtual bool GetPlacementBlockTypeMeta(
|
||||||
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
||||||
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||||
|
@ -53,17 +53,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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_Player->GetClientHandle()->SendEditSign(a_BlockX, a_BlockY, a_BlockZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
|
virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override
|
||||||
{
|
{
|
||||||
return (a_Meta + 4) & 0x0f;
|
return (a_Meta + 4) & 0x0f;
|
||||||
|
@ -27,17 +27,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnPlacedByPlayer(
|
|
||||||
cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, 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_Player->GetClientHandle()->SendEditSign(a_BlockX, a_BlockY, a_BlockZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||||
{
|
{
|
||||||
int BlockX = (a_Chunk.GetPosX() * cChunkDef::Width) + a_RelX;
|
int BlockX = (a_Chunk.GetPosX() * cChunkDef::Width) + a_RelX;
|
||||||
|
@ -13,6 +13,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** When defined, each access to a cByteBuffer object is checked whether it's done in the same thread.
|
||||||
|
cByteBuffer assumes that it is not used by multiple threads at once, this macro adds a runtime check for that.
|
||||||
|
Unfortunately it is very slow, so it is disabled even for regular DEBUG builds. */
|
||||||
|
// #define DEBUG_SINGLE_THREAD_ACCESS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Try to determine endianness:
|
// Try to determine endianness:
|
||||||
#if ( \
|
#if ( \
|
||||||
defined(__i386__) || defined(__alpha__) || \
|
defined(__i386__) || defined(__alpha__) || \
|
||||||
@ -109,7 +118,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef DEBUG_SINGLE_THREAD_ACCESS
|
||||||
|
|
||||||
/** Simple RAII class that is used for checking that no two threads are using an object simultanously.
|
/** Simple RAII class that is used for checking that no two threads are using an object simultanously.
|
||||||
It requires the monitored object to provide the storage for a thread ID.
|
It requires the monitored object to provide the storage for a thread ID.
|
||||||
@ -122,7 +131,7 @@ public:
|
|||||||
{
|
{
|
||||||
ASSERT(
|
ASSERT(
|
||||||
(*a_ThreadID == std::this_thread::get_id()) || // Either the object is used by current thread...
|
(*a_ThreadID == std::this_thread::get_id()) || // Either the object is used by current thread...
|
||||||
(*a_ThreadID == std::thread::id()) // ... or by no thread at all
|
(*a_ThreadID == m_EmptyThreadID) // ... or by no thread at all
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mark as being used by this thread:
|
// Mark as being used by this thread:
|
||||||
@ -138,8 +147,13 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
/** Points to the storage used for ID of the thread using the object. */
|
/** Points to the storage used for ID of the thread using the object. */
|
||||||
std::thread::id * m_ThreadID;
|
std::thread::id * m_ThreadID;
|
||||||
|
|
||||||
|
/** The value of an unassigned thread ID, used to speed up checking. */
|
||||||
|
static std::thread::id m_EmptyThreadID;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::thread::id cSingleThreadAccessChecker::m_EmptyThreadID;
|
||||||
|
|
||||||
#define CHECK_THREAD cSingleThreadAccessChecker Checker(&m_ThreadID);
|
#define CHECK_THREAD cSingleThreadAccessChecker Checker(&m_ThreadID);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -330,12 +344,28 @@ bool cByteBuffer::ReadByte(unsigned char & a_Value)
|
|||||||
|
|
||||||
|
|
||||||
bool cByteBuffer::ReadBEShort(short & a_Value)
|
bool cByteBuffer::ReadBEShort(short & a_Value)
|
||||||
|
{
|
||||||
|
CHECK_THREAD
|
||||||
|
CheckValid();
|
||||||
|
NEEDBYTES(2);
|
||||||
|
Int16 val;
|
||||||
|
ReadBuf(&val, 2);
|
||||||
|
val = ntohs(val);
|
||||||
|
a_Value = *(reinterpret_cast<short *>(&val));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cByteBuffer::ReadBEUInt16(UInt16 & a_Value)
|
||||||
{
|
{
|
||||||
CHECK_THREAD
|
CHECK_THREAD
|
||||||
CheckValid();
|
CheckValid();
|
||||||
NEEDBYTES(2);
|
NEEDBYTES(2);
|
||||||
ReadBuf(&a_Value, 2);
|
ReadBuf(&a_Value, 2);
|
||||||
a_Value = (short)ntohs((u_short)a_Value);
|
a_Value = ntohs(a_Value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +387,20 @@ bool cByteBuffer::ReadBEInt(int & a_Value)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cByteBuffer::ReadBEUInt32(UInt32 & a_Value)
|
||||||
|
{
|
||||||
|
CHECK_THREAD
|
||||||
|
CheckValid();
|
||||||
|
NEEDBYTES(4);
|
||||||
|
ReadBuf(&a_Value, 4);
|
||||||
|
a_Value = ntohl(a_Value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cByteBuffer::ReadBEInt64(Int64 & a_Value)
|
bool cByteBuffer::ReadBEInt64(Int64 & a_Value)
|
||||||
{
|
{
|
||||||
CHECK_THREAD
|
CHECK_THREAD
|
||||||
|
@ -55,7 +55,9 @@ public:
|
|||||||
bool ReadChar (char & a_Value);
|
bool ReadChar (char & a_Value);
|
||||||
bool ReadByte (unsigned char & a_Value);
|
bool ReadByte (unsigned char & a_Value);
|
||||||
bool ReadBEShort (short & a_Value);
|
bool ReadBEShort (short & a_Value);
|
||||||
|
bool ReadBEUInt16 (UInt16 & a_Value);
|
||||||
bool ReadBEInt (int & a_Value);
|
bool ReadBEInt (int & a_Value);
|
||||||
|
bool ReadBEUInt32 (UInt32 & a_Value);
|
||||||
bool ReadBEInt64 (Int64 & a_Value);
|
bool ReadBEInt64 (Int64 & a_Value);
|
||||||
bool ReadBEFloat (float & a_Value);
|
bool ReadBEFloat (float & a_Value);
|
||||||
bool ReadBEDouble (double & a_Value);
|
bool ReadBEDouble (double & a_Value);
|
||||||
|
@ -5,6 +5,7 @@ project (MCServer)
|
|||||||
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/")
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/")
|
||||||
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include")
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/jsoncpp/include")
|
||||||
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include")
|
||||||
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libevent/include")
|
||||||
|
|
||||||
set(FOLDERS
|
set(FOLDERS
|
||||||
OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++ Bindings
|
OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++ Bindings
|
||||||
@ -323,4 +324,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} luaexpat jsoncpp polarssl zlib sqlite lua SQLiteCpp)
|
target_link_libraries(${EXECUTABLE} luaexpat jsoncpp polarssl zlib sqlite lua SQLiteCpp event_core event_extra)
|
||||||
|
@ -49,14 +49,14 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// sSetBlock:
|
// sSetBlock:
|
||||||
|
|
||||||
sSetBlock::sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) // absolute block position
|
sSetBlock::sSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta):
|
||||||
: x( a_BlockX)
|
m_RelX(a_BlockX),
|
||||||
, y( a_BlockY)
|
m_RelY(a_BlockY),
|
||||||
, z( a_BlockZ)
|
m_RelZ(a_BlockZ),
|
||||||
, BlockType( a_BlockType)
|
m_BlockType(a_BlockType),
|
||||||
, BlockMeta( a_BlockMeta)
|
m_BlockMeta(a_BlockMeta)
|
||||||
{
|
{
|
||||||
cChunkDef::AbsoluteToRelative(x, y, z, ChunkX, ChunkZ);
|
cChunkDef::AbsoluteToRelative(m_RelX, m_RelY, m_RelZ, m_ChunkX, m_ChunkZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,6 +73,7 @@ cChunk::cChunk(
|
|||||||
cAllocationPool<cChunkData::sChunkSection> & a_Pool
|
cAllocationPool<cChunkData::sChunkSection> & a_Pool
|
||||||
) :
|
) :
|
||||||
m_Presence(cpInvalid),
|
m_Presence(cpInvalid),
|
||||||
|
m_ShouldGenerateIfLoadFailed(false),
|
||||||
m_IsLightValid(false),
|
m_IsLightValid(false),
|
||||||
m_IsDirty(false),
|
m_IsDirty(false),
|
||||||
m_IsSaving(false),
|
m_IsSaving(false),
|
||||||
@ -93,6 +94,7 @@ cChunk::cChunk(
|
|||||||
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_RedstoneSimulatorData(a_World->GetRedstoneSimulator()->CreateChunkData()),
|
m_RedstoneSimulatorData(a_World->GetRedstoneSimulator()->CreateChunkData()),
|
||||||
|
m_IsRedstoneDirty(false),
|
||||||
m_AlwaysTicked(0)
|
m_AlwaysTicked(0)
|
||||||
{
|
{
|
||||||
if (a_NeighborXM != nullptr)
|
if (a_NeighborXM != nullptr)
|
||||||
@ -599,7 +601,7 @@ void cChunk::SpawnMobs(cMobSpawner& a_MobSpawner)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::Tick(float a_Dt)
|
void cChunk::Tick(std::chrono::milliseconds a_Dt)
|
||||||
{
|
{
|
||||||
BroadcastPendingBlockChanges();
|
BroadcastPendingBlockChanges();
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ public:
|
|||||||
/** Try to Spawn Monsters inside chunk */
|
/** Try to Spawn Monsters inside chunk */
|
||||||
void SpawnMobs(cMobSpawner& a_MobSpawner);
|
void SpawnMobs(cMobSpawner& a_MobSpawner);
|
||||||
|
|
||||||
void Tick(float a_Dt);
|
void Tick(std::chrono::milliseconds a_Dt);
|
||||||
|
|
||||||
/** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
|
/** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
|
||||||
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
|
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
|
||||||
|
@ -347,18 +347,32 @@ public:
|
|||||||
|
|
||||||
struct sSetBlock
|
struct sSetBlock
|
||||||
{
|
{
|
||||||
int x, y, z;
|
int m_RelX, m_RelY, m_RelZ;
|
||||||
int ChunkX, ChunkZ;
|
int m_ChunkX, m_ChunkZ;
|
||||||
BLOCKTYPE BlockType;
|
BLOCKTYPE m_BlockType;
|
||||||
NIBBLETYPE BlockMeta;
|
NIBBLETYPE m_BlockMeta;
|
||||||
|
|
||||||
sSetBlock( int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta); // absolute block position
|
sSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||||
sSetBlock(int a_ChunkX, int a_ChunkZ, int a_X, int a_Y, int a_Z, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) :
|
|
||||||
x(a_X), y(a_Y), z(a_Z),
|
sSetBlock(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) :
|
||||||
ChunkX(a_ChunkX), ChunkZ(a_ChunkZ),
|
m_RelX(a_RelX), m_RelY(a_RelY), m_RelZ(a_RelZ),
|
||||||
BlockType(a_BlockType),
|
m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ),
|
||||||
BlockMeta(a_BlockMeta)
|
m_BlockType(a_BlockType),
|
||||||
{}
|
m_BlockMeta(a_BlockMeta)
|
||||||
|
{
|
||||||
|
ASSERT((a_RelX >= 0) && (a_RelX < cChunkDef::Width));
|
||||||
|
ASSERT((a_RelZ >= 0) && (a_RelZ < cChunkDef::Width));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the absolute X coord of the stored block. */
|
||||||
|
int GetX(void) const { return m_RelX + cChunkDef::Width * m_ChunkX; }
|
||||||
|
|
||||||
|
/** Returns the absolute Y coord of the stored block.
|
||||||
|
Is the same as relative Y coords, because there's no Y relativization. */
|
||||||
|
int GetY(void) const { return m_RelY; }
|
||||||
|
|
||||||
|
/** Returns the absolute Z coord of the stored block. */
|
||||||
|
int GetZ(void) const { return m_RelZ + cChunkDef::Width * m_ChunkZ; }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<sSetBlock> sSetBlockList;
|
typedef std::list<sSetBlock> sSetBlockList;
|
||||||
@ -385,6 +399,17 @@ public:
|
|||||||
typedef std::list<cChunkCoords> cChunkCoordsList;
|
typedef std::list<cChunkCoords> cChunkCoordsList;
|
||||||
typedef std::vector<cChunkCoords> cChunkCoordsVector;
|
typedef std::vector<cChunkCoords> cChunkCoordsVector;
|
||||||
|
|
||||||
|
/** A simple hash function for chunk coords, we assume that chunk coords won't use more than 16 bits, so the hash is almost an identity.
|
||||||
|
Used for std::unordered_map<cChunkCoords, ...> */
|
||||||
|
class cChunkCoordsHash
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
size_t operator () (const cChunkCoords & a_Coords) const
|
||||||
|
{
|
||||||
|
return (static_cast<size_t>(a_Coords.m_ChunkX) << 16) ^ static_cast<size_t>(a_Coords.m_ChunkZ);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
107
src/ChunkMap.cpp
107
src/ChunkMap.cpp
@ -1101,17 +1101,17 @@ void cChunkMap::FastSetBlocks(sSetBlockList & a_BlockList)
|
|||||||
// Process all items from a_BlockList, either successfully or by placing into Failed
|
// Process all items from a_BlockList, either successfully or by placing into Failed
|
||||||
while (!a_BlockList.empty())
|
while (!a_BlockList.empty())
|
||||||
{
|
{
|
||||||
int ChunkX = a_BlockList.front().ChunkX;
|
int ChunkX = a_BlockList.front().m_ChunkX;
|
||||||
int ChunkZ = a_BlockList.front().ChunkZ;
|
int ChunkZ = a_BlockList.front().m_ChunkZ;
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
|
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ChunkZ);
|
||||||
if ((Chunk != nullptr) && Chunk->IsValid())
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
||||||
{
|
{
|
||||||
for (sSetBlockList::iterator itr = a_BlockList.begin(); itr != a_BlockList.end();)
|
for (sSetBlockList::iterator itr = a_BlockList.begin(); itr != a_BlockList.end();)
|
||||||
{
|
{
|
||||||
if ((itr->ChunkX == ChunkX) && (itr->ChunkZ == ChunkZ))
|
if ((itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ))
|
||||||
{
|
{
|
||||||
Chunk->FastSetBlock(itr->x, itr->y, itr->z, itr->BlockType, itr->BlockMeta);
|
Chunk->FastSetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
|
||||||
itr = a_BlockList.erase(itr);
|
itr = a_BlockList.erase(itr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1125,7 +1125,7 @@ void cChunkMap::FastSetBlocks(sSetBlockList & a_BlockList)
|
|||||||
// The chunk is not valid, move all blocks within this chunk to Failed
|
// The chunk is not valid, move all blocks within this chunk to Failed
|
||||||
for (sSetBlockList::iterator itr = a_BlockList.begin(); itr != a_BlockList.end();)
|
for (sSetBlockList::iterator itr = a_BlockList.begin(); itr != a_BlockList.end();)
|
||||||
{
|
{
|
||||||
if ((itr->ChunkX == ChunkX) && (itr->ChunkZ == ChunkZ))
|
if ((itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ))
|
||||||
{
|
{
|
||||||
Failed.push_back(*itr);
|
Failed.push_back(*itr);
|
||||||
itr = a_BlockList.erase(itr);
|
itr = a_BlockList.erase(itr);
|
||||||
@ -1146,6 +1146,34 @@ void cChunkMap::FastSetBlocks(sSetBlockList & a_BlockList)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunkMap::SetBlocks(const sSetBlockVector & a_Blocks)
|
||||||
|
{
|
||||||
|
cCSLock lock(m_CSLayers);
|
||||||
|
cChunkPtr chunk = nullptr;
|
||||||
|
int lastChunkX = 0x7fffffff; // Bogus coords so that chunk is updated on first pass
|
||||||
|
int lastChunkZ = 0x7fffffff;
|
||||||
|
for (auto block: a_Blocks)
|
||||||
|
{
|
||||||
|
// Update the chunk, if different from last time:
|
||||||
|
if ((block.m_ChunkX != lastChunkX) || (block.m_ChunkZ != lastChunkZ))
|
||||||
|
{
|
||||||
|
lastChunkX = block.m_ChunkX;
|
||||||
|
lastChunkZ = block.m_ChunkZ;
|
||||||
|
chunk = GetChunk(lastChunkX, lastChunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the chunk is valid, set the block:
|
||||||
|
if (chunk != nullptr)
|
||||||
|
{
|
||||||
|
chunk->SetBlock(block.m_RelX, block.m_RelY, block.m_RelZ, block.m_BlockType, block.m_BlockMeta);
|
||||||
|
}
|
||||||
|
} // for block - a_Blocks[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::CollectPickupsByPlayer(cPlayer & a_Player)
|
void cChunkMap::CollectPickupsByPlayer(cPlayer & a_Player)
|
||||||
{
|
{
|
||||||
int BlockX = (int)(a_Player.GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
|
int BlockX = (int)(a_Player.GetPosX()); // Truncating doesn't matter much; we're scanning entire chunks anyway
|
||||||
@ -1175,28 +1203,28 @@ void cChunkMap::CollectPickupsByPlayer(cPlayer & a_Player)
|
|||||||
|
|
||||||
BLOCKTYPE cChunkMap::GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
|
BLOCKTYPE cChunkMap::GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
|
int X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
|
||||||
|
int ChunkX, ChunkZ;
|
||||||
|
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
|
||||||
|
|
||||||
// First check if it isn't queued in the m_FastSetBlockQueue:
|
// First check if it isn't queued in the m_FastSetBlockQueue:
|
||||||
{
|
{
|
||||||
int X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
|
|
||||||
int ChunkX, ChunkZ;
|
|
||||||
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
|
|
||||||
cCSLock Lock(m_CSFastSetBlock);
|
cCSLock Lock(m_CSFastSetBlock);
|
||||||
for (sSetBlockList::iterator itr = m_FastSetBlockQueue.begin(); itr != m_FastSetBlockQueue.end(); ++itr)
|
for (sSetBlockList::iterator itr = m_FastSetBlockQueue.begin(); itr != m_FastSetBlockQueue.end(); ++itr)
|
||||||
{
|
{
|
||||||
if ((itr->x == X) && (itr->y == Y) && (itr->z == Z) && (itr->ChunkX == ChunkX) && (itr->ChunkZ == ChunkZ))
|
if ((itr->m_RelX == X) && (itr->m_RelY == Y) && (itr->m_RelZ == Z) && (itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ))
|
||||||
{
|
{
|
||||||
return itr->BlockType;
|
return itr->m_BlockType;
|
||||||
}
|
}
|
||||||
} // for itr - m_FastSetBlockQueue[]
|
} // for itr - m_FastSetBlockQueue[]
|
||||||
}
|
}
|
||||||
int ChunkX, ChunkZ;
|
|
||||||
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
|
// Not in the queue, query the chunk, if loaded:
|
||||||
|
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
|
cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
|
||||||
if ((Chunk != nullptr) && Chunk->IsValid())
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
||||||
{
|
{
|
||||||
return Chunk->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
|
return Chunk->GetBlock(X, Y, Z);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1207,25 +1235,28 @@ BLOCKTYPE cChunkMap::GetBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
|
|||||||
|
|
||||||
NIBBLETYPE cChunkMap::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ)
|
NIBBLETYPE cChunkMap::GetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
|
int X = a_BlockX, Y = a_BlockY, Z = a_BlockZ;
|
||||||
|
int ChunkX, ChunkZ;
|
||||||
|
cChunkDef::AbsoluteToRelative(X, Y, Z, ChunkX, ChunkZ);
|
||||||
|
|
||||||
// First check if it isn't queued in the m_FastSetBlockQueue:
|
// First check if it isn't queued in the m_FastSetBlockQueue:
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSFastSetBlock);
|
cCSLock Lock(m_CSFastSetBlock);
|
||||||
for (sSetBlockList::iterator itr = m_FastSetBlockQueue.begin(); itr != m_FastSetBlockQueue.end(); ++itr)
|
for (sSetBlockList::iterator itr = m_FastSetBlockQueue.begin(); itr != m_FastSetBlockQueue.end(); ++itr)
|
||||||
{
|
{
|
||||||
if ((itr->x == a_BlockX) && (itr->y == a_BlockY) && (itr->z == a_BlockZ))
|
if ((itr->m_RelX == X) && (itr->m_RelY == Y) && (itr->m_RelZ == Z) && (itr->m_ChunkX == ChunkX) && (itr->m_ChunkZ == ChunkZ))
|
||||||
{
|
{
|
||||||
return itr->BlockMeta;
|
return itr->m_BlockMeta;
|
||||||
}
|
}
|
||||||
} // for itr - m_FastSetBlockQueue[]
|
} // for itr - m_FastSetBlockQueue[]
|
||||||
}
|
}
|
||||||
int ChunkX, ChunkZ;
|
|
||||||
cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
|
// Not in the queue, query the chunk, if loaded:
|
||||||
|
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
cChunkPtr Chunk = GetChunk( ChunkX, ChunkZ);
|
cChunkPtr Chunk = GetChunk(ChunkX, ChunkZ);
|
||||||
if ((Chunk != nullptr) && Chunk->IsValid())
|
if ((Chunk != nullptr) && Chunk->IsValid())
|
||||||
{
|
{
|
||||||
return Chunk->GetMeta(a_BlockX, a_BlockY, a_BlockZ);
|
return Chunk->GetMeta(X, Y, Z);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1373,14 +1404,14 @@ void cChunkMap::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_Filt
|
|||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
||||||
{
|
{
|
||||||
cChunkPtr Chunk = GetChunk(itr->ChunkX, itr->ChunkZ);
|
cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (Chunk->GetBlock(itr->x, itr->y, itr->z) == a_FilterBlockType)
|
if (Chunk->GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ) == a_FilterBlockType)
|
||||||
{
|
{
|
||||||
Chunk->SetBlock(itr->x, itr->y, itr->z, itr->BlockType, itr->BlockMeta);
|
Chunk->SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1394,24 +1425,24 @@ void cChunkMap::ReplaceTreeBlocks(const sSetBlockVector & a_Blocks)
|
|||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
for (sSetBlockVector::const_iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
||||||
{
|
{
|
||||||
cChunkPtr Chunk = GetChunk(itr->ChunkX, itr->ChunkZ);
|
cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (Chunk->GetBlock(itr->x, itr->y, itr->z))
|
switch (Chunk->GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ))
|
||||||
{
|
{
|
||||||
CASE_TREE_OVERWRITTEN_BLOCKS:
|
CASE_TREE_OVERWRITTEN_BLOCKS:
|
||||||
{
|
{
|
||||||
Chunk->SetBlock(itr->x, itr->y, itr->z, itr->BlockType, itr->BlockMeta);
|
Chunk->SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case E_BLOCK_LEAVES:
|
case E_BLOCK_LEAVES:
|
||||||
case E_BLOCK_NEW_LEAVES:
|
case E_BLOCK_NEW_LEAVES:
|
||||||
{
|
{
|
||||||
if ((itr->BlockType == E_BLOCK_LOG) || (itr->BlockType == E_BLOCK_NEW_LOG))
|
if ((itr->m_BlockType == E_BLOCK_LOG) || (itr->m_BlockType == E_BLOCK_NEW_LOG))
|
||||||
{
|
{
|
||||||
Chunk->SetBlock(itr->x, itr->y, itr->z, itr->BlockType, itr->BlockMeta);
|
Chunk->SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1507,7 +1538,7 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
|
|||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
for (sSetBlockVector::iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
for (sSetBlockVector::iterator itr = a_Blocks.begin(); itr != a_Blocks.end(); ++itr)
|
||||||
{
|
{
|
||||||
cChunkPtr Chunk = GetChunk(itr->ChunkX, itr->ChunkZ);
|
cChunkPtr Chunk = GetChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||||
if ((Chunk == nullptr) || !Chunk->IsValid())
|
if ((Chunk == nullptr) || !Chunk->IsValid())
|
||||||
{
|
{
|
||||||
if (!a_ContinueOnFailure)
|
if (!a_ContinueOnFailure)
|
||||||
@ -1517,8 +1548,8 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
|
|||||||
res = false;
|
res = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
itr->BlockType = Chunk->GetBlock(itr->x, itr->y, itr->z);
|
itr->m_BlockType = Chunk->GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
|
||||||
itr->BlockMeta = Chunk->GetMeta(itr->x, itr->y, itr->z);
|
itr->m_BlockMeta = Chunk->GetMeta(itr->m_RelX, itr->m_RelY, itr->m_RelZ);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -1527,11 +1558,11 @@ bool cChunkMap::GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cChunkMap::DigBlock(int a_X, int a_Y, int a_Z)
|
bool cChunkMap::DigBlock(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
int PosX = a_X, PosY = a_Y, PosZ = a_Z, ChunkX, ChunkZ;
|
int PosX = a_BlockX, PosY = a_BlockY, PosZ = a_BlockZ, ChunkX, ChunkZ;
|
||||||
|
|
||||||
cChunkDef::AbsoluteToRelative( PosX, PosY, PosZ, ChunkX, ChunkZ);
|
cChunkDef::AbsoluteToRelative(PosX, PosY, PosZ, ChunkX, ChunkZ);
|
||||||
|
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
@ -1542,7 +1573,7 @@ bool cChunkMap::DigBlock(int a_X, int a_Y, int a_Z)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DestChunk->SetBlock(PosX, PosY, PosZ, E_BLOCK_AIR, 0);
|
DestChunk->SetBlock(PosX, PosY, PosZ, E_BLOCK_AIR, 0);
|
||||||
m_World->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z, DestChunk);
|
m_World->GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ, DestChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -2689,7 +2720,7 @@ void cChunkMap::SpawnMobs(cMobSpawner& a_MobSpawner)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::Tick(float a_Dt)
|
void cChunkMap::Tick(std::chrono::milliseconds a_Dt)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
for (cChunkLayerList::iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
for (cChunkLayerList::iterator itr = m_Layers.begin(); itr != m_Layers.end(); ++itr)
|
||||||
@ -2917,7 +2948,7 @@ void cChunkMap::cChunkLayer::SpawnMobs(cMobSpawner& a_MobSpawner)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::cChunkLayer::Tick(float a_Dt)
|
void cChunkMap::cChunkLayer::Tick(std::chrono::milliseconds a_Dt)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
for (size_t i = 0; i < ARRAYCOUNT(m_Chunks); i++)
|
||||||
{
|
{
|
||||||
|
@ -143,7 +143,13 @@ public:
|
|||||||
void FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
void FastSetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||||
|
|
||||||
void FastSetQueuedBlocks();
|
void FastSetQueuedBlocks();
|
||||||
void FastSetBlocks (sSetBlockList & a_BlockList);
|
void FastSetBlocks(sSetBlockList & a_BlockList);
|
||||||
|
|
||||||
|
/** Performs the specified single-block set operations simultaneously, as if SetBlock() was called for each item.
|
||||||
|
Is more efficient than calling SetBlock() multiple times.
|
||||||
|
If the chunk for any of the blocks is not loaded, the set operation is ignored silently. */
|
||||||
|
void SetBlocks(const sSetBlockVector & a_Blocks);
|
||||||
|
|
||||||
void CollectPickupsByPlayer(cPlayer & a_Player);
|
void CollectPickupsByPlayer(cPlayer & a_Player);
|
||||||
|
|
||||||
BLOCKTYPE GetBlock (int a_BlockX, int a_BlockY, int a_BlockZ);
|
BLOCKTYPE GetBlock (int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
@ -173,11 +179,20 @@ public:
|
|||||||
(Re)sends the chunks to their relevant clients if successful. */
|
(Re)sends the chunks to their relevant clients if successful. */
|
||||||
bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome);
|
bool SetAreaBiome(int a_MinX, int a_MaxX, int a_MinZ, int a_MaxZ, EMCSBiome a_Biome);
|
||||||
|
|
||||||
/** Retrieves block types of the specified blocks. If a chunk is not loaded, doesn't modify the block. Returns true if all blocks were read. */
|
/** Retrieves block types and metas of the specified blocks.
|
||||||
|
If a chunk is not loaded, doesn't modify the block and consults a_ContinueOnFailure whether to process the rest of the array.
|
||||||
|
Returns true if all blocks were read, false if any one failed. */
|
||||||
bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure);
|
bool GetBlocks(sSetBlockVector & a_Blocks, bool a_ContinueOnFailure);
|
||||||
|
|
||||||
bool DigBlock (int a_X, int a_Y, int a_Z);
|
/** Removes the block at the specified coords and wakes up simulators.
|
||||||
void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer * a_Player);
|
Returns false if the chunk is not loaded (and the block is not dug).
|
||||||
|
Returns true if successful. */
|
||||||
|
bool DigBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
|
|
||||||
|
/** Sends the block at the specified coords to the specified player.
|
||||||
|
Uses a blockchange packet to send the block.
|
||||||
|
If the relevant chunk isn't loaded, doesn't do anything. */
|
||||||
|
void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, cPlayer * a_Player);
|
||||||
|
|
||||||
/** Compares clients of two chunks, calls the callback accordingly */
|
/** Compares clients of two chunks, calls the callback accordingly */
|
||||||
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
void CompareChunkClients(int a_ChunkX1, int a_ChunkZ1, int a_ChunkX2, int a_ChunkZ2, cClientDiffCallback & a_Callback);
|
||||||
@ -333,7 +348,7 @@ public:
|
|||||||
/** Try to Spawn Monsters inside all Chunks */
|
/** Try to Spawn Monsters inside all Chunks */
|
||||||
void SpawnMobs(cMobSpawner& a_MobSpawner);
|
void SpawnMobs(cMobSpawner& a_MobSpawner);
|
||||||
|
|
||||||
void Tick(float a_Dt);
|
void Tick(std::chrono::milliseconds a_Dt);
|
||||||
|
|
||||||
/** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
|
/** Ticks a single block. Used by cWorld::TickQueuedBlocks() to tick the queued blocks */
|
||||||
void TickBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
void TickBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
@ -400,7 +415,7 @@ private:
|
|||||||
/** Try to Spawn Monsters inside all Chunks */
|
/** Try to Spawn Monsters inside all Chunks */
|
||||||
void SpawnMobs(cMobSpawner& a_MobSpawner);
|
void SpawnMobs(cMobSpawner& a_MobSpawner);
|
||||||
|
|
||||||
void Tick(float a_Dt);
|
void Tick(std::chrono::milliseconds a_Dt);
|
||||||
|
|
||||||
void RemoveClient(cClientHandle * a_Client);
|
void RemoveClient(cClientHandle * a_Client);
|
||||||
|
|
||||||
|
@ -1349,12 +1349,19 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
|||||||
|
|
||||||
if (ItemHandler->IsPlaceable() && (a_BlockFace != BLOCK_FACE_NONE))
|
if (ItemHandler->IsPlaceable() && (a_BlockFace != BLOCK_FACE_NONE))
|
||||||
{
|
{
|
||||||
HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
|
if (!ItemHandler->OnPlayerPlace(*World, *m_Player, Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
|
||||||
|
{
|
||||||
|
// Placement failed, bail out
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable(EquippedDamage)))
|
else if ((ItemHandler->IsFood() || ItemHandler->IsDrinkable(EquippedDamage)))
|
||||||
{
|
{
|
||||||
if ((m_Player->IsSatiated() || m_Player->IsGameModeCreative()) &&
|
if (
|
||||||
ItemHandler->IsFood() && (Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE))
|
(m_Player->IsSatiated() || m_Player->IsGameModeCreative()) && // Only creative or hungry players can eat
|
||||||
|
ItemHandler->IsFood() &&
|
||||||
|
(Equipped.m_ItemType != E_ITEM_GOLDEN_APPLE) // Golden apple is a special case, it is used instead of eaten
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// The player is satiated or in creative, and trying to eat
|
// The player is satiated or in creative, and trying to eat
|
||||||
return;
|
return;
|
||||||
@ -1382,151 +1389,6 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, e
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler)
|
|
||||||
{
|
|
||||||
BLOCKTYPE EquippedBlock = (BLOCKTYPE)(m_Player->GetEquippedItem().m_ItemType);
|
|
||||||
if (a_BlockFace < 0)
|
|
||||||
{
|
|
||||||
// Clicked in air
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cWorld * World = m_Player->GetWorld();
|
|
||||||
|
|
||||||
BLOCKTYPE ClickedBlock;
|
|
||||||
NIBBLETYPE ClickedBlockMeta;
|
|
||||||
NIBBLETYPE EquippedBlockDamage = (NIBBLETYPE)(m_Player->GetEquippedItem().m_ItemDamage);
|
|
||||||
|
|
||||||
if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
|
|
||||||
{
|
|
||||||
// The block is being placed outside the world, ignore this packet altogether (#128)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta);
|
|
||||||
|
|
||||||
// Special slab handling - placing a slab onto another slab produces a dblslab instead:
|
|
||||||
if (
|
|
||||||
cBlockSlabHandler::IsAnySlabType(ClickedBlock) && // Is there a slab already?
|
|
||||||
cBlockSlabHandler::IsAnySlabType(EquippedBlock) && // Is the player placing another slab?
|
|
||||||
((ClickedBlockMeta & 0x07) == EquippedBlockDamage) && // Is it the same slab type?
|
|
||||||
(
|
|
||||||
(a_BlockFace == BLOCK_FACE_TOP) || // Clicking the top of a bottom slab
|
|
||||||
(a_BlockFace == BLOCK_FACE_BOTTOM) // Clicking the bottom of a top slab
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Coordinates at clicked block, which was an eligible slab, and either top or bottom faces were clicked
|
|
||||||
// If clicked top face and slab occupies the top voxel, we want a slab to be placed above it (therefore increment Y)
|
|
||||||
// Else if clicked bottom face and slab occupies the bottom voxel, decrement Y for the same reason
|
|
||||||
// Don't touch coordinates if anything else because a dblslab opportunity is present
|
|
||||||
if ((ClickedBlockMeta & 0x08) && (a_BlockFace == BLOCK_FACE_TOP))
|
|
||||||
{
|
|
||||||
++a_BlockY;
|
|
||||||
}
|
|
||||||
else if (!(ClickedBlockMeta & 0x08) && (a_BlockFace == BLOCK_FACE_BOTTOM))
|
|
||||||
{
|
|
||||||
--a_BlockY;
|
|
||||||
}
|
|
||||||
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedBlockMeta);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if the block ignores build collision (water, grass etc.):
|
|
||||||
if (
|
|
||||||
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision() ||
|
|
||||||
BlockHandler(ClickedBlock)->DoesIgnoreBuildCollision(m_Player, ClickedBlockMeta)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
|
||||||
BlockHandler(ClickedBlock)->OnDestroyedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
|
||||||
|
|
||||||
if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
|
|
||||||
{
|
|
||||||
// The block is being placed outside the world, ignore this packet altogether (#128)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NIBBLETYPE PlaceMeta;
|
|
||||||
BLOCKTYPE PlaceBlock;
|
|
||||||
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, PlaceBlock, PlaceMeta);
|
|
||||||
|
|
||||||
// Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed.
|
|
||||||
// No need to do combinability (dblslab) checks, client will do that here.
|
|
||||||
if (cBlockSlabHandler::IsAnySlabType(PlaceBlock))
|
|
||||||
{
|
|
||||||
// It's a slab, don't do checks and proceed to double-slabbing
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (
|
|
||||||
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision() &&
|
|
||||||
!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision(m_Player, PlaceMeta)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Tried to place a block *into* another?
|
|
||||||
// Happens when you place a block aiming at side of block with a torch on it or stem beside it
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BLOCKTYPE BlockType;
|
|
||||||
NIBBLETYPE BlockMeta;
|
|
||||||
if (!a_ItemHandler.GetPlacementBlockTypeMeta(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
|
|
||||||
{
|
|
||||||
// Handler refused the placement, send that information back to the client:
|
|
||||||
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
|
||||||
m_Player->GetInventory().SendEquippedSlot();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cBlockHandler * NewBlock = BlockHandler(BlockType);
|
|
||||||
|
|
||||||
if (cRoot::Get()->GetPluginManager()->CallHookPlayerPlacingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
|
|
||||||
{
|
|
||||||
// A plugin doesn't agree with placing the block, revert the block on the client:
|
|
||||||
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
|
|
||||||
m_Player->GetInventory().SendEquippedSlot();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The actual block placement:
|
|
||||||
World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
|
||||||
if (!m_Player->IsGameModeCreative())
|
|
||||||
{
|
|
||||||
m_Player->GetInventory().RemoveOneEquippedItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
cChunkInterface ChunkInterface(World->GetChunkMap());
|
|
||||||
NewBlock->OnPlacedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
|
|
||||||
|
|
||||||
AString PlaceSound = cBlockInfo::GetPlaceSound(BlockType);
|
|
||||||
float Volume = 1.0f, Pitch = 0.8f;
|
|
||||||
if (PlaceSound == "dig.metal")
|
|
||||||
{
|
|
||||||
Pitch = 1.2f;
|
|
||||||
PlaceSound = "dig.stone";
|
|
||||||
}
|
|
||||||
else if (PlaceSound == "random.anvil_land")
|
|
||||||
{
|
|
||||||
Volume = 0.65f;
|
|
||||||
}
|
|
||||||
|
|
||||||
World->BroadcastSoundEffect(PlaceSound, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, Volume, Pitch);
|
|
||||||
|
|
||||||
cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::HandleChat(const AString & a_Message)
|
void cClientHandle::HandleChat(const AString & a_Message)
|
||||||
{
|
{
|
||||||
// We no longer need to postpone message processing, because the messages already arrive in the Tick thread
|
// We no longer need to postpone message processing, because the messages already arrive in the Tick thread
|
||||||
@ -1586,7 +1448,7 @@ void cClientHandle::HandlePlayerMoveLook(double a_PosX, double a_PosY, double a_
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::HandleAnimation(char a_Animation)
|
void cClientHandle::HandleAnimation(int a_Animation)
|
||||||
{
|
{
|
||||||
if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_Animation))
|
if (cPluginManager::Get()->CallHookPlayerAnimation(*m_Player, a_Animation))
|
||||||
{
|
{
|
||||||
@ -2973,7 +2835,7 @@ void cClientHandle::PacketUnknown(UInt32 a_PacketType)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::PacketError(unsigned char a_PacketType)
|
void cClientHandle::PacketError(UInt32 a_PacketType)
|
||||||
{
|
{
|
||||||
LOGERROR("Protocol error while parsing packet type 0x%02x; disconnecting client \"%s\"", a_PacketType, m_Username.c_str());
|
LOGERROR("Protocol error while parsing packet type 0x%02x; disconnecting client \"%s\"", a_PacketType, m_Username.c_str());
|
||||||
SendDisconnect("Protocol error");
|
SendDisconnect("Protocol error");
|
||||||
|
@ -251,10 +251,10 @@ public:
|
|||||||
// Calls that cProtocol descendants use to report state:
|
// Calls that cProtocol descendants use to report state:
|
||||||
void PacketBufferFull(void);
|
void PacketBufferFull(void);
|
||||||
void PacketUnknown(UInt32 a_PacketType);
|
void PacketUnknown(UInt32 a_PacketType);
|
||||||
void PacketError(unsigned char a_PacketType);
|
void PacketError(UInt32 a_PacketType);
|
||||||
|
|
||||||
// Calls that cProtocol descendants use for handling packets:
|
// Calls that cProtocol descendants use for handling packets:
|
||||||
void HandleAnimation(char a_Animation);
|
void HandleAnimation(int a_Animation);
|
||||||
|
|
||||||
/** Called when the protocol receives a MC|ItemName plugin message, indicating that the player named
|
/** Called when the protocol receives a MC|ItemName plugin message, indicating that the player named
|
||||||
an item in the anvil UI. */
|
an item in the anvil UI. */
|
||||||
@ -459,9 +459,6 @@ private:
|
|||||||
UInt32 m_ProtocolVersion;
|
UInt32 m_ProtocolVersion;
|
||||||
|
|
||||||
|
|
||||||
/** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */
|
|
||||||
void HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler);
|
|
||||||
|
|
||||||
/** Returns true if the rate block interactions is within a reasonable limit (bot protection) */
|
/** Returns true if the rate block interactions is within a reasonable limit (bot protection) */
|
||||||
bool CheckBlockInteractionsRate(void);
|
bool CheckBlockInteractionsRate(void);
|
||||||
|
|
||||||
|
@ -183,6 +183,7 @@ int cEnchantments::StringToEnchantmentID(const AString & a_EnchantmentName)
|
|||||||
{ enchRespiration, "Respiration"},
|
{ enchRespiration, "Respiration"},
|
||||||
{ enchAquaAffinity, "AquaAffinity"},
|
{ enchAquaAffinity, "AquaAffinity"},
|
||||||
{ enchThorns, "Thorns"},
|
{ enchThorns, "Thorns"},
|
||||||
|
{ enchDepthStrider, "DepthStrider"},
|
||||||
{ enchSharpness, "Sharpness"},
|
{ enchSharpness, "Sharpness"},
|
||||||
{ enchSmite, "Smite"},
|
{ enchSmite, "Smite"},
|
||||||
{ enchBaneOfArthropods, "BaneOfArthropods"},
|
{ enchBaneOfArthropods, "BaneOfArthropods"},
|
||||||
@ -506,6 +507,20 @@ void cEnchantments::AddItemEnchantmentWeights(cWeightedEnchantments & a_Enchantm
|
|||||||
{
|
{
|
||||||
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1);
|
AddEnchantmentWeightToVector(a_Enchantments, 5, enchFeatherFalling, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Depth Strider
|
||||||
|
if ((a_EnchantmentLevel >= 30) && (a_EnchantmentLevel <= 45))
|
||||||
|
{
|
||||||
|
AddEnchantmentWeightToVector(a_Enchantments, 2, enchDepthStrider, 3);
|
||||||
|
}
|
||||||
|
else if ((a_EnchantmentLevel >= 20) && (a_EnchantmentLevel <= 35))
|
||||||
|
{
|
||||||
|
AddEnchantmentWeightToVector(a_Enchantments, 2, enchDepthStrider, 2);
|
||||||
|
}
|
||||||
|
else if ((a_EnchantmentLevel >= 10) && (a_EnchantmentLevel <= 25))
|
||||||
|
{
|
||||||
|
AddEnchantmentWeightToVector(a_Enchantments, 2, enchDepthStrider, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1021,26 +1036,34 @@ cEnchantments cEnchantments::GetRandomEnchantmentFromVector(cWeightedEnchantment
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cEnchantments cEnchantments::GenerateEnchantmentFromVector(cWeightedEnchantments & a_Enchantments, int a_Seed)
|
cEnchantments cEnchantments::SelectEnchantmentFromVector(const cWeightedEnchantments & a_Enchantments, int a_Seed)
|
||||||
{
|
{
|
||||||
|
// Sum up all the enchantments' weights:
|
||||||
int AllWeights = 0;
|
int AllWeights = 0;
|
||||||
for (const auto Enchantment : a_Enchantments)
|
for (const auto Enchantment : a_Enchantments)
|
||||||
{
|
{
|
||||||
AllWeights += Enchantment.m_Weight;
|
AllWeights += Enchantment.m_Weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there's no weight for any of the enchantments, return an empty enchantment
|
||||||
|
if (AllWeights <= 0)
|
||||||
|
{
|
||||||
|
return cEnchantments();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick a random enchantment:
|
||||||
cNoise Noise(a_Seed);
|
cNoise Noise(a_Seed);
|
||||||
int RandomNumber = Noise.IntNoise1DInt(AllWeights) / 7 % AllWeights;
|
int RandomNumber = Noise.IntNoise1DInt(AllWeights) / 7 % AllWeights;
|
||||||
|
|
||||||
for (const auto Enchantment : a_Enchantments)
|
for (const auto Enchantment : a_Enchantments)
|
||||||
{
|
{
|
||||||
RandomNumber -= Enchantment.m_Weight;
|
RandomNumber -= Enchantment.m_Weight;
|
||||||
if (RandomNumber < 0)
|
if (RandomNumber <= 0)
|
||||||
{
|
{
|
||||||
return Enchantment.m_Enchantments;
|
return Enchantment.m_Enchantments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No enchantment picked, return an empty one (we probably shouldn't ever get here):
|
||||||
return cEnchantments();
|
return cEnchantments();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ public:
|
|||||||
enchRespiration = 5,
|
enchRespiration = 5,
|
||||||
enchAquaAffinity = 6,
|
enchAquaAffinity = 6,
|
||||||
enchThorns = 7,
|
enchThorns = 7,
|
||||||
|
enchDepthStrider = 8,
|
||||||
enchSharpness = 16,
|
enchSharpness = 16,
|
||||||
enchSmite = 17,
|
enchSmite = 17,
|
||||||
enchBaneOfArthropods = 18,
|
enchBaneOfArthropods = 18,
|
||||||
@ -128,8 +129,10 @@ public:
|
|||||||
/** Gets random enchantment from Vector and returns it */
|
/** Gets random enchantment from Vector and returns it */
|
||||||
static cEnchantments GetRandomEnchantmentFromVector(cWeightedEnchantments & a_Enchantments);
|
static cEnchantments GetRandomEnchantmentFromVector(cWeightedEnchantments & a_Enchantments);
|
||||||
|
|
||||||
/** Returns an enchantment from a Vector using cNoise. Mostly used for generators.*/
|
/** Selects one enchantment from a Vector using cNoise. Mostly used for generators.
|
||||||
static cEnchantments GenerateEnchantmentFromVector(cWeightedEnchantments & a_Enchantments, int a_Seed);
|
Uses the enchantments' weights for the random distribution.
|
||||||
|
If a_Enchantments is empty, returns an empty enchantment. */
|
||||||
|
static cEnchantments SelectEnchantmentFromVector(const cWeightedEnchantments & a_Enchantments, int a_Seed);
|
||||||
|
|
||||||
/** Returns true if a_Other doesn't contain exactly the same enchantments and levels */
|
/** Returns true if a_Other doesn't contain exactly the same enchantments and levels */
|
||||||
bool operator !=(const cEnchantments & a_Other) const;
|
bool operator !=(const cEnchantments & a_Other) const;
|
||||||
|
@ -174,20 +174,20 @@ void cArrowEntity::CollectedBy(cPlayer & a_Dest)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
m_Timer += a_Dt;
|
m_Timer += a_Dt;
|
||||||
|
|
||||||
if (m_bIsCollected)
|
if (m_bIsCollected)
|
||||||
{
|
{
|
||||||
if (m_Timer > 500.f) // 0.5 seconds
|
if (m_Timer > std::chrono::milliseconds(500))
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (m_Timer > 1000 * 60 * 5) // 5 minutes
|
else if (m_Timer > std::chrono::minutes(5))
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
return;
|
return;
|
||||||
@ -202,7 +202,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 > 500.f) // Send after half a second, could be less, but just in case
|
if (m_HitGroundTimer > std::chrono::milliseconds(500))
|
||||||
{
|
{
|
||||||
m_World->BroadcastTeleportEntity(*this);
|
m_World->BroadcastTeleportEntity(*this);
|
||||||
m_HasTeleported = true;
|
m_HasTeleported = true;
|
||||||
|
@ -85,10 +85,10 @@ protected:
|
|||||||
bool m_IsCritical;
|
bool m_IsCritical;
|
||||||
|
|
||||||
/** Timer for pickup collection animation or five minute timeout */
|
/** Timer for pickup collection animation or five minute timeout */
|
||||||
float m_Timer;
|
std::chrono::milliseconds m_Timer;
|
||||||
|
|
||||||
/** Timer for client arrow position confirmation via TeleportEntity */
|
/** Timer for client arrow position confirmation via TeleportEntity */
|
||||||
float m_HitGroundTimer;
|
std::chrono::milliseconds m_HitGroundTimer;
|
||||||
|
|
||||||
// Whether the arrow has already been teleported into the proper position in the ground.
|
// Whether the arrow has already been teleported into the proper position in the ground.
|
||||||
bool m_HasTeleported;
|
bool m_HasTeleported;
|
||||||
@ -103,6 +103,6 @@ protected:
|
|||||||
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 CollectedBy(cPlayer & a_Player) override;
|
virtual void CollectedBy(cPlayer & a_Player) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
}; // tolua_export
|
}; // tolua_export
|
||||||
|
@ -91,7 +91,7 @@ void cBoat::OnRightClicked(cPlayer & a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBoat::Tick(float a_Dt, cChunk & a_Chunk)
|
void cBoat::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
BroadcastMovementUpdate();
|
BroadcastMovementUpdate();
|
||||||
|
@ -27,7 +27,7 @@ public:
|
|||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||||
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
|
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override;
|
virtual void HandleSpeedFromAttachee(float a_Forward, float a_Sideways) override;
|
||||||
|
|
||||||
cBoat(double a_X, double a_Y, double a_Z);
|
cBoat(double a_X, double a_Y, double a_Z);
|
||||||
|
@ -29,7 +29,7 @@ void cEnderCrystal::SpawnOn(cClientHandle & a_ClientHandle)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEnderCrystal::Tick(float a_Dt, cChunk & a_Chunk)
|
void cEnderCrystal::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
// No further processing (physics e.t.c.) is needed
|
// No further processing (physics e.t.c.) is needed
|
||||||
|
@ -23,7 +23,7 @@ private:
|
|||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
|
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
|
||||||
|
|
||||||
}; // tolua_export
|
}; // tolua_export
|
||||||
|
@ -772,7 +772,7 @@ void cEntity::SetHealth(int a_Health)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
void cEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
m_TicksAlive++;
|
m_TicksAlive++;
|
||||||
|
|
||||||
@ -841,7 +841,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
void cEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
int BlockX = POSX_TOINT;
|
int BlockX = POSX_TOINT;
|
||||||
int BlockY = POSY_TOINT;
|
int BlockY = POSY_TOINT;
|
||||||
@ -851,15 +851,15 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, BlockX, BlockZ)
|
GET_AND_VERIFY_CURRENT_CHUNK(NextChunk, BlockX, BlockZ)
|
||||||
|
|
||||||
// TODO Add collision detection with entities.
|
// TODO Add collision detection with entities.
|
||||||
a_Dt /= 1000; // Convert from msec to sec
|
auto DtSec = std::chrono::duration_cast<std::chrono::duration<double>>(a_Dt);
|
||||||
Vector3d NextPos = Vector3d(GetPosX(), GetPosY(), GetPosZ());
|
Vector3d NextPos = Vector3d(GetPosX(), GetPosY(), GetPosZ());
|
||||||
Vector3d NextSpeed = Vector3d(GetSpeedX(), GetSpeedY(), GetSpeedZ());
|
Vector3d NextSpeed = Vector3d(GetSpeedX(), GetSpeedY(), GetSpeedZ());
|
||||||
|
|
||||||
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
|
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
|
||||||
{
|
{
|
||||||
// Outside of the world
|
// Outside of the world
|
||||||
AddSpeedY(m_Gravity * a_Dt);
|
AddSpeedY(m_Gravity * DtSec.count());
|
||||||
AddPosition(GetSpeed() * a_Dt);
|
AddPosition(GetSpeed() * DtSec.count());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -927,11 +927,11 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
if (!m_bOnGround)
|
if (!m_bOnGround)
|
||||||
{
|
{
|
||||||
float fallspeed;
|
double fallspeed;
|
||||||
if (IsBlockWater(BlockIn))
|
if (IsBlockWater(BlockIn))
|
||||||
{
|
{
|
||||||
fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water
|
fallspeed = m_Gravity * DtSec.count() / 3; // Fall 3x slower in water
|
||||||
ApplyFriction(NextSpeed, 0.7, a_Dt);
|
ApplyFriction(NextSpeed, 0.7, static_cast<float>(DtSec.count()));
|
||||||
}
|
}
|
||||||
else if (BlockIn == E_BLOCK_COBWEB)
|
else if (BlockIn == E_BLOCK_COBWEB)
|
||||||
{
|
{
|
||||||
@ -941,13 +941,13 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Normal gravity
|
// Normal gravity
|
||||||
fallspeed = m_Gravity * a_Dt;
|
fallspeed = m_Gravity * DtSec.count();
|
||||||
}
|
}
|
||||||
NextSpeed.y += fallspeed;
|
NextSpeed.y += static_cast<float>(fallspeed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ApplyFriction(NextSpeed, 0.7, a_Dt);
|
ApplyFriction(NextSpeed, 0.7, static_cast<float>(DtSec.count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
|
// Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
|
||||||
@ -1002,14 +1002,14 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
{
|
{
|
||||||
cTracer Tracer(GetWorld());
|
cTracer Tracer(GetWorld());
|
||||||
// Distance traced is an integer, so we round up from the distance we should go (Speed * Delta), else we will encounter collision detection failurse
|
// Distance traced is an integer, so we round up from the distance we should go (Speed * Delta), else we will encounter collision detection failurse
|
||||||
int DistanceToTrace = (int)(ceil((NextSpeed * a_Dt).SqrLength()) * 2);
|
int DistanceToTrace = (int)(ceil((NextSpeed * DtSec.count()).SqrLength()) * 2);
|
||||||
bool HasHit = Tracer.Trace(NextPos, NextSpeed, DistanceToTrace);
|
bool HasHit = Tracer.Trace(NextPos, NextSpeed, DistanceToTrace);
|
||||||
|
|
||||||
if (HasHit)
|
if (HasHit)
|
||||||
{
|
{
|
||||||
// Oh noez! We hit something: verify that the (hit position - current) was smaller or equal to the (position that we should travel without obstacles - current)
|
// Oh noez! We hit something: verify that the (hit position - current) was smaller or equal to the (position that we should travel without obstacles - current)
|
||||||
// This is because previously, we traced with a length that was rounded up (due to integer limitations), and in the case that something was hit, we don't want to overshoot our projected movement
|
// This is because previously, we traced with a length that was rounded up (due to integer limitations), and in the case that something was hit, we don't want to overshoot our projected movement
|
||||||
if ((Tracer.RealHit - NextPos).SqrLength() <= (NextSpeed * a_Dt).SqrLength())
|
if ((Tracer.RealHit - NextPos).SqrLength() <= (NextSpeed * DtSec.count()).SqrLength())
|
||||||
{
|
{
|
||||||
// Block hit was within our projected path
|
// Block hit was within our projected path
|
||||||
// Begin by stopping movement in the direction that we hit something. The Normal is the line perpendicular to a 2D face and in this case, stores what block face was hit through either -1 or 1.
|
// Begin by stopping movement in the direction that we hit something. The Normal is the line perpendicular to a 2D face and in this case, stores what block face was hit through either -1 or 1.
|
||||||
@ -1044,13 +1044,13 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
// and that this piece of software will come to be hailed as the epitome of performance and functionality in C++, never before seen, and of such a like that will never
|
// and that this piece of software will come to be hailed as the epitome of performance and functionality in C++, never before seen, and of such a like that will never
|
||||||
// be henceforth seen again in the time of programmers and man alike
|
// be henceforth seen again in the time of programmers and man alike
|
||||||
// </&sensationalist>
|
// </&sensationalist>
|
||||||
NextPos += (NextSpeed * a_Dt);
|
NextPos += (NextSpeed * DtSec.count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We didn't hit anything, so move =]
|
// We didn't hit anything, so move =]
|
||||||
NextPos += (NextSpeed * a_Dt);
|
NextPos += (NextSpeed * DtSec.count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,10 +326,10 @@ public:
|
|||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk);
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk);
|
||||||
|
|
||||||
/// Handles the physics of the entity - updates position based on speed, updates speed based on environment
|
/// Handles the physics of the entity - updates position based on speed, updates speed based on environment
|
||||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk);
|
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk);
|
||||||
|
|
||||||
/// Updates the state related to this entity being on fire
|
/// Updates the state related to this entity being on fire
|
||||||
virtual void TickBurning(cChunk & a_Chunk);
|
virtual void TickBurning(cChunk & a_Chunk);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward)
|
cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward)
|
||||||
: cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98)
|
: cEntity(etExpOrb, a_X, a_Y, a_Z, 0.98, 0.98)
|
||||||
, m_Reward(a_Reward)
|
, m_Reward(a_Reward)
|
||||||
, m_Timer(0.f)
|
, m_Timer(0)
|
||||||
{
|
{
|
||||||
SetMaxHealth(5);
|
SetMaxHealth(5);
|
||||||
SetHealth(5);
|
SetHealth(5);
|
||||||
@ -21,7 +21,7 @@ cExpOrb::cExpOrb(double a_X, double a_Y, double a_Z, int a_Reward)
|
|||||||
cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward)
|
cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward)
|
||||||
: cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98)
|
: cEntity(etExpOrb, a_Pos.x, a_Pos.y, a_Pos.z, 0.98, 0.98)
|
||||||
, m_Reward(a_Reward)
|
, m_Reward(a_Reward)
|
||||||
, m_Timer(0.f)
|
, m_Timer(0)
|
||||||
{
|
{
|
||||||
SetMaxHealth(5);
|
SetMaxHealth(5);
|
||||||
SetHealth(5);
|
SetHealth(5);
|
||||||
@ -42,7 +42,7 @@ void cExpOrb::SpawnOn(cClientHandle & a_Client)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
|
void cExpOrb::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
cPlayer * a_ClosestPlayer(m_World->FindClosestPlayer(Vector3f(GetPosition()), 5));
|
cPlayer * a_ClosestPlayer(m_World->FindClosestPlayer(Vector3f(GetPosition()), 5));
|
||||||
if (a_ClosestPlayer != nullptr)
|
if (a_ClosestPlayer != nullptr)
|
||||||
@ -70,7 +70,7 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
HandlePhysics(a_Dt, a_Chunk);
|
HandlePhysics(a_Dt, a_Chunk);
|
||||||
|
|
||||||
m_Timer += a_Dt;
|
m_Timer += a_Dt;
|
||||||
if (m_Timer >= 1000 * 60 * 5) // 5 minutes
|
if (m_Timer >= std::chrono::minutes(5))
|
||||||
{
|
{
|
||||||
Destroy(true);
|
Destroy(true);
|
||||||
}
|
}
|
||||||
|
@ -22,14 +22,14 @@ public:
|
|||||||
cExpOrb(const Vector3d & a_Pos, int a_Reward);
|
cExpOrb(const Vector3d & a_Pos, int a_Reward);
|
||||||
|
|
||||||
// Override functions
|
// Override functions
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
|
|
||||||
/** Returns the number of ticks that this entity has existed */
|
/** Returns the number of ticks that this entity has existed */
|
||||||
int GetAge(void) const { return (int)(m_Timer / 50); } // tolua_export
|
int GetAge(void) const { return std::chrono::duration_cast<cTickTime>(m_Timer).count(); } // tolua_export
|
||||||
|
|
||||||
/** Set the number of ticks that this entity has existed */
|
/** Set the number of ticks that this entity has existed */
|
||||||
void SetAge(int a_Age) { m_Timer = (float)(a_Age * 50); } // tolua_export
|
void SetAge(int a_Age) { m_Timer = cTickTime(a_Age); } // tolua_export
|
||||||
|
|
||||||
/** Get the exp amount */
|
/** Get the exp amount */
|
||||||
int GetReward(void) const { return m_Reward; } // tolua_export
|
int GetReward(void) const { return m_Reward; } // tolua_export
|
||||||
@ -41,5 +41,5 @@ protected:
|
|||||||
int m_Reward;
|
int m_Reward;
|
||||||
|
|
||||||
/** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
|
/** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
|
||||||
float m_Timer;
|
std::chrono::milliseconds m_Timer;
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
@ -31,7 +31,7 @@ void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
|
void cFallingBlock::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// GetWorld()->BroadcastTeleportEntity(*this); // Test position
|
// GetWorld()->BroadcastTeleportEntity(*this); // Test position
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float MilliDt = a_Dt * 0.001f;
|
float MilliDt = a_Dt.count() * 0.001f;
|
||||||
AddSpeedY(MilliDt * -9.8f);
|
AddSpeedY(MilliDt * -9.8f);
|
||||||
AddPosition(GetSpeed() * MilliDt);
|
AddPosition(GetSpeed() * MilliDt);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ public:
|
|||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BLOCKTYPE m_BlockType;
|
BLOCKTYPE m_BlockType;
|
||||||
|
@ -19,7 +19,7 @@ cFireworkEntity::cFireworkEntity(cEntity * a_Creator, double a_X, double a_Y, do
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
void cFireworkEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
|
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||||
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
|
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||||
@ -28,7 +28,7 @@ void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
if ((PosY < 0) || (PosY >= cChunkDef::Height))
|
if ((PosY < 0) || (PosY >= cChunkDef::Height))
|
||||||
{
|
{
|
||||||
AddSpeedY(1);
|
AddSpeedY(1);
|
||||||
AddPosition(GetSpeed() * (a_Dt / 1000));
|
AddPosition(GetSpeed() * (static_cast<double>(a_Dt.count()) / 1000));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,14 +53,14 @@ void cFireworkEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddSpeedY(1);
|
AddSpeedY(1);
|
||||||
AddPosition(GetSpeed() * (a_Dt / 1000));
|
AddPosition(GetSpeed() * (static_cast<double>(a_Dt.count()) / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFireworkEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
void cFireworkEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
// cProjectileEntity overrides:
|
// cProjectileEntity overrides:
|
||||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ void cFloater::SpawnOn(cClientHandle & a_Client)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFloater::Tick(float a_Dt, cChunk & a_Chunk)
|
void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
HandlePhysics(a_Dt, a_Chunk);
|
HandlePhysics(a_Dt, a_Chunk);
|
||||||
if (IsBlockWater(m_World->GetBlock((int) GetPosX(), (int) GetPosY(), (int) GetPosZ())) && m_World->GetBlockMeta((int) GetPosX(), (int) GetPosY(), (int) GetPosZ()) == 0)
|
if (IsBlockWater(m_World->GetBlock((int) GetPosX(), (int) GetPosY(), (int) GetPosZ())) && m_World->GetBlockMeta((int) GetPosX(), (int) GetPosY(), (int) GetPosZ()) == 0)
|
||||||
|
@ -21,7 +21,7 @@ public:
|
|||||||
cFloater(double a_X, double a_Y, double a_Z, Vector3d a_Speed, int a_PlayerID, int a_CountDownTime);
|
cFloater(double a_X, double a_Y, double a_Z, Vector3d a_Speed, int a_PlayerID, int a_CountDownTime);
|
||||||
|
|
||||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
bool CanPickup(void) const { return m_CanPickupItem; }
|
bool CanPickup(void) const { return m_CanPickupItem; }
|
||||||
|
@ -43,7 +43,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override {}
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override {}
|
||||||
|
|
||||||
eBlockFace m_Facing;
|
eBlockFace m_Facing;
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
void cMinecart::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead
|
if (IsDestroyed()) // Mainly to stop detector rails triggering again after minecart is dead
|
||||||
{
|
{
|
||||||
@ -178,7 +178,7 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
default: VERIFY(!"Unhandled rail type despite checking if block was rail!"); break;
|
default: VERIFY(!"Unhandled rail type despite checking if block was rail!"); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddPosition(GetSpeed() * (a_Dt / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
|
AddPosition(GetSpeed() * (static_cast<double>(a_Dt.count()) / 1000)); // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -206,7 +206,7 @@ void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
|
void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
NOTE: Please bear in mind that taking away from negatives make them even more negative,
|
NOTE: Please bear in mind that taking away from negatives make them even more negative,
|
||||||
@ -566,7 +566,7 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
|
void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt)
|
||||||
{
|
{
|
||||||
m_World->SetBlockMeta(m_DetectorRailPosition, a_RailMeta | 0x08);
|
m_World->SetBlockMeta(m_DetectorRailPosition, a_RailMeta | 0x08);
|
||||||
|
|
||||||
@ -577,7 +577,7 @@ void cMinecart::HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cMinecart::HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt)
|
void cMinecart::HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt)
|
||||||
{
|
{
|
||||||
HandleRailPhysics(a_RailMeta & 0x07, a_Dt);
|
HandleRailPhysics(a_RailMeta & 0x07, a_Dt);
|
||||||
}
|
}
|
||||||
@ -1214,7 +1214,7 @@ void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cMinecartWithFurnace::Tick(float a_Dt, cChunk & a_Chunk)
|
void cMinecartWithFurnace::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public:
|
|||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
|
virtual bool DoTakeDamage(TakeDamageInfo & TDI) override;
|
||||||
virtual void Destroyed() override;
|
virtual void Destroyed() override;
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ protected:
|
|||||||
/** Handles physics on normal rails
|
/** Handles physics on normal rails
|
||||||
For each tick, slow down on flat rails, speed up or slow down on ascending/descending rails (depending on direction), and turn on curved rails
|
For each tick, slow down on flat rails, speed up or slow down on ascending/descending rails (depending on direction), and turn on curved rails
|
||||||
*/
|
*/
|
||||||
void HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt);
|
void HandleRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt);
|
||||||
|
|
||||||
/** Handles powered rail physics
|
/** Handles powered rail physics
|
||||||
Each tick, speed up or slow down cart, depending on metadata of rail (powered or not)
|
Each tick, speed up or slow down cart, depending on metadata of rail (powered or not)
|
||||||
@ -66,10 +66,10 @@ protected:
|
|||||||
/** Handles detector rail activation
|
/** Handles detector rail activation
|
||||||
Activates detector rails when a minecart is on them. Calls HandleRailPhysics() for physics simulations
|
Activates detector rails when a minecart is on them. Calls HandleRailPhysics() for physics simulations
|
||||||
*/
|
*/
|
||||||
void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt);
|
void HandleDetectorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt);
|
||||||
|
|
||||||
/** Handles activator rails - placeholder for future implementation */
|
/** Handles activator rails - placeholder for future implementation */
|
||||||
void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt);
|
void HandleActivatorRailPhysics(NIBBLETYPE a_RailMeta, std::chrono::milliseconds a_Dt);
|
||||||
|
|
||||||
/** Snaps a mincecart to a rail's axis, resetting its speed
|
/** Snaps a mincecart to a rail's axis, resetting its speed
|
||||||
For curved rails, it changes the cart's direction as well as snapping it to axis */
|
For curved rails, it changes the cart's direction as well as snapping it to axis */
|
||||||
@ -171,7 +171,7 @@ public:
|
|||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
// Set functions.
|
// Set functions.
|
||||||
void SetIsFueled(bool a_IsFueled, int a_FueledTimeLeft = -1) {m_IsFueled = a_IsFueled; m_FueledTimeLeft = a_FueledTimeLeft;}
|
void SetIsFueled(bool a_IsFueled, int a_FueledTimeLeft = -1) {m_IsFueled = a_IsFueled; m_FueledTimeLeft = a_FueledTimeLeft;}
|
||||||
|
@ -31,7 +31,7 @@ void cPainting::SpawnOn(cClientHandle & a_Client)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPainting::Tick(float a_Dt, cChunk & a_Chunk)
|
void cPainting::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
UNUSED(a_Dt);
|
UNUSED(a_Dt);
|
||||||
UNUSED(a_Chunk);
|
UNUSED(a_Chunk);
|
||||||
|
@ -31,7 +31,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
|
virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override;
|
||||||
virtual void KilledBy(TakeDamageInfo & a_TDI) override
|
virtual void KilledBy(TakeDamageInfo & a_TDI) override
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@ cPawn::cPawn(eEntityType a_EntityType, double a_Width, double a_Height) :
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPawn::Tick(float a_Dt, cChunk & a_Chunk)
|
void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// Iterate through this entity's applied effects
|
// Iterate through this entity's applied effects
|
||||||
for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
|
for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
|
|
||||||
cPawn(eEntityType a_EntityType, double a_Width, double a_Height);
|
cPawn(eEntityType a_EntityType, double a_Width, double a_Height);
|
||||||
|
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
|
virtual void KilledBy(TakeDamageInfo & a_TDI) override;
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
@ -86,7 +86,7 @@ protected:
|
|||||||
|
|
||||||
cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */)
|
cPickup::cPickup(double a_PosX, double a_PosY, double a_PosZ, const cItem & a_Item, bool IsPlayerCreated, float a_SpeedX /* = 0.f */, float a_SpeedY /* = 0.f */, float a_SpeedZ /* = 0.f */)
|
||||||
: cEntity(etPickup, a_PosX, a_PosY, a_PosZ, 0.2, 0.2)
|
: cEntity(etPickup, a_PosX, a_PosY, a_PosZ, 0.2, 0.2)
|
||||||
, m_Timer(0.f)
|
, m_Timer(0)
|
||||||
, m_Item(a_Item)
|
, m_Item(a_Item)
|
||||||
, m_bCollected(false)
|
, m_bCollected(false)
|
||||||
, m_bIsPlayerCreated(IsPlayerCreated)
|
, m_bIsPlayerCreated(IsPlayerCreated)
|
||||||
@ -110,7 +110,7 @@ void cPickup::SpawnOn(cClientHandle & a_Client)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
|
void cPickup::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
BroadcastMovementUpdate(); // Notify clients of position
|
BroadcastMovementUpdate(); // Notify clients of position
|
||||||
@ -141,9 +141,9 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
m_bCollected = true;
|
m_bCollected = true;
|
||||||
m_Timer = 0; // We have to reset the timer.
|
m_Timer = std::chrono::milliseconds(0); // We have to reset the timer.
|
||||||
m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick.
|
m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick.
|
||||||
if (m_Timer > 500.f)
|
if (m_Timer > std::chrono::milliseconds(500))
|
||||||
{
|
{
|
||||||
Destroy(true);
|
Destroy(true);
|
||||||
return;
|
return;
|
||||||
@ -167,14 +167,14 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_Timer > 500.f) // 0.5 second
|
if (m_Timer > std::chrono::milliseconds(500)) // 0.5 second
|
||||||
{
|
{
|
||||||
Destroy(true);
|
Destroy(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Timer > 1000 * 60 * 5) // 5 minutes
|
if (m_Timer > std::chrono::minutes(5)) // 5 minutes
|
||||||
{
|
{
|
||||||
Destroy(true);
|
Destroy(true);
|
||||||
return;
|
return;
|
||||||
@ -200,7 +200,7 @@ bool cPickup::CollectedBy(cPlayer & a_Dest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Two seconds if player created the pickup (vomiting), half a second if anything else
|
// Two seconds if player created the pickup (vomiting), half a second if anything else
|
||||||
if (m_Timer < (m_bIsPlayerCreated ? 2000.f : 500.f))
|
if (m_Timer < (m_bIsPlayerCreated ? std::chrono::seconds(2) : std::chrono::milliseconds(500)))
|
||||||
{
|
{
|
||||||
// LOG("Pickup %d cannot be collected by \"%s\", because it is not old enough.", m_UniqueID, a_Dest->GetName().c_str());
|
// LOG("Pickup %d cannot be collected by \"%s\", because it is not old enough.", m_UniqueID, a_Dest->GetName().c_str());
|
||||||
return false; // Not old enough
|
return false; // Not old enough
|
||||||
@ -234,7 +234,7 @@ bool cPickup::CollectedBy(cPlayer & a_Dest)
|
|||||||
// All of the pickup has been collected, schedule the pickup for destroying
|
// All of the pickup has been collected, schedule the pickup for destroying
|
||||||
m_bCollected = true;
|
m_bCollected = true;
|
||||||
}
|
}
|
||||||
m_Timer = 0;
|
m_Timer = std::chrono::milliseconds(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,13 +34,13 @@ public:
|
|||||||
|
|
||||||
bool CollectedBy(cPlayer & a_Dest); // tolua_export
|
bool CollectedBy(cPlayer & a_Dest); // tolua_export
|
||||||
|
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
/** Returns the number of ticks that this entity has existed */
|
/** Returns the number of ticks that this entity has existed */
|
||||||
int GetAge(void) const { return static_cast<int>(m_Timer / 50); } // tolua_export
|
int GetAge(void) const { return std::chrono::duration_cast<cTickTime>(m_Timer).count(); } // tolua_export
|
||||||
|
|
||||||
/** Set the number of ticks that this entity has existed */
|
/** Set the number of ticks that this entity has existed */
|
||||||
void SetAge(int a_Age) { m_Timer = static_cast<float>(a_Age * 50); } // tolua_export
|
void SetAge(int a_Age) { m_Timer = cTickTime(a_Age); } // tolua_export
|
||||||
|
|
||||||
/** Returns true if the pickup has already been collected */
|
/** Returns true if the pickup has already been collected */
|
||||||
bool IsCollected(void) const { return m_bCollected; } // tolua_export
|
bool IsCollected(void) const { return m_bCollected; } // tolua_export
|
||||||
@ -51,7 +51,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
/** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
|
/** The number of ticks that the entity has existed / timer between collect and destroy; in msec */
|
||||||
float m_Timer;
|
std::chrono::milliseconds m_Timer;
|
||||||
|
|
||||||
cItem m_Item;
|
cItem m_Item;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#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 "Player.h"
|
#include "Player.h"
|
||||||
|
#include <unordered_map>
|
||||||
#include "../ChatColor.h"
|
#include "../ChatColor.h"
|
||||||
#include "../Server.h"
|
#include "../Server.h"
|
||||||
#include "../UI/InventoryWindow.h"
|
#include "../UI/InventoryWindow.h"
|
||||||
@ -19,6 +20,10 @@
|
|||||||
#include "../WorldStorage/StatSerializer.h"
|
#include "../WorldStorage/StatSerializer.h"
|
||||||
#include "../CompositeChat.h"
|
#include "../CompositeChat.h"
|
||||||
|
|
||||||
|
#include "../Blocks/BlockHandler.h"
|
||||||
|
#include "../Blocks/BlockSlab.h"
|
||||||
|
#include "../Blocks/ChunkInterface.h"
|
||||||
|
|
||||||
#include "../IniFile.h"
|
#include "../IniFile.h"
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
|
||||||
@ -186,7 +191,7 @@ void cPlayer::SpawnOn(cClientHandle & a_Client)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
if (m_ClientHandle != nullptr)
|
if (m_ClientHandle != nullptr)
|
||||||
{
|
{
|
||||||
@ -2168,6 +2173,97 @@ void cPlayer::LoadRank(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPlayer::PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||||
|
{
|
||||||
|
sSetBlockVector blk{{a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta}};
|
||||||
|
return PlaceBlocks(blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPlayer::SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Range)
|
||||||
|
{
|
||||||
|
// Collect the coords of all the blocks to send:
|
||||||
|
sSetBlockVector blks;
|
||||||
|
for (int y = a_BlockY - a_Range + 1; y < a_BlockY + a_Range; y++)
|
||||||
|
{
|
||||||
|
for (int z = a_BlockZ - a_Range + 1; z < a_BlockZ + a_Range; z++)
|
||||||
|
{
|
||||||
|
for (int x = a_BlockX - a_Range + 1; x < a_BlockX + a_Range; x++)
|
||||||
|
{
|
||||||
|
blks.emplace_back(x, y, z, E_BLOCK_AIR, 0); // Use fake blocktype, it will get set later on.
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // for y
|
||||||
|
|
||||||
|
// Get the values of all the blocks:
|
||||||
|
if (!m_World->GetBlocks(blks, false))
|
||||||
|
{
|
||||||
|
LOGD("%s: Cannot query all blocks, not sending an update", __FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divide the block changes by their respective chunks:
|
||||||
|
std::unordered_map<cChunkCoords, sSetBlockVector, cChunkCoordsHash> Changes;
|
||||||
|
for (const auto & blk: blks)
|
||||||
|
{
|
||||||
|
Changes[cChunkCoords(blk.m_ChunkX, blk.m_ChunkZ)].push_back(blk);
|
||||||
|
} // for blk - blks[]
|
||||||
|
blks.clear();
|
||||||
|
|
||||||
|
// Send the blocks for each affected chunk:
|
||||||
|
for (auto itr = Changes.cbegin(), end = Changes.cend(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
m_ClientHandle->SendBlockChanges(itr->first.m_ChunkX, itr->first.m_ChunkZ, itr->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
|
||||||
|
{
|
||||||
|
// Call the "placing" hooks; if any fail, abort:
|
||||||
|
cPluginManager * pm = cPluginManager::Get();
|
||||||
|
for (auto blk: a_Blocks)
|
||||||
|
{
|
||||||
|
if (pm->CallHookPlayerPlacingBlock(*this, blk))
|
||||||
|
{
|
||||||
|
// Abort - re-send all the current blocks in the a_Blocks' coords to the client:
|
||||||
|
for (auto blk2: a_Blocks)
|
||||||
|
{
|
||||||
|
m_World->SendBlockTo(blk2.GetX(), blk2.GetY(), blk2.GetZ(), this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // for blk - a_Blocks[]
|
||||||
|
|
||||||
|
// Set the blocks:
|
||||||
|
m_World->SetBlocks(a_Blocks);
|
||||||
|
|
||||||
|
// Notify the blockhandlers:
|
||||||
|
cChunkInterface ChunkInterface(m_World->GetChunkMap());
|
||||||
|
for (auto blk: a_Blocks)
|
||||||
|
{
|
||||||
|
cBlockHandler * newBlock = BlockHandler(blk.m_BlockType);
|
||||||
|
newBlock->OnPlacedByPlayer(ChunkInterface, *m_World, this, blk);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the "placed" hooks:
|
||||||
|
for (auto blk: a_Blocks)
|
||||||
|
{
|
||||||
|
pm->CallHookPlayerPlacedBlock(*this, blk);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::Detach()
|
void cPlayer::Detach()
|
||||||
{
|
{
|
||||||
super::Detach();
|
super::Detach();
|
||||||
|
@ -46,9 +46,9 @@ public:
|
|||||||
|
|
||||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
|
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
virtual void HandlePhysics(float a_Dt, cChunk &) override { UNUSED(a_Dt); }
|
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &) override { UNUSED(a_Dt); }
|
||||||
|
|
||||||
/** Returns the curently equipped weapon; empty item if none */
|
/** Returns the curently equipped weapon; empty item if none */
|
||||||
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
|
virtual cItem GetEquippedWeapon(void) const override { return m_Inventory.GetEquippedItem(); }
|
||||||
@ -440,8 +440,27 @@ public:
|
|||||||
Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */
|
Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */
|
||||||
void LoadRank(void);
|
void LoadRank(void);
|
||||||
|
|
||||||
|
/** Calls the block-placement hook and places the block in the world, unless refused by the hook.
|
||||||
|
If the hook prevents the placement, sends the current block at the specified coords back to the client.
|
||||||
|
Assumes that the block is in a currently loaded chunk.
|
||||||
|
Returns true if the block is successfully placed. */
|
||||||
|
bool PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||||
|
|
||||||
|
/** Sends the block in the specified range around the specified coord to the client
|
||||||
|
as a block change packet.
|
||||||
|
The blocks in range (a_BlockX - a_Range, a_BlockX + a_Range) are sent (NY-metric). */
|
||||||
|
void SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Range = 1);
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
|
||||||
|
/** Calls the block placement hooks and places the blocks in the world.
|
||||||
|
First the "placing" hooks for all the blocks are called, then the blocks are placed, and finally
|
||||||
|
the "placed" hooks are called.
|
||||||
|
If the any of the "placing" hooks aborts, none of the blocks are placed and the function returns false.
|
||||||
|
Returns true if all the blocks are placed.
|
||||||
|
Assumes that all the blocks are in currently loaded chunks. */
|
||||||
|
bool PlaceBlocks(const sSetBlockVector & a_Blocks);
|
||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual bool IsCrouched (void) const { return m_IsCrouched; }
|
virtual bool IsCrouched (void) const { return m_IsCrouched; }
|
||||||
virtual bool IsSprinting(void) const { return m_IsSprinting; }
|
virtual bool IsSprinting(void) const { return m_IsSprinting; }
|
||||||
|
@ -331,7 +331,7 @@ AString cProjectileEntity::GetMCAClassName(void) const
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
void cProjectileEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
|
||||||
@ -346,7 +346,7 @@ void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
void cProjectileEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
if (m_IsInGround)
|
if (m_IsInGround)
|
||||||
{
|
{
|
||||||
|
@ -118,8 +118,8 @@ protected:
|
|||||||
bool m_IsInGround;
|
bool m_IsInGround;
|
||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void SpawnOn(cClientHandle & a_Client) override;
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
|
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user