Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
029eb3d4fa
@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required (VERSION 2.8.2)
|
cmake_minimum_required (VERSION 2.8.7)
|
||||||
|
|
||||||
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
|
# Without this, the MSVC variable isn't defined for MSVC builds ( http://www.cmake.org/pipermail/cmake/2011-November/047130.html )
|
||||||
enable_language(CXX C)
|
enable_language(CXX C)
|
||||||
|
@ -8,8 +8,4 @@
|
|||||||
..\MCServer\monsters.ini
|
..\MCServer\monsters.ini
|
||||||
MCServer*debug.cmd
|
MCServer*debug.cmd
|
||||||
*.example.ini
|
*.example.ini
|
||||||
Lua-LICENSE.txt
|
ThirdPartyLicenses
|
||||||
LuaExpat-license.html
|
|
||||||
LuaSQLite3-LICENSE.txt
|
|
||||||
SQLiteCpp-LICENSE.txt
|
|
||||||
MersenneTwister-LICENSE.txt
|
|
||||||
|
@ -202,7 +202,7 @@ function Explode(Split, Player)
|
|||||||
if (#Split ~= 2) then
|
if (#Split ~= 2) then
|
||||||
-- There was more or less than one argument (excluding the "/explode" bit)
|
-- There was more or less than one argument (excluding the "/explode" bit)
|
||||||
-- Send the proper usage to the player and exit
|
-- Send the proper usage to the player and exit
|
||||||
SendMessage(Player, "Usage: /explode [playername]")
|
Player:SendMessage("Usage: /explode [playername]")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ function Explode(Split, Player)
|
|||||||
if (Explodee:GetName() == Split[2]) then
|
if (Explodee:GetName() == Split[2]) then
|
||||||
-- Create an explosion at the same position as they are; see <a href="cWorld.html">API docs</a> for further details of this function
|
-- Create an explosion at the same position as they are; see <a href="cWorld.html">API docs</a> for further details of this function
|
||||||
Player:GetWorld():DoExplosionAt(Explodee:GetPosX(), Explodee:GetPosY(), Explodee:GetPosZ(), false, esPlugin)
|
Player:GetWorld():DoExplosionAt(Explodee:GetPosX(), Explodee:GetPosY(), Explodee:GetPosZ(), false, esPlugin)
|
||||||
SendMessageSuccess(Player, Split[2] .. " was successfully exploded")
|
Player:SendMessageSuccess(Split[2] .. " was successfully exploded")
|
||||||
HasExploded = true;
|
HasExploded = true;
|
||||||
return true -- Signalize to MCS that we do not need to call this callback for any more players
|
return true -- Signalize to MCS that we do not need to call this callback for any more players
|
||||||
end
|
end
|
||||||
@ -224,7 +224,7 @@ function Explode(Split, Player)
|
|||||||
|
|
||||||
if not(HasExploded) then
|
if not(HasExploded) then
|
||||||
-- We have not broken out so far, therefore, the player must not exist, send failure
|
-- We have not broken out so far, therefore, the player must not exist, send failure
|
||||||
SendMessageFailure(Player, Split[2] .. " was not found")
|
Player:SendMessageFailure(Split[2] .. " was not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
BIN
MCServer/webadmin/files/background.gif
Normal file
BIN
MCServer/webadmin/files/background.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 57 B |
BIN
MCServer/webadmin/files/favicon.ico
Normal file
BIN
MCServer/webadmin/files/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
MCServer/webadmin/files/logo.png
Normal file
BIN
MCServer/webadmin/files/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
MCServer/webadmin/files/mc-logo.png
Normal file
BIN
MCServer/webadmin/files/mc-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
326
MCServer/webadmin/files/style.css
Normal file
326
MCServer/webadmin/files/style.css
Normal file
@ -0,0 +1,326 @@
|
|||||||
|
/* reset CSS */
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
vertical-align: baseline;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
ol, ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
blockquote, q {
|
||||||
|
quotes: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remember to define focus styles! */
|
||||||
|
:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove textarea resize at Safari */
|
||||||
|
textarea {
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remember to highlight inserts somehow! */
|
||||||
|
ins {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
del {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tables still need 'cellspacing="0"' in the markup */
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Origional from http://www.perspectived.com/
|
||||||
|
Modified by Ben Phelps
|
||||||
|
Made for FakeTruth - MCServer
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Basic ---------------------------------------- */
|
||||||
|
|
||||||
|
.clear { clear: both; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: white;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #646464;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper {
|
||||||
|
text-align: left;
|
||||||
|
width: 930px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo ---------------------------------------- */
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 15px 0 10px 5px;
|
||||||
|
width: 180px;
|
||||||
|
height: 36px;
|
||||||
|
background: url(logo.png) no-repeat left top;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a {
|
||||||
|
display: block;
|
||||||
|
width: 225px;
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 span { display: none; }
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #646464;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container ---------------------------------------- */
|
||||||
|
|
||||||
|
#containerHolder {
|
||||||
|
background: #eee;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#container {
|
||||||
|
background: #fff url(background.gif) repeat-y left top;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
width: 918px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#connectHolder {
|
||||||
|
background: #eee;
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom:8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#connect {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
background-color: #fff;
|
||||||
|
padding:5px;
|
||||||
|
width: 908px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pics {
|
||||||
|
height: 375px;
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pics img {
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
background-color: #eee;
|
||||||
|
width: 600px;
|
||||||
|
height: 375px;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Login -------------------------------------- */
|
||||||
|
|
||||||
|
#loginLogo {
|
||||||
|
margin: 0 auto;
|
||||||
|
margin-top:100px;
|
||||||
|
width: 180px;
|
||||||
|
height: 36px;
|
||||||
|
background-image: url(logo.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
#loginHolder {
|
||||||
|
background: #eee;
|
||||||
|
padding: 5px;
|
||||||
|
width: 310px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 90px;
|
||||||
|
margin-top:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#login {
|
||||||
|
padding:10px;
|
||||||
|
width: 288px;
|
||||||
|
height: 68px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
background:#fff;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sidebar ---------------------------------------- */
|
||||||
|
|
||||||
|
#sidebar {
|
||||||
|
width: 179px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .sideNav { width: 179px; }
|
||||||
|
|
||||||
|
#sidebar .sideNav li { border-bottom: 1px solid #ddd; width: 179px; }
|
||||||
|
|
||||||
|
#sidebar .sideNav li a {
|
||||||
|
display: block;
|
||||||
|
color: #646464;
|
||||||
|
background: #f6f6f6;
|
||||||
|
text-decoration: none;
|
||||||
|
height: 29px;
|
||||||
|
line-height: 29px;
|
||||||
|
padding: 0 19px;
|
||||||
|
width: 141px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar .sideNav li a:hover { background: #fdfcf6; }
|
||||||
|
|
||||||
|
#sidebar .sideNav li a.active, #sidebar .sideNav li a.active:hover {
|
||||||
|
background: #f0f7fa;
|
||||||
|
color: #c66653;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Breadcrumb ---------------------------------------- */
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
width: 718px;
|
||||||
|
float: right;
|
||||||
|
color: #646464;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 20px 0 0 0;
|
||||||
|
padding: 0 0 10px 0;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 a {
|
||||||
|
color: #646464;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 a.active { color: #c66653; }
|
||||||
|
|
||||||
|
h2 a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
|
/* Content ---------------------------------------- */
|
||||||
|
|
||||||
|
#main {
|
||||||
|
width: 700px;
|
||||||
|
float: right;
|
||||||
|
padding: 0 19px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main p {
|
||||||
|
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #5494af;
|
||||||
|
padding: 0 0 0 10px;
|
||||||
|
margin: 20px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
padding: 0 0 0 10px;
|
||||||
|
margin: 20px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main ul {
|
||||||
|
padding: 0 0 0 10px;
|
||||||
|
list-style-type: circle;
|
||||||
|
list-style-position: inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main table {
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
width: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main table tr th {
|
||||||
|
text-align: left;
|
||||||
|
background: #f6f6f6;
|
||||||
|
padding: 0px 20px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main table tr td {
|
||||||
|
background: #f6f6f6;
|
||||||
|
padding: 0px 20px;
|
||||||
|
height: 29px;
|
||||||
|
line-height: 29px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main table tr.odd td {
|
||||||
|
background: #fbfbfb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main table tr:hover td { background: #fdfcf6; }
|
||||||
|
|
||||||
|
#main table .action {
|
||||||
|
text-align: right;
|
||||||
|
padding: 0 20px 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main table tr .action a { margin: 0 0 0 10px; text-decoration: none; color: #9b9b9b; }
|
||||||
|
#main table tr:hover .action .edit { color: #c5a059; }
|
||||||
|
#main table tr:hover .action .delete { color: #a02b2b; }
|
||||||
|
#main table tr:hover .action .view { color: #55a34a; }
|
||||||
|
|
||||||
|
#main table tr:hover .action a:hover { text-decoration: underline; }
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 19px;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
background: #fbfbfb;
|
||||||
|
}
|
||||||
|
|
||||||
|
form p { margin: 0 0 14px 0; float: left; width: 100%; }
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 0 7px 0;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer ---------------------------------------- */
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
margin: 10px 0 30px 0;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 11px;
|
||||||
|
color: #9B9B9B;
|
||||||
|
padding: 0 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a { color: #9B9B9B; }
|
||||||
|
|
||||||
|
#footer a:hover { text-decoration: none; }
|
25
MCServer/webadmin/login_template.html
Normal file
25
MCServer/webadmin/login_template.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>MCServer WebAdmin - Login</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="icon" href="favicon.ico">
|
||||||
|
<style type="text/css">
|
||||||
|
header {
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<img src="mc-logo.png" alt="MCServer Logo" class="logo">
|
||||||
|
<h1>MCServer - WebAdmin</h1>
|
||||||
|
<form method="get" action="webadmin/">
|
||||||
|
<input type="submit" value="Log in">
|
||||||
|
</form>
|
||||||
|
</header>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
File diff suppressed because one or more lines are too long
@ -205,6 +205,15 @@ macro(enable_profile)
|
|||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
#this is a hack because we can't use cmake 2.8.10 because of travis
|
||||||
|
macro(get_clang_version)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_CXX_COMPILER}" "--version"
|
||||||
|
OUTPUT_VARIABLE CLANG_VERSION_OUTPUT)
|
||||||
|
string(REGEX MATCH "version ([0-9]\\.[0-9])" x ${CLANG_VERSION_OUTPUT})
|
||||||
|
set(CLANG_VERSION ${CMAKE_MATCH_1})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
macro(set_exe_flags)
|
macro(set_exe_flags)
|
||||||
# Remove disabling the maximum warning level:
|
# Remove disabling the maximum warning level:
|
||||||
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
|
# clang does not like a command line that reads -Wall -Wextra -w -Wall -Wextra and does not output any warnings
|
||||||
@ -223,17 +232,29 @@ macro(set_exe_flags)
|
|||||||
add_flags_cxx("-ffast-math")
|
add_flags_cxx("-ffast-math")
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
|
get_clang_version()
|
||||||
|
if ("${CLANG_VERSION}" VERSION_LESS 3.0)
|
||||||
|
message(FATAL_ERROR "MCServer requires clang version 3.0 or higher, version is ${CLANG_VERSION}")
|
||||||
|
endif()
|
||||||
# clang does not provide the __extern_always_inline macro and a part of libm depends on this when using fast-math
|
# clang does not provide the __extern_always_inline macro and a part of libm depends on this when using fast-math
|
||||||
add_flags_cxx("-D__extern_always_inline=inline")
|
add_flags_cxx("-D__extern_always_inline=inline")
|
||||||
add_flags_cxx("-Werror -Weverything -Wno-c++98-compat-pedantic -Wno-string-conversion")
|
add_flags_cxx("-Werror -Weverything -Wno-c++98-compat-pedantic -Wno-string-conversion")
|
||||||
add_flags_cxx("-Wno-error=switch-enum -Wno-documentation -Wno-exit-time-destructors")
|
add_flags_cxx("-Wno-error=switch-enum -Wno-exit-time-destructors")
|
||||||
add_flags_cxx("-Wno-error=sign-conversion -Wno-error=conversion -Wno-padded")
|
add_flags_cxx("-Wno-error=sign-conversion -Wno-error=conversion -Wno-padded")
|
||||||
add_flags_cxx("-Wno-error=deprecated -Wno-error=weak-vtables -Wno-error=float-equal")
|
add_flags_cxx("-Wno-error=deprecated -Wno-error=weak-vtables -Wno-error=float-equal")
|
||||||
add_flags_cxx("-Wno-error=missing-prototypes -Wno-error=non-virtual-dtor")
|
add_flags_cxx("-Wno-error=missing-prototypes -Wno-error=non-virtual-dtor")
|
||||||
add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=shadow -Wno-error=old-style-cast")
|
add_flags_cxx("-Wno-error=shadow -Wno-error=old-style-cast -Wno-error=global-constructors")
|
||||||
add_flags_cxx("-Wno-error=exit-time-destructors -Wno-error=missing-variable-declarations")
|
add_flags_cxx("-Wno-error=exit-time-destructors")
|
||||||
add_flags_cxx("-Wno-error=global-constructors -Wno-implicit-fallthrough")
|
add_flags_cxx("-Wno-weak-vtables -Wno-switch-enum")
|
||||||
add_flags_cxx("-Wno-error=extra-semi -Wno-weak-vtables -Wno-switch-enum")
|
if ("${CLANG_VERSION}" VERSION_GREATER 3.0)
|
||||||
|
# flags that are not present in 3.0
|
||||||
|
add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=missing-variable-declarations")
|
||||||
|
add_flags_cxx("-Wno-implicit-fallthrough -Wno-error=extra-semi")
|
||||||
|
endif()
|
||||||
|
if ("${CLANG_VERSION}" VERSION_GREATER 3.1)
|
||||||
|
# flags introduced in 3.2
|
||||||
|
add_flags_cxx("-Wno-documentation")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World) :
|
cSignEntity::cSignEntity(BLOCKTYPE a_BlockType, int a_X, int a_Y, int a_Z, cWorld * a_World) :
|
||||||
super(a_BlockType, a_X, a_Y, a_Z, a_World)
|
super(a_BlockType, a_X, a_Y, a_Z, a_World)
|
||||||
{
|
{
|
||||||
|
ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ cChunk::cChunk(
|
|||||||
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP,
|
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP,
|
||||||
cAllocationPool<cChunkData::sChunkSection> & a_Pool
|
cAllocationPool<cChunkData::sChunkSection> & a_Pool
|
||||||
) :
|
) :
|
||||||
m_IsValid(false),
|
m_Presence(cpInvalid),
|
||||||
m_IsLightValid(false),
|
m_IsLightValid(false),
|
||||||
m_IsDirty(false),
|
m_IsDirty(false),
|
||||||
m_IsSaving(false),
|
m_IsSaving(false),
|
||||||
@ -165,11 +165,22 @@ cChunk::~cChunk()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunk::SetValid(void)
|
void cChunk::SetPresence(cChunk::ePresence a_Presence)
|
||||||
{
|
{
|
||||||
m_IsValid = true;
|
m_Presence = a_Presence;
|
||||||
|
if (a_Presence == cpPresent)
|
||||||
m_World->GetChunkMap()->ChunkValidated();
|
{
|
||||||
|
m_World->GetChunkMap()->ChunkValidated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cChunk::SetShouldGenerateIfLoadFailed(bool a_ShouldGenerateIfLoadFailed)
|
||||||
|
{
|
||||||
|
m_ShouldGenerateIfLoadFailed = a_ShouldGenerateIfLoadFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -178,6 +189,9 @@ void cChunk::SetValid(void)
|
|||||||
|
|
||||||
void cChunk::MarkRegenerating(void)
|
void cChunk::MarkRegenerating(void)
|
||||||
{
|
{
|
||||||
|
// Set as queued again:
|
||||||
|
SetPresence(cpQueued);
|
||||||
|
|
||||||
// Tell all clients attached to this chunk that they want this chunk:
|
// Tell all clients attached to this chunk that they want this chunk:
|
||||||
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
|
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
|
||||||
{
|
{
|
||||||
@ -191,7 +205,11 @@ void cChunk::MarkRegenerating(void)
|
|||||||
|
|
||||||
bool cChunk::CanUnload(void)
|
bool cChunk::CanUnload(void)
|
||||||
{
|
{
|
||||||
return m_LoadedByClient.empty() && !m_IsDirty && (m_StayCount == 0);
|
return
|
||||||
|
m_LoadedByClient.empty() && // The chunk is not used by any client
|
||||||
|
!m_IsDirty && // The chunk has been saved properly or hasn't been touched since the load / gen
|
||||||
|
(m_StayCount == 0) && // The chunk is not in a ChunkStay
|
||||||
|
(m_Presence != cpQueued) ; // The chunk is not queued for loading / generating (otherwise multi-load / multi-gen could occur)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -223,7 +241,7 @@ void cChunk::MarkSaved(void)
|
|||||||
void cChunk::MarkLoaded(void)
|
void cChunk::MarkLoaded(void)
|
||||||
{
|
{
|
||||||
m_IsDirty = false;
|
m_IsDirty = false;
|
||||||
SetValid();
|
SetPresence(cpPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -232,12 +250,17 @@ void cChunk::MarkLoaded(void)
|
|||||||
|
|
||||||
void cChunk::MarkLoadFailed(void)
|
void cChunk::MarkLoadFailed(void)
|
||||||
{
|
{
|
||||||
if (m_IsValid)
|
ASSERT(m_Presence == cpQueued);
|
||||||
|
|
||||||
|
// If the chunk is marked as needed, generate it:
|
||||||
|
if (m_ShouldGenerateIfLoadFailed)
|
||||||
{
|
{
|
||||||
return;
|
m_World->GetGenerator().QueueGenerateChunk(m_PosX, m_PosZ, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Presence = cpInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_HasLoadFailed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -246,6 +269,8 @@ void cChunk::MarkLoadFailed(void)
|
|||||||
|
|
||||||
void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
void cChunk::GetAllData(cChunkDataCallback & a_Callback)
|
||||||
{
|
{
|
||||||
|
ASSERT(m_Presence == cpPresent);
|
||||||
|
|
||||||
a_Callback.HeightMap(&m_HeightMap);
|
a_Callback.HeightMap(&m_HeightMap);
|
||||||
a_Callback.BiomeData(&m_BiomeMap);
|
a_Callback.BiomeData(&m_BiomeMap);
|
||||||
|
|
||||||
@ -272,6 +297,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
|
|||||||
{
|
{
|
||||||
ASSERT(a_SetChunkData.IsHeightMapValid());
|
ASSERT(a_SetChunkData.IsHeightMapValid());
|
||||||
ASSERT(a_SetChunkData.AreBiomesValid());
|
ASSERT(a_SetChunkData.AreBiomesValid());
|
||||||
|
ASSERT(IsQueued());
|
||||||
|
|
||||||
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
|
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
|
||||||
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
|
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
|
||||||
@ -317,7 +343,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
|
|||||||
CreateBlockEntities();
|
CreateBlockEntities();
|
||||||
|
|
||||||
// Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize)
|
// Set the chunk data as valid. This may be needed for some simulators that perform actions upon block adding (Vaporize)
|
||||||
SetValid();
|
SetPresence(cpPresent);
|
||||||
|
|
||||||
// Wake up all simulators for their respective blocks:
|
// Wake up all simulators for their respective blocks:
|
||||||
WakeUpSimulators();
|
WakeUpSimulators();
|
||||||
@ -1319,11 +1345,11 @@ void cChunk::CreateBlockEntities(void)
|
|||||||
case E_BLOCK_JUKEBOX:
|
case E_BLOCK_JUKEBOX:
|
||||||
case E_BLOCK_FLOWER_POT:
|
case E_BLOCK_FLOWER_POT:
|
||||||
{
|
{
|
||||||
if (!HasBlockEntityAt(x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width))
|
if (!HasBlockEntityAt(x + m_PosX * Width, y, z + m_PosZ * Width))
|
||||||
{
|
{
|
||||||
m_BlockEntities.push_back(cBlockEntity::CreateByBlockType(
|
m_BlockEntities.push_back(cBlockEntity::CreateByBlockType(
|
||||||
BlockType, GetMeta(x, y, z),
|
BlockType, GetMeta(x, y, z),
|
||||||
x + m_PosX * Width, y + m_PosY * Height, z + m_PosZ * Width, m_World
|
x + m_PosX * Width, y, z + m_PosZ * Width, m_World
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3152,7 +3178,7 @@ void cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ, int & a
|
|||||||
|
|
||||||
Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ)
|
Vector3i cChunk::PositionToWorldPosition(int a_RelX, int a_RelY, int a_RelZ)
|
||||||
{
|
{
|
||||||
return Vector3i(m_PosX * Width + a_RelX, m_PosY * Height + a_RelY, m_PosZ * Width + a_RelZ);
|
return Vector3i(m_PosX * Width + a_RelX, a_RelY, m_PosZ * Width + a_RelZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
47
src/Chunk.h
47
src/Chunk.h
@ -66,6 +66,14 @@ class cChunk :
|
|||||||
public cChunkDef // The inheritance is "misused" here only to inherit the functions and constants defined in cChunkDef
|
public cChunkDef // The inheritance is "misused" here only to inherit the functions and constants defined in cChunkDef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/** Represents the presence state of the chunk */
|
||||||
|
enum ePresence
|
||||||
|
{
|
||||||
|
cpInvalid, /**< The chunk is not present at all and is not queued in the loader / generator */
|
||||||
|
cpQueued, /**< The chunk is not present, but is queued for loading / generation */
|
||||||
|
cpPresent, /**< The chunk is present */
|
||||||
|
};
|
||||||
|
|
||||||
cChunk(
|
cChunk(
|
||||||
int a_ChunkX, int a_ChunkZ, // Chunk coords
|
int a_ChunkX, int a_ChunkZ, // Chunk coords
|
||||||
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
|
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
|
||||||
@ -75,11 +83,25 @@ public:
|
|||||||
cChunk(cChunk & other);
|
cChunk(cChunk & other);
|
||||||
~cChunk();
|
~cChunk();
|
||||||
|
|
||||||
bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk block data is valid (loaded / generated)
|
/** Returns true iff the chunk block data is valid (loaded / generated) */
|
||||||
void SetValid(void); // Also wakes up any calls to cChunkMap::GetHeight()
|
bool IsValid(void) const {return (m_Presence == cpPresent); }
|
||||||
void MarkRegenerating(void); // Marks all clients attached to this chunk as wanting this chunk
|
|
||||||
bool IsDirty(void) const {return m_IsDirty; } // Returns true if the chunk has changed since it was last saved
|
/** Returns true iff the chunk is in the queue for loading / generating */
|
||||||
bool HasLoadFailed(void) const {return m_HasLoadFailed; } // Returns true if the chunk failed to load and hasn't been generated since then
|
bool IsQueued(void) const {return (m_Presence == cpQueued); }
|
||||||
|
|
||||||
|
/** Sets the chunk's presence.
|
||||||
|
Wakes up any calls to cChunkMap::GetHeight() when setting to cpPresent. */
|
||||||
|
void SetPresence(ePresence a_Presence);
|
||||||
|
|
||||||
|
/** Called to indicate whether the chunk should be queued in the generator if it fails to load. Set by cChunkMap::GetChunk(). */
|
||||||
|
void SetShouldGenerateIfLoadFailed(bool a_ShouldGenerateIfLoadFailed);
|
||||||
|
|
||||||
|
/** Marks all clients attached to this chunk as wanting this chunk. Also sets presence to cpQueued. */
|
||||||
|
void MarkRegenerating(void);
|
||||||
|
|
||||||
|
/** Returns true iff the chunk has changed since it was last saved. */
|
||||||
|
bool IsDirty(void) const {return m_IsDirty; }
|
||||||
|
|
||||||
bool CanUnload(void);
|
bool CanUnload(void);
|
||||||
|
|
||||||
bool IsLightValid(void) const {return m_IsLightValid; }
|
bool IsLightValid(void) const {return m_IsLightValid; }
|
||||||
@ -94,7 +116,10 @@ public:
|
|||||||
void MarkSaving(void); // Marks the chunk as being saved.
|
void MarkSaving(void); // Marks the chunk as being saved.
|
||||||
void MarkSaved(void); // Marks the chunk as saved, if it didn't change from the last call to MarkSaving()
|
void MarkSaved(void); // Marks the chunk as saved, if it didn't change from the last call to MarkSaving()
|
||||||
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
|
void MarkLoaded(void); // Marks the chunk as freshly loaded. Fails if the chunk is already valid
|
||||||
void MarkLoadFailed(void); // Marks the chunk as failed to load. Ignored is the chunk is already valid
|
|
||||||
|
/** Marks the chunk as failed to load.
|
||||||
|
If m_ShouldGenerateIfLoadFailed is set, queues the chunk for generating. */
|
||||||
|
void MarkLoadFailed(void);
|
||||||
|
|
||||||
/** Gets all chunk data, calls the a_Callback's methods for each data type */
|
/** Gets all chunk data, calls the a_Callback's methods for each data type */
|
||||||
void GetAllData(cChunkDataCallback & a_Callback);
|
void GetAllData(cChunkDataCallback & a_Callback);
|
||||||
@ -135,7 +160,6 @@ public:
|
|||||||
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
|
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
|
||||||
|
|
||||||
int GetPosX(void) const { return m_PosX; }
|
int GetPosX(void) const { return m_PosX; }
|
||||||
int GetPosY(void) const { return m_PosY; }
|
|
||||||
int GetPosZ(void) const { return m_PosZ; }
|
int GetPosZ(void) const { return m_PosZ; }
|
||||||
|
|
||||||
cWorld * GetWorld(void) const { return m_World; }
|
cWorld * GetWorld(void) const { return m_World; }
|
||||||
@ -434,7 +458,12 @@ private:
|
|||||||
typedef std::vector<sSetBlockQueueItem> sSetBlockQueueVector;
|
typedef std::vector<sSetBlockQueueItem> sSetBlockQueueVector;
|
||||||
|
|
||||||
|
|
||||||
bool m_IsValid; // True if the chunk is loaded / generated
|
/** Holds the presence status of the chunk - if it is present, or in the loader / generator queue, or unloaded */
|
||||||
|
ePresence m_Presence;
|
||||||
|
|
||||||
|
/** If the chunk fails to load, should it be queued in the generator or reset back to invalid? */
|
||||||
|
bool m_ShouldGenerateIfLoadFailed;
|
||||||
|
|
||||||
bool m_IsLightValid; // True if the blocklight and skylight are calculated
|
bool m_IsLightValid; // True if the blocklight and skylight are calculated
|
||||||
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
bool m_IsDirty; // True if the chunk has changed since it was last saved
|
||||||
bool m_IsSaving; // True if the chunk is being saved
|
bool m_IsSaving; // True if the chunk is being saved
|
||||||
@ -453,7 +482,7 @@ private:
|
|||||||
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
|
/** Number of times the chunk has been requested to stay (by various cChunkStay objects); if zero, the chunk can be unloaded */
|
||||||
int m_StayCount;
|
int m_StayCount;
|
||||||
|
|
||||||
int m_PosX, m_PosY, m_PosZ;
|
int m_PosX, m_PosZ;
|
||||||
cWorld * m_World;
|
cWorld * m_World;
|
||||||
cChunkMap * m_ChunkMap;
|
cChunkMap * m_ChunkMap;
|
||||||
|
|
||||||
|
@ -145,10 +145,9 @@ cChunkMap::cChunkLayer * cChunkMap::GetLayerForChunk(int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
// No need to lock m_CSLayers, since it's already locked by the operation that called us
|
ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
|
||||||
ASSERT(m_CSLayers.IsLockedByCurrentThread());
|
|
||||||
|
|
||||||
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
cChunkLayer * Layer = GetLayerForChunk(a_ChunkX, a_ChunkZ);
|
||||||
if (Layer == NULL)
|
if (Layer == NULL)
|
||||||
{
|
{
|
||||||
// An error must have occurred, since layers are automatically created if they don't exist
|
// An error must have occurred, since layers are automatically created if they don't exist
|
||||||
@ -160,9 +159,11 @@ cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(Chunk->IsValid()))
|
if (!Chunk->IsValid() && !Chunk->IsQueued())
|
||||||
{
|
{
|
||||||
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ, true);
|
Chunk->SetPresence(cChunk::cpQueued);
|
||||||
|
Chunk->SetShouldGenerateIfLoadFailed(true);
|
||||||
|
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ);
|
||||||
}
|
}
|
||||||
return Chunk;
|
return Chunk;
|
||||||
}
|
}
|
||||||
@ -171,10 +172,11 @@ cChunkPtr cChunkMap::GetChunk(int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkZ)
|
cChunkPtr cChunkMap::GetChunkNoGen(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
// No need to lock m_CSLayers, since it's already locked by the operation that called us
|
ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
|
||||||
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
|
||||||
|
cChunkLayer * Layer = GetLayerForChunk(a_ChunkX, a_ChunkZ);
|
||||||
if (Layer == NULL)
|
if (Layer == NULL)
|
||||||
{
|
{
|
||||||
// An error must have occurred, since layers are automatically created if they don't exist
|
// An error must have occurred, since layers are automatically created if they don't exist
|
||||||
@ -186,9 +188,10 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkZ)
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!(Chunk->IsValid()))
|
if (!Chunk->IsValid() && !Chunk->IsQueued())
|
||||||
{
|
{
|
||||||
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ, false);
|
Chunk->SetPresence(cChunk::cpQueued);
|
||||||
|
m_World->GetStorage().QueueLoadChunk(a_ChunkX, a_ChunkZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Chunk;
|
return Chunk;
|
||||||
@ -200,7 +203,8 @@ cChunkPtr cChunkMap::GetChunkNoGen( int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkZ)
|
cChunkPtr cChunkMap::GetChunkNoLoad( int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
// No need to lock m_CSLayers, since it's already locked by the operation that called us
|
ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
|
||||||
|
|
||||||
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
|
||||||
if (Layer == NULL)
|
if (Layer == NULL)
|
||||||
{
|
{
|
||||||
@ -1009,6 +1013,17 @@ bool cChunkMap::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blo
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cChunkMap::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSLayers);
|
||||||
|
cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, a_ChunkZ);
|
||||||
|
return (Chunk != NULL) && Chunk->IsQueued();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
@ -2332,48 +2347,6 @@ void cChunkMap::TouchChunk(int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Loads the chunk synchronously, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before)
|
|
||||||
bool cChunkMap::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
cCSLock Lock(m_CSLayers);
|
|
||||||
cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkZ);
|
|
||||||
if (Chunk == NULL)
|
|
||||||
{
|
|
||||||
// Internal error
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (Chunk->IsValid())
|
|
||||||
{
|
|
||||||
// Already loaded
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (Chunk->HasLoadFailed())
|
|
||||||
{
|
|
||||||
// Already tried loading and it failed
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m_World->GetStorage().LoadChunk(a_ChunkX, a_ChunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid()
|
|
||||||
void cChunkMap::LoadChunks(const cChunkCoordsList & a_Chunks)
|
|
||||||
{
|
|
||||||
for (cChunkCoordsList::const_iterator itr = a_Chunks.begin(); itr != a_Chunks.end(); ++itr)
|
|
||||||
{
|
|
||||||
LoadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
|
||||||
} // for itr - a_Chunks[]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
void cChunkMap::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSLayers);
|
cCSLock Lock(m_CSLayers);
|
||||||
|
@ -133,6 +133,9 @@ public:
|
|||||||
/** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
|
/** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
|
||||||
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
|
bool GetChunkBlockTypes (int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_Blocks);
|
||||||
|
|
||||||
|
/** Returns true iff the chunk is in the loader / generator queue. */
|
||||||
|
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
|
bool IsChunkValid (int a_ChunkX, int a_ChunkZ);
|
||||||
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ);
|
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkZ);
|
||||||
int GetHeight (int a_BlockX, int a_BlockZ); // Waits for the chunk to get loaded / generated
|
int GetHeight (int a_BlockX, int a_BlockZ); // Waits for the chunk to get loaded / generated
|
||||||
@ -278,12 +281,6 @@ public:
|
|||||||
/** Touches the chunk, causing it to be loaded or generated */
|
/** Touches the chunk, causing it to be loaded or generated */
|
||||||
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
/** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
|
|
||||||
bool LoadChunk(int a_ChunkX, int a_ChunkZ);
|
|
||||||
|
|
||||||
/** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
|
|
||||||
void LoadChunks(const cChunkCoordsList & a_Chunks);
|
|
||||||
|
|
||||||
/** Marks the chunk as failed-to-load */
|
/** Marks the chunk as failed-to-load */
|
||||||
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
|
@ -1670,7 +1670,11 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
|||||||
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
|
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
|
||||||
|
|
||||||
m_LoadedWorldName = root.get("world", "world").asString();
|
m_LoadedWorldName = root.get("world", "world").asString();
|
||||||
a_World = cRoot::Get()->GetWorld(GetLoadedWorldName(), true);
|
a_World = cRoot::Get()->GetWorld(GetLoadedWorldName(), false);
|
||||||
|
if (a_World == NULL)
|
||||||
|
{
|
||||||
|
a_World = cRoot::Get()->GetDefaultWorld();
|
||||||
|
}
|
||||||
|
|
||||||
m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt();
|
m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt();
|
||||||
m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
|
m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
|
||||||
|
@ -227,7 +227,7 @@ cBioGenMulticache::cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_Cache
|
|||||||
|
|
||||||
cBioGenMulticache::~cBioGenMulticache()
|
cBioGenMulticache::~cBioGenMulticache()
|
||||||
{
|
{
|
||||||
for (std::vector<cBiomeGen*>::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
|
for (cBiomeGens::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
|
||||||
{
|
{
|
||||||
delete *it;
|
delete *it;
|
||||||
}
|
}
|
||||||
@ -251,7 +251,7 @@ void cBioGenMulticache::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMa
|
|||||||
|
|
||||||
void cBioGenMulticache::InitializeBiomeGen(cIniFile & a_IniFile)
|
void cBioGenMulticache::InitializeBiomeGen(cIniFile & a_IniFile)
|
||||||
{
|
{
|
||||||
for (std::vector<cBiomeGen*>::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
|
for (cBiomeGens::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
|
||||||
{
|
{
|
||||||
cBiomeGen * tmp = *it;
|
cBiomeGen * tmp = *it;
|
||||||
tmp->InitializeBiomeGen(a_IniFile);
|
tmp->InitializeBiomeGen(a_IniFile);
|
||||||
|
@ -87,16 +87,20 @@ class cBioGenMulticache :
|
|||||||
typedef cBiomeGen super;
|
typedef cBiomeGen super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
a_CacheSize defines the size of each singular cache
|
a_CacheSize defines the size of each singular cache
|
||||||
a_CachesLength defines how many caches are used for the multicache
|
a_CachesLength defines how many caches are used for the multicache
|
||||||
*/
|
*/
|
||||||
cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_CacheSize, size_t a_CachesLength); // Doesn't take ownership of a_BioGenToCache
|
cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_CacheSize, size_t a_CachesLength); // Doesn't take ownership of a_BioGenToCache
|
||||||
~cBioGenMulticache();
|
~cBioGenMulticache();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t m_CachesLength;
|
typedef std::vector<cBiomeGen *> cBiomeGens;
|
||||||
std::vector<cBiomeGen*> m_Caches;
|
|
||||||
|
|
||||||
|
size_t m_CachesLength;
|
||||||
|
cBiomeGens m_Caches;
|
||||||
|
|
||||||
|
|
||||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
|
||||||
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
|
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
|
||||||
|
@ -112,6 +112,8 @@ void cChunkGenerator::Stop(void)
|
|||||||
|
|
||||||
void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate)
|
void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate)
|
||||||
{
|
{
|
||||||
|
ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CS);
|
cCSLock Lock(m_CS);
|
||||||
|
|
||||||
@ -283,7 +285,8 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ)
|
|||||||
{
|
{
|
||||||
ASSERT(m_PluginInterface != NULL);
|
ASSERT(m_PluginInterface != NULL);
|
||||||
ASSERT(m_ChunkSink != NULL);
|
ASSERT(m_ChunkSink != NULL);
|
||||||
|
ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
|
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
|
||||||
m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
|
m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
|
||||||
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
|
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
|
||||||
|
@ -106,6 +106,10 @@ public:
|
|||||||
If this callback returns false, the chunk is not generated.
|
If this callback returns false, the chunk is not generated.
|
||||||
*/
|
*/
|
||||||
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0;
|
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0;
|
||||||
|
|
||||||
|
/** Called to check whether the specified chunk is in the queued state.
|
||||||
|
Currently used only in Debug-mode asserts. */
|
||||||
|
virtual bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) = 0;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -230,29 +230,30 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
|
|||||||
|
|
||||||
// Add a cache, if requested:
|
// Add a cache, if requested:
|
||||||
int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 64);
|
int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 64);
|
||||||
int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 4);
|
|
||||||
|
|
||||||
if (CacheSize > 0)
|
if (CacheSize <= 0)
|
||||||
{
|
{
|
||||||
if (CacheSize < 4)
|
return;
|
||||||
{
|
}
|
||||||
LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
|
|
||||||
CacheSize, 4
|
int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 4);
|
||||||
);
|
if (CacheSize < 4)
|
||||||
CacheSize = 4;
|
{
|
||||||
}
|
LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
|
||||||
LOGD("Using a cache for biomegen of size %d.", CacheSize);
|
CacheSize, 4
|
||||||
m_UnderlyingBiomeGen = m_BiomeGen;
|
);
|
||||||
if (MultiCacheLength > 0)
|
CacheSize = 4;
|
||||||
{
|
}
|
||||||
LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength);
|
LOGD("Using a cache for biomegen of size %d.", CacheSize);
|
||||||
m_BiomeGen = new cBioGenMulticache(m_UnderlyingBiomeGen, CacheSize, MultiCacheLength);
|
m_UnderlyingBiomeGen = m_BiomeGen;
|
||||||
}
|
if (MultiCacheLength > 0)
|
||||||
else
|
{
|
||||||
{
|
LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength);
|
||||||
m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize);
|
m_BiomeGen = new cBioGenMulticache(m_UnderlyingBiomeGen, CacheSize, MultiCacheLength);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1355,6 +1355,7 @@ void cProtocol172::SendUpdateBlockEntity(cBlockEntity & a_BlockEntity)
|
|||||||
void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
|
void cProtocol172::SendUpdateSign(int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4)
|
||||||
{
|
{
|
||||||
ASSERT(m_State == 3); // In game mode?
|
ASSERT(m_State == 3); // In game mode?
|
||||||
|
ASSERT((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height));
|
||||||
|
|
||||||
cPacketizer Pkt(*this, 0x33);
|
cPacketizer Pkt(*this, 0x33);
|
||||||
Pkt.WriteInt(a_BlockX);
|
Pkt.WriteInt(a_BlockX);
|
||||||
|
@ -71,7 +71,9 @@ public:
|
|||||||
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
|
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
|
||||||
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
|
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
|
||||||
virtual void SendDisconnect (const AString & a_Reason) override;
|
virtual void SendDisconnect (const AString & a_Reason) override;
|
||||||
|
virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override;
|
||||||
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
|
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
|
||||||
|
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
|
||||||
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override;
|
virtual void SendEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration) override;
|
||||||
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
|
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
|
||||||
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
|
virtual void SendEntityHeadLook (const cEntity & a_Entity) override;
|
||||||
@ -82,6 +84,8 @@ public:
|
|||||||
virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
|
virtual void SendEntityRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override;
|
||||||
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
|
virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override;
|
||||||
virtual void SendEntityVelocity (const cEntity & a_Entity) override;
|
virtual void SendEntityVelocity (const cEntity & a_Entity) override;
|
||||||
|
virtual void SendExperience (void) override;
|
||||||
|
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
||||||
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override;
|
virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override;
|
||||||
virtual void SendGameMode (eGameMode a_GameMode) override;
|
virtual void SendGameMode (eGameMode a_GameMode) override;
|
||||||
virtual void SendHealth (void) override;
|
virtual void SendHealth (void) override;
|
||||||
@ -93,10 +97,9 @@ public:
|
|||||||
virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override;
|
virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override;
|
||||||
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override;
|
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override;
|
||||||
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
|
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
|
||||||
|
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override;
|
||||||
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
|
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
|
||||||
virtual void SendPlayerAbilities (void) override;
|
virtual void SendPlayerAbilities (void) override;
|
||||||
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
|
|
||||||
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmmount) override;
|
|
||||||
virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override;
|
virtual void SendPlayerListItem (const cPlayer & a_Player, bool a_IsOnline) override;
|
||||||
virtual void SendPlayerMaxSpeed (void) override;
|
virtual void SendPlayerMaxSpeed (void) override;
|
||||||
virtual void SendPlayerMoveLook (void) override;
|
virtual void SendPlayerMoveLook (void) override;
|
||||||
@ -105,12 +108,9 @@ public:
|
|||||||
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
virtual void SendPluginMessage (const AString & a_Channel, const AString & a_Message) override;
|
||||||
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
virtual void SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) override;
|
||||||
virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
|
virtual void SendRespawn (eDimension a_Dimension, bool a_ShouldIgnoreDimensionChecks) override;
|
||||||
virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
|
|
||||||
virtual void SendExperience (void) override;
|
|
||||||
virtual void SendExperienceOrb (const cExpOrb & a_ExpOrb) override;
|
|
||||||
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
|
||||||
virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override;
|
virtual void SendScoreUpdate (const AString & a_Objective, const AString & a_Player, cObjective::Score a_Score, Byte a_Mode) override;
|
||||||
virtual void SendDisplayObjective (const AString & a_Objective, cScoreboard::eDisplaySlot a_Display) override;
|
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
|
||||||
|
virtual void SendSoundEffect (const AString & a_SoundName, double a_X, double a_Y, double a_Z, float a_Volume, float a_Pitch) override;
|
||||||
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
|
virtual void SendSoundParticleEffect (int a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
|
||||||
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
|
virtual void SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
|
||||||
virtual void SendSpawnMob (const cMonster & a_Mob) override;
|
virtual void SendSpawnMob (const cMonster & a_Mob) override;
|
||||||
|
@ -44,7 +44,6 @@ cSetChunkData::cSetChunkData(
|
|||||||
// Check the params' validity:
|
// Check the params' validity:
|
||||||
ASSERT(a_BlockTypes != NULL);
|
ASSERT(a_BlockTypes != NULL);
|
||||||
ASSERT(a_BlockMetas != NULL);
|
ASSERT(a_BlockMetas != NULL);
|
||||||
ASSERT(a_Biomes != NULL);
|
|
||||||
|
|
||||||
// Copy block types and metas:
|
// Copy block types and metas:
|
||||||
memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
|
memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
|
||||||
|
142
src/WebAdmin.cpp
142
src/WebAdmin.cpp
@ -131,8 +131,24 @@ bool cWebAdmin::Start(void)
|
|||||||
m_TemplateScript.RegisterAPILibs();
|
m_TemplateScript.RegisterAPILibs();
|
||||||
if (!m_TemplateScript.LoadFile(FILE_IO_PREFIX "webadmin/template.lua"))
|
if (!m_TemplateScript.LoadFile(FILE_IO_PREFIX "webadmin/template.lua"))
|
||||||
{
|
{
|
||||||
LOGWARN("Could not load WebAdmin template \"%s\", using default template.", FILE_IO_PREFIX "webadmin/template.lua");
|
LOGWARN("Could not load WebAdmin template \"%s\". WebAdmin disabled!", FILE_IO_PREFIX "webadmin/template.lua");
|
||||||
m_TemplateScript.Close();
|
m_TemplateScript.Close();
|
||||||
|
m_HTTPServer.Stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LoadLoginTemplate())
|
||||||
|
{
|
||||||
|
LOGWARN("Could not load WebAdmin login template \"%s\", using fallback template.", FILE_IO_PREFIX "webadmin/login_template.html");
|
||||||
|
|
||||||
|
// Sets the fallback template:
|
||||||
|
m_LoginTemplate = \
|
||||||
|
"<h1>MCServer WebAdmin</h1>" \
|
||||||
|
"<center>" \
|
||||||
|
"<form method='get' action='webadmin/'>" \
|
||||||
|
"<input type='submit' value='Log in'>" \
|
||||||
|
"</form>" \
|
||||||
|
"</center>";
|
||||||
}
|
}
|
||||||
|
|
||||||
m_IsRunning = m_HTTPServer.Start(*this);
|
m_IsRunning = m_HTTPServer.Start(*this);
|
||||||
@ -159,6 +175,28 @@ void cWebAdmin::Stop(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWebAdmin::LoadLoginTemplate(void)
|
||||||
|
{
|
||||||
|
cFile File(FILE_IO_PREFIX "webadmin/login_template.html", cFile::fmRead);
|
||||||
|
if (!File.IsOpen())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AString TemplateContent;
|
||||||
|
if (File.ReadRestOfFile(TemplateContent) == -1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_LoginTemplate = TemplateContent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
||||||
{
|
{
|
||||||
if (!a_Request.HasAuth())
|
if (!a_Request.HasAuth())
|
||||||
@ -298,17 +336,11 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
|
|||||||
void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
||||||
{
|
{
|
||||||
UNUSED(a_Request);
|
UNUSED(a_Request);
|
||||||
static const char LoginForm[] = \
|
|
||||||
"<h1>MCServer WebAdmin</h1>" \
|
|
||||||
"<center>" \
|
|
||||||
"<form method='get' action='webadmin/'>" \
|
|
||||||
"<input type='submit' value='Log in'>" \
|
|
||||||
"</form>" \
|
|
||||||
"</center>";
|
|
||||||
cHTTPResponse Resp;
|
cHTTPResponse Resp;
|
||||||
Resp.SetContentType("text/html");
|
Resp.SetContentType("text/html");
|
||||||
a_Connection.Send(Resp);
|
a_Connection.Send(Resp);
|
||||||
a_Connection.Send(LoginForm, sizeof(LoginForm) - 1);
|
a_Connection.Send(m_LoginTemplate);
|
||||||
a_Connection.FinishResponse();
|
a_Connection.FinishResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +348,94 @@ void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest &
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cWebAdmin::HandleFileRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request)
|
||||||
|
{
|
||||||
|
AString FileURL = a_Request.GetURL();
|
||||||
|
std::replace(FileURL.begin(), FileURL.end(), '\\', '/');
|
||||||
|
|
||||||
|
// Remove all leading backslashes:
|
||||||
|
if (FileURL[0] == '/')
|
||||||
|
{
|
||||||
|
size_t FirstCharToRead = FileURL.find_first_not_of('/');
|
||||||
|
if (FirstCharToRead != AString::npos)
|
||||||
|
{
|
||||||
|
FileURL = FileURL.substr(FirstCharToRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all "../" strings:
|
||||||
|
ReplaceString(FileURL, "../", "");
|
||||||
|
|
||||||
|
bool LoadedSuccessfull = false;
|
||||||
|
AString Content = "<h2>404 Not Found</h2>";
|
||||||
|
AString Path = Printf(FILE_IO_PREFIX "webadmin/files/%s", FileURL.c_str());
|
||||||
|
if (cFile::IsFile(Path))
|
||||||
|
{
|
||||||
|
cFile File(Path, cFile::fmRead);
|
||||||
|
AString FileContent;
|
||||||
|
if (File.IsOpen() && (File.ReadRestOfFile(FileContent) != -1))
|
||||||
|
{
|
||||||
|
LoadedSuccessfull = true;
|
||||||
|
Content = FileContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find content type (The currently method is very bad. We should change it later)
|
||||||
|
AString ContentType = "text/html";
|
||||||
|
size_t LastPointPosition = Path.find_last_of('.');
|
||||||
|
if (LoadedSuccessfull && (LastPointPosition != AString::npos) && (LastPointPosition < Path.length()))
|
||||||
|
{
|
||||||
|
AString FileExtension = Path.substr(LastPointPosition + 1);
|
||||||
|
ContentType = GetContentTypeFromFileExt(FileExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the response:
|
||||||
|
cHTTPResponse Resp;
|
||||||
|
Resp.SetContentType(ContentType);
|
||||||
|
a_Connection.Send(Resp);
|
||||||
|
a_Connection.Send(Content);
|
||||||
|
a_Connection.FinishResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cWebAdmin::GetContentTypeFromFileExt(const AString & a_FileExtension)
|
||||||
|
{
|
||||||
|
static bool IsInitialized = false;
|
||||||
|
static std::map<AString, AString> ContentTypeMap;
|
||||||
|
if (!IsInitialized)
|
||||||
|
{
|
||||||
|
// Initialize the ContentTypeMap:
|
||||||
|
ContentTypeMap["png"] = "image/png";
|
||||||
|
ContentTypeMap["fif"] = "image/fif";
|
||||||
|
ContentTypeMap["gif"] = "image/gif";
|
||||||
|
ContentTypeMap["jpeg"] = "image/jpeg";
|
||||||
|
ContentTypeMap["jpg"] = "image/jpeg";
|
||||||
|
ContentTypeMap["jpe"] = "image/jpeg";
|
||||||
|
ContentTypeMap["tiff"] = "image/tiff";
|
||||||
|
ContentTypeMap["ico"] = "image/ico";
|
||||||
|
ContentTypeMap["csv"] = "image/comma-separated-values";
|
||||||
|
ContentTypeMap["css"] = "text/css";
|
||||||
|
ContentTypeMap["js"] = "text/javascript";
|
||||||
|
ContentTypeMap["txt"] = "text/plain";
|
||||||
|
ContentTypeMap["rtx"] = "text/richtext";
|
||||||
|
ContentTypeMap["xml"] = "text/xml";
|
||||||
|
}
|
||||||
|
|
||||||
|
AString FileExtension = StrToLower(a_FileExtension);
|
||||||
|
if (ContentTypeMap.find(a_FileExtension) == ContentTypeMap.end())
|
||||||
|
{
|
||||||
|
return "text/html";
|
||||||
|
}
|
||||||
|
return ContentTypeMap[FileExtension];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sWebAdminPage cWebAdmin::GetPage(const HTTPRequest & a_Request)
|
sWebAdminPage cWebAdmin::GetPage(const HTTPRequest & a_Request)
|
||||||
{
|
{
|
||||||
sWebAdminPage Page;
|
sWebAdminPage Page;
|
||||||
@ -382,6 +502,7 @@ AString cWebAdmin::GetDefaultPage(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AString cWebAdmin::GetBaseURL( const AString& a_URL)
|
AString cWebAdmin::GetBaseURL( const AString& a_URL)
|
||||||
{
|
{
|
||||||
return GetBaseURL(StringSplit(a_URL, "/"));
|
return GetBaseURL(StringSplit(a_URL, "/"));
|
||||||
@ -528,7 +649,7 @@ void cWebAdmin::OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest &
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Handle other requests
|
HandleFileRequest(a_Connection, a_Request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete any request data assigned to the request:
|
// Delete any request data assigned to the request:
|
||||||
@ -551,4 +672,3 @@ void cWebAdmin::cWebadminRequestData::OnBody(const char * a_Data, size_t a_Size)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,6 +116,9 @@ public:
|
|||||||
/** Stops the HTTP server, if it was started. */
|
/** Stops the HTTP server, if it was started. */
|
||||||
void Stop(void);
|
void Stop(void);
|
||||||
|
|
||||||
|
/** Loads the login template. Returns true if the loading succeeds, false if not. */
|
||||||
|
bool LoadLoginTemplate(void);
|
||||||
|
|
||||||
void AddPlugin(cWebPlugin * a_Plugin);
|
void AddPlugin(cWebPlugin * a_Plugin);
|
||||||
void RemovePlugin(cWebPlugin * a_Plugin);
|
void RemovePlugin(cWebPlugin * a_Plugin);
|
||||||
|
|
||||||
@ -146,6 +149,9 @@ public:
|
|||||||
/** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style) */
|
/** Returns the prefix needed for making a link point to the webadmin root from the given URL ("../../../webadmin"-style) */
|
||||||
static AString GetBaseURL(const AStringVector & a_URLSplit);
|
static AString GetBaseURL(const AStringVector & a_URLSplit);
|
||||||
|
|
||||||
|
/** Returns the content type from the file extension. If the extension isn't in the list, the function returns "text/html" */
|
||||||
|
static AString GetContentTypeFromFileExt(const AString & a_FileExtension);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Common base class for request body data handlers */
|
/** Common base class for request body data handlers */
|
||||||
class cRequestData
|
class cRequestData
|
||||||
@ -205,6 +211,9 @@ protected:
|
|||||||
/** The Lua template script to provide templates: */
|
/** The Lua template script to provide templates: */
|
||||||
cLuaState m_TemplateScript;
|
cLuaState m_TemplateScript;
|
||||||
|
|
||||||
|
/** The template that provides the login site: */
|
||||||
|
AString m_LoginTemplate;
|
||||||
|
|
||||||
/** The HTTP server which provides the underlying HTTP parsing, serialization and events */
|
/** The HTTP server which provides the underlying HTTP parsing, serialization and events */
|
||||||
cHTTPServer m_HTTPServer;
|
cHTTPServer m_HTTPServer;
|
||||||
|
|
||||||
@ -214,6 +223,9 @@ protected:
|
|||||||
/** Handles requests for the root page */
|
/** Handles requests for the root page */
|
||||||
void HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
|
void HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
|
||||||
|
|
||||||
|
/** Handles requests for a file */
|
||||||
|
void HandleFileRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
|
||||||
|
|
||||||
// cHTTPServer::cCallbacks overrides:
|
// cHTTPServer::cCallbacks overrides:
|
||||||
virtual void OnRequestBegun (cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override;
|
virtual void OnRequestBegun (cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override;
|
||||||
virtual void OnRequestBody (cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override;
|
virtual void OnRequestBody (cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override;
|
||||||
|
@ -2374,6 +2374,8 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
|
void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
|
||||||
{
|
{
|
||||||
|
ASSERT(IsChunkQueued(a_SetChunkData->GetChunkX(), a_SetChunkData->GetChunkZ()));
|
||||||
|
|
||||||
// Validate biomes, if needed:
|
// Validate biomes, if needed:
|
||||||
if (!a_SetChunkData->AreBiomesValid())
|
if (!a_SetChunkData->AreBiomesValid())
|
||||||
{
|
{
|
||||||
@ -2463,6 +2465,15 @@ bool cWorld::GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockT
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWorld::IsChunkQueued(int a_ChunkX, int a_ChunkZ) const
|
||||||
|
{
|
||||||
|
return m_ChunkMap->IsChunkQueued(a_ChunkX, a_ChunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
|
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkZ) const
|
||||||
{
|
{
|
||||||
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkZ);
|
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkZ);
|
||||||
@ -2787,24 +2798,6 @@ void cWorld::TouchChunk(int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cWorld::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
|
||||||
{
|
|
||||||
return m_ChunkMap->LoadChunk(a_ChunkX, a_ChunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::LoadChunks(const cChunkCoordsList & a_Chunks)
|
|
||||||
{
|
|
||||||
m_ChunkMap->LoadChunks(a_Chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
void cWorld::ChunkLoadFailed(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
m_ChunkMap->ChunkLoadFailed(a_ChunkX, a_ChunkZ);
|
m_ChunkMap->ChunkLoadFailed(a_ChunkX, a_ChunkZ);
|
||||||
@ -3520,6 +3513,15 @@ bool cWorld::cChunkGeneratorCallbacks::IsChunkValid(int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cWorld::cChunkGeneratorCallbacks::IsChunkQueued(int a_ChunkX, int a_ChunkZ)
|
||||||
|
{
|
||||||
|
return m_World->IsChunkQueued(a_ChunkX, a_ChunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
|
bool cWorld::cChunkGeneratorCallbacks::HasChunkAnyClients(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
return m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
|
return m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
|
||||||
|
14
src/World.h
14
src/World.h
@ -279,7 +279,12 @@ public:
|
|||||||
/** Gets the chunk's blocks, only the block types */
|
/** Gets the chunk's blocks, only the block types */
|
||||||
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes);
|
bool GetChunkBlockTypes(int a_ChunkX, int a_ChunkZ, BLOCKTYPE * a_BlockTypes);
|
||||||
|
|
||||||
bool IsChunkValid (int a_ChunkX, int a_ChunkZ) const;
|
/** Returns true iff the chunk is in the loader / generator queue. */
|
||||||
|
bool IsChunkQueued(int a_ChunkX, int a_ChunkZ) const;
|
||||||
|
|
||||||
|
/** Returns true iff the chunk is present and valid. */
|
||||||
|
bool IsChunkValid(int a_ChunkX, int a_ChunkZ) const;
|
||||||
|
|
||||||
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const;
|
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) const;
|
||||||
|
|
||||||
/** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/
|
/** Queues a task to unload unused chunks onto the tick thread. The prefferred way of unloading*/
|
||||||
@ -358,12 +363,6 @@ public:
|
|||||||
/** Touches the chunk, causing it to be loaded or generated */
|
/** Touches the chunk, causing it to be loaded or generated */
|
||||||
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
void TouchChunk(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
/** Loads the chunk, if not already loaded. Doesn't generate. Returns true if chunk valid (even if already loaded before) */
|
|
||||||
bool LoadChunk(int a_ChunkX, int a_ChunkZ);
|
|
||||||
|
|
||||||
/** Loads the chunks specified. Doesn't report failure, other than chunks being !IsValid() */
|
|
||||||
void LoadChunks(const cChunkCoordsList & a_Chunks);
|
|
||||||
|
|
||||||
/** Marks the chunk as failed-to-load: */
|
/** Marks the chunk as failed-to-load: */
|
||||||
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
@ -822,6 +821,7 @@ private:
|
|||||||
virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override;
|
virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override;
|
||||||
virtual bool IsChunkValid (int a_ChunkX, int a_ChunkZ) override;
|
virtual bool IsChunkValid (int a_ChunkX, int a_ChunkZ) override;
|
||||||
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) override;
|
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) override;
|
||||||
|
virtual bool IsChunkQueued (int a_ChunkX, int a_ChunkZ) override;
|
||||||
|
|
||||||
// cPluginInterface overrides:
|
// cPluginInterface overrides:
|
||||||
virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override;
|
virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override;
|
||||||
|
@ -283,37 +283,37 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT)
|
|||||||
bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false;
|
bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false;
|
||||||
|
|
||||||
int CurrLine = a_NBT.FindChildByName(Child, "Name");
|
int CurrLine = a_NBT.FindChildByName(Child, "Name");
|
||||||
if (CurrLine >= 0)
|
if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
|
||||||
{
|
{
|
||||||
Name = a_NBT.GetInt(CurrLine);
|
Name = a_NBT.GetString(CurrLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrLine = a_NBT.FindChildByName(Child, "DisplayName");
|
CurrLine = a_NBT.FindChildByName(Child, "DisplayName");
|
||||||
if (CurrLine >= 0)
|
if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
|
||||||
{
|
{
|
||||||
DisplayName = a_NBT.GetInt(CurrLine);
|
DisplayName = a_NBT.GetString(CurrLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrLine = a_NBT.FindChildByName(Child, "Prefix");
|
CurrLine = a_NBT.FindChildByName(Child, "Prefix");
|
||||||
if (CurrLine >= 0)
|
if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
|
||||||
{
|
{
|
||||||
Prefix = a_NBT.GetInt(CurrLine);
|
Prefix = a_NBT.GetString(CurrLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrLine = a_NBT.FindChildByName(Child, "Suffix");
|
CurrLine = a_NBT.FindChildByName(Child, "Suffix");
|
||||||
if (CurrLine >= 0)
|
if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
|
||||||
{
|
{
|
||||||
Suffix = a_NBT.GetInt(CurrLine);
|
Suffix = a_NBT.GetString(CurrLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire");
|
CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire");
|
||||||
if (CurrLine >= 0)
|
if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
|
||||||
{
|
{
|
||||||
AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0);
|
AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles");
|
CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles");
|
||||||
if (CurrLine >= 0)
|
if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
|
||||||
{
|
{
|
||||||
CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0);
|
CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0);
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,13 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int Sections = a_NBT.FindChildByName(Level, "Sections");
|
int Sections = a_NBT.FindChildByName(Level, "Sections");
|
||||||
if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List) || (a_NBT.GetChildrenType(Sections) != TAG_Compound))
|
if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List))
|
||||||
|
{
|
||||||
|
LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
eTagType SectionsType = a_NBT.GetChildrenType(Sections);
|
||||||
|
if ((SectionsType != TAG_Compound) && (SectionsType != TAG_End))
|
||||||
{
|
{
|
||||||
LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
|
LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
|
||||||
return false;
|
return false;
|
||||||
@ -589,7 +595,7 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
|
|||||||
|
|
||||||
// Get the BlockEntity's position
|
// Get the BlockEntity's position
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
if (!GetBlockEntityNBTPos(a_NBT, Child, x, y, z))
|
if (!GetBlockEntityNBTPos(a_NBT, Child, x, y, z) || (y < 0) || (y >= cChunkDef::Height))
|
||||||
{
|
{
|
||||||
LOGWARNING("Bad block entity, missing the coords. Will be ignored.");
|
LOGWARNING("Bad block entity, missing the coords. Will be ignored.");
|
||||||
continue;
|
continue;
|
||||||
@ -617,6 +623,8 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
|
|||||||
|
|
||||||
cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a_Tag, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a_Tag, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
|
||||||
{
|
{
|
||||||
|
ASSERT((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height));
|
||||||
|
|
||||||
// Load the specific BlockEntity type:
|
// Load the specific BlockEntity type:
|
||||||
switch (a_BlockType)
|
switch (a_BlockType)
|
||||||
{
|
{
|
||||||
@ -2815,7 +2823,7 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a
|
|||||||
}
|
}
|
||||||
unsigned ChunkLocation = ntohl(m_Header[LocalX + 32 * LocalZ]);
|
unsigned ChunkLocation = ntohl(m_Header[LocalX + 32 * LocalZ]);
|
||||||
unsigned ChunkOffset = ChunkLocation >> 8;
|
unsigned ChunkOffset = ChunkLocation >> 8;
|
||||||
if (ChunkOffset <= 2)
|
if (ChunkOffset < 2)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -141,9 +141,11 @@ size_t cWorldStorage::GetSaveQueueLength(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate)
|
void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
m_LoadQueue.EnqueueItem(sChunkLoad(a_ChunkX, a_ChunkZ, a_Generate));
|
ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
|
m_LoadQueue.EnqueueItem(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||||
m_Event.Set();
|
m_Event.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,6 +155,8 @@ void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate)
|
|||||||
|
|
||||||
void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ)
|
void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
|
ASSERT(m_World->IsChunkValid(a_ChunkX, a_ChunkZ));
|
||||||
|
|
||||||
m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkZ));
|
m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||||
m_Event.Set();
|
m_Event.Set();
|
||||||
}
|
}
|
||||||
@ -163,7 +167,7 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ)
|
|||||||
|
|
||||||
void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkZ)
|
void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
m_LoadQueue.Remove(sChunkLoad(a_ChunkX, a_ChunkZ, true));
|
m_LoadQueue.Remove(cChunkCoords(a_ChunkX, a_ChunkZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -242,22 +246,14 @@ void cWorldStorage::Execute(void)
|
|||||||
|
|
||||||
bool cWorldStorage::LoadOneChunk(void)
|
bool cWorldStorage::LoadOneChunk(void)
|
||||||
{
|
{
|
||||||
sChunkLoad ToLoad(0, 0, false);
|
cChunkCoords ToLoad(0, 0);
|
||||||
bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
|
bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
|
||||||
if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ))
|
|
||||||
|
if (ShouldLoad)
|
||||||
{
|
{
|
||||||
if (ToLoad.m_Generate)
|
return LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ);
|
||||||
{
|
|
||||||
// The chunk couldn't be loaded, generate it:
|
|
||||||
m_World->GetGenerator().QueueGenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Notify the world that the load has failed:
|
|
||||||
// m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkZ);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ShouldLoad;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -285,11 +281,7 @@ bool cWorldStorage::SaveOneChunk(void)
|
|||||||
|
|
||||||
bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkZ)
|
||||||
{
|
{
|
||||||
if (m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
|
ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ));
|
||||||
{
|
|
||||||
// Already loaded (can happen, since the queue is async)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
cChunkCoords Coords(a_ChunkX, a_ChunkZ);
|
cChunkCoords Coords(a_ChunkX, a_ChunkZ);
|
||||||
|
|
||||||
|
@ -64,12 +64,9 @@ public:
|
|||||||
cWorldStorage(void);
|
cWorldStorage(void);
|
||||||
~cWorldStorage();
|
~cWorldStorage();
|
||||||
|
|
||||||
void QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate); // Queues the chunk for loading; if not loaded, the chunk will be generated if a_Generate is true
|
void QueueLoadChunk(int a_ChunkX, int a_ChunkZ);
|
||||||
void QueueSaveChunk(int a_ChunkX, int a_ChunkZ);
|
void QueueSaveChunk(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
/// Loads the chunk specified; returns true on success, false on failure
|
|
||||||
bool LoadChunk(int a_ChunkX, int a_ChunkZ);
|
|
||||||
|
|
||||||
void UnqueueLoad(int a_ChunkX, int a_ChunkZ);
|
void UnqueueLoad(int a_ChunkX, int a_ChunkZ);
|
||||||
void UnqueueSave(const cChunkCoords & a_Chunk);
|
void UnqueueSave(const cChunkCoords & a_Chunk);
|
||||||
|
|
||||||
@ -84,38 +81,10 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
struct sChunkLoad
|
|
||||||
{
|
|
||||||
int m_ChunkX;
|
|
||||||
int m_ChunkZ;
|
|
||||||
bool m_Generate; // If true, the chunk will be generated if it cannot be loaded
|
|
||||||
|
|
||||||
sChunkLoad(int a_ChunkX, int a_ChunkZ, bool a_Generate) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), m_Generate(a_Generate) {}
|
|
||||||
|
|
||||||
bool operator ==(const sChunkLoad other) const
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
(this->m_ChunkX == other.m_ChunkX) &&
|
|
||||||
(this->m_ChunkZ == other.m_ChunkZ)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
struct FuncTable
|
|
||||||
{
|
|
||||||
static void Delete(sChunkLoad) {}
|
|
||||||
static void Combine(sChunkLoad & a_orig, const sChunkLoad a_new)
|
|
||||||
{
|
|
||||||
a_orig.m_Generate |= a_new.m_Generate;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef cQueue<sChunkLoad, FuncTable> sChunkLoadQueue;
|
|
||||||
|
|
||||||
cWorld * m_World;
|
cWorld * m_World;
|
||||||
AString m_StorageSchemaName;
|
AString m_StorageSchemaName;
|
||||||
|
|
||||||
sChunkLoadQueue m_LoadQueue;
|
cChunkCoordsQueue m_LoadQueue;
|
||||||
cChunkCoordsQueue m_SaveQueue;
|
cChunkCoordsQueue m_SaveQueue;
|
||||||
|
|
||||||
/// All the storage schemas (all used for loading)
|
/// All the storage schemas (all used for loading)
|
||||||
@ -123,7 +92,11 @@ protected:
|
|||||||
|
|
||||||
/// The one storage schema used for saving
|
/// The one storage schema used for saving
|
||||||
cWSSchema * m_SaveSchema;
|
cWSSchema * m_SaveSchema;
|
||||||
|
|
||||||
|
|
||||||
|
/// Loads the chunk specified; returns true on success, false on failure
|
||||||
|
bool LoadChunk(int a_ChunkX, int a_ChunkZ);
|
||||||
|
|
||||||
void InitSchemas(int a_StorageCompressionFactor);
|
void InitSchemas(int a_StorageCompressionFactor);
|
||||||
|
|
||||||
virtual void Execute(void) override;
|
virtual void Execute(void) override;
|
||||||
|
Loading…
Reference in New Issue
Block a user