summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--Install/ThirdPartyLicenses/Lua-LICENSE.txt (renamed from Install/Lua-LICENSE.txt)0
-rw-r--r--Install/ThirdPartyLicenses/LuaExpat-license.html (renamed from Install/LuaExpat-license.html)0
-rw-r--r--Install/ThirdPartyLicenses/LuaSQLite3-LICENSE.txt (renamed from Install/LuaSQLite3-LICENSE.txt)0
-rw-r--r--Install/ThirdPartyLicenses/MersenneTwister-LICENSE.txt (renamed from Install/MersenneTwister-LICENSE.txt)0
-rw-r--r--Install/ThirdPartyLicenses/SQLiteCpp-LICENSE.txt (renamed from Install/SQLiteCpp-LICENSE.txt)0
-rw-r--r--Install/Zip2008.list6
-rw-r--r--MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html6
-rw-r--r--MCServer/webadmin/files/background.gifbin0 -> 57 bytes
-rw-r--r--MCServer/webadmin/files/favicon.icobin0 -> 32038 bytes
-rw-r--r--MCServer/webadmin/files/logo.pngbin0 -> 3315 bytes
-rw-r--r--MCServer/webadmin/files/mc-logo.pngbin0 -> 66137 bytes
-rw-r--r--MCServer/webadmin/files/style.css326
-rw-r--r--MCServer/webadmin/login_template.html25
-rw-r--r--MCServer/webadmin/template.lua344
-rw-r--r--SetFlags.cmake31
-rw-r--r--src/BlockEntities/SignEntity.cpp1
-rw-r--r--src/Chunk.cpp56
-rw-r--r--src/Chunk.h47
-rw-r--r--src/ChunkMap.cpp79
-rw-r--r--src/ChunkMap.h9
-rw-r--r--src/Entities/Player.cpp6
-rw-r--r--src/Generating/BioGen.cpp4
-rw-r--r--src/Generating/BioGen.h14
-rw-r--r--src/Generating/ChunkGenerator.cpp5
-rw-r--r--src/Generating/ChunkGenerator.h4
-rw-r--r--src/Generating/ComposableGenerator.cpp43
-rw-r--r--src/Protocol/Protocol17x.cpp1
-rw-r--r--src/Protocol/Protocol17x.h14
-rw-r--r--src/SetChunkData.cpp1
-rw-r--r--src/WebAdmin.cpp142
-rw-r--r--src/WebAdmin.h12
-rw-r--r--src/World.cpp38
-rw-r--r--src/World.h14
-rw-r--r--src/WorldStorage/ScoreboardSerializer.cpp20
-rw-r--r--src/WorldStorage/WSSAnvil.cpp14
-rw-r--r--src/WorldStorage/WorldStorage.cpp34
-rw-r--r--src/WorldStorage/WorldStorage.h39
38 files changed, 762 insertions, 575 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dd9b1e67c..4c47eb509 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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 )
enable_language(CXX C)
diff --git a/Install/Lua-LICENSE.txt b/Install/ThirdPartyLicenses/Lua-LICENSE.txt
index 3c6d06fcf..3c6d06fcf 100644
--- a/Install/Lua-LICENSE.txt
+++ b/Install/ThirdPartyLicenses/Lua-LICENSE.txt
diff --git a/Install/LuaExpat-license.html b/Install/ThirdPartyLicenses/LuaExpat-license.html
index bd4a54f9a..bd4a54f9a 100644
--- a/Install/LuaExpat-license.html
+++ b/Install/ThirdPartyLicenses/LuaExpat-license.html
diff --git a/Install/LuaSQLite3-LICENSE.txt b/Install/ThirdPartyLicenses/LuaSQLite3-LICENSE.txt
index cf1014378..cf1014378 100644
--- a/Install/LuaSQLite3-LICENSE.txt
+++ b/Install/ThirdPartyLicenses/LuaSQLite3-LICENSE.txt
diff --git a/Install/MersenneTwister-LICENSE.txt b/Install/ThirdPartyLicenses/MersenneTwister-LICENSE.txt
index 5c7a6ef04..5c7a6ef04 100644
--- a/Install/MersenneTwister-LICENSE.txt
+++ b/Install/ThirdPartyLicenses/MersenneTwister-LICENSE.txt
diff --git a/Install/SQLiteCpp-LICENSE.txt b/Install/ThirdPartyLicenses/SQLiteCpp-LICENSE.txt
index ec952abba..ec952abba 100644
--- a/Install/SQLiteCpp-LICENSE.txt
+++ b/Install/ThirdPartyLicenses/SQLiteCpp-LICENSE.txt
diff --git a/Install/Zip2008.list b/Install/Zip2008.list
index 5736867d8..dba435f60 100644
--- a/Install/Zip2008.list
+++ b/Install/Zip2008.list
@@ -8,8 +8,4 @@
..\MCServer\monsters.ini
MCServer*debug.cmd
*.example.ini
-Lua-LICENSE.txt
-LuaExpat-license.html
-LuaSQLite3-LICENSE.txt
-SQLiteCpp-LICENSE.txt
-MersenneTwister-LICENSE.txt
+ThirdPartyLicenses
diff --git a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
index 35c880b00..dd124e119 100644
--- a/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
+++ b/MCServer/Plugins/APIDump/Writing-a-MCServer-plugin.html
@@ -202,7 +202,7 @@ function Explode(Split, Player)
if (#Split ~= 2) then
-- There was more or less than one argument (excluding the "/explode" bit)
-- Send the proper usage to the player and exit
- SendMessage(Player, "Usage: /explode [playername]")
+ Player:SendMessage("Usage: /explode [playername]")
return true
end
@@ -213,7 +213,7 @@ function Explode(Split, Player)
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
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;
return true -- Signalize to MCS that we do not need to call this callback for any more players
end
@@ -224,7 +224,7 @@ function Explode(Split, Player)
if not(HasExploded) then
-- 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
return true
diff --git a/MCServer/webadmin/files/background.gif b/MCServer/webadmin/files/background.gif
new file mode 100644
index 000000000..cab9bed56
--- /dev/null
+++ b/MCServer/webadmin/files/background.gif
Binary files differ
diff --git a/MCServer/webadmin/files/favicon.ico b/MCServer/webadmin/files/favicon.ico
new file mode 100644
index 000000000..ea4bde926
--- /dev/null
+++ b/MCServer/webadmin/files/favicon.ico
Binary files differ
diff --git a/MCServer/webadmin/files/logo.png b/MCServer/webadmin/files/logo.png
new file mode 100644
index 000000000..50733e824
--- /dev/null
+++ b/MCServer/webadmin/files/logo.png
Binary files differ
diff --git a/MCServer/webadmin/files/mc-logo.png b/MCServer/webadmin/files/mc-logo.png
new file mode 100644
index 000000000..9a77a490f
--- /dev/null
+++ b/MCServer/webadmin/files/mc-logo.png
Binary files differ
diff --git a/MCServer/webadmin/files/style.css b/MCServer/webadmin/files/style.css
new file mode 100644
index 000000000..e7ffe3999
--- /dev/null
+++ b/MCServer/webadmin/files/style.css
@@ -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; }
diff --git a/MCServer/webadmin/login_template.html b/MCServer/webadmin/login_template.html
new file mode 100644
index 000000000..913a85db0
--- /dev/null
+++ b/MCServer/webadmin/login_template.html
@@ -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>
diff --git a/MCServer/webadmin/template.lua b/MCServer/webadmin/template.lua
index a066d8b33..a7480f83e 100644
--- a/MCServer/webadmin/template.lua
+++ b/MCServer/webadmin/template.lua
@@ -57,7 +57,7 @@ end
function ShowPage(WebAdmin, TemplateRequest)
SiteContent = {}
local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path)
- local Title = "MCServer"
+ local Title = "MCServer WebAdmin"
local MemoryUsageKiB = cRoot:GetPhysicalRAMUsage()
local NumChunks = cRoot:Get():GetTotalChunkCount()
local PluginPage = WebAdmin:GetPage(TemplateRequest.Request)
@@ -74,339 +74,9 @@ function ShowPage(WebAdmin, TemplateRequest)
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<link rel="icon" href="data:application/octet-stream;base64,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">
+<link rel="icon" href="/favicon.ico">
<title>]] .. Title .. [[</title>
-
-<style type="text/css" media="screen">
-
- /* 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(data:image/png;base64,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) 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(data:image/gif;base64,R0lGODlhtAABAIAAAN3d3f///yH5BAAAAAAALAAAAAC0AAEAAAIMjI+py+0Po5y0WgYKADs%3D) 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(data:image/png;base64,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);
- }
-
- #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; }
-</style>
-
+<link rel="stylesheet" type="text/css" media="screen" href="/style.css">
</head>
<body>
@@ -421,16 +91,16 @@ function ShowPage(WebAdmin, TemplateRequest)
<ul class="sideNav">
]])
-
+
local AllPlugins = WebAdmin:GetPlugins()
for key,value in pairs(AllPlugins) do
local PluginWebTitle = value:GetWebTitle()
local TabNames = value:GetTabNames()
if (GetTableSize(TabNames) > 0) then
- Output("<li>"..PluginWebTitle.."</li>");
+ Output("<li>"..PluginWebTitle.."</li>\n");
for webname,prettyname in pairs(TabNames) do
- Output("<li><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "'>" .. prettyname .. "</a></li>")
+ Output("<li><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "'>" .. prettyname .. "</a></li>\n")
end
end
end
@@ -464,4 +134,4 @@ function ShowPage(WebAdmin, TemplateRequest)
]])
return table.concat(SiteContent)
-end \ No newline at end of file
+end
diff --git a/SetFlags.cmake b/SetFlags.cmake
index 0e2e0c277..0835189ad 100644
--- a/SetFlags.cmake
+++ b/SetFlags.cmake
@@ -205,6 +205,15 @@ macro(enable_profile)
endif()
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)
# 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
@@ -223,17 +232,29 @@ macro(set_exe_flags)
add_flags_cxx("-ffast-math")
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
add_flags_cxx("-D__extern_always_inline=inline")
add_flags_cxx("-Werror -Weverything -Wno-c++98-compat-pedantic -Wno-string-conversion")
- add_flags_cxx("-Wno-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=deprecated -Wno-error=weak-vtables -Wno-error=float-equal")
add_flags_cxx("-Wno-error=missing-prototypes -Wno-error=non-virtual-dtor")
- add_flags_cxx("-Wno-error=covered-switch-default -Wno-error=shadow -Wno-error=old-style-cast")
- add_flags_cxx("-Wno-error=exit-time-destructors -Wno-error=missing-variable-declarations")
- add_flags_cxx("-Wno-error=global-constructors -Wno-implicit-fallthrough")
- add_flags_cxx("-Wno-error=extra-semi -Wno-weak-vtables -Wno-switch-enum")
+ add_flags_cxx("-Wno-error=shadow -Wno-error=old-style-cast -Wno-error=global-constructors")
+ add_flags_cxx("-Wno-error=exit-time-destructors")
+ add_flags_cxx("-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()
diff --git a/src/BlockEntities/SignEntity.cpp b/src/BlockEntities/SignEntity.cpp
index 97fed0f04..23d9ef926 100644
--- a/src/BlockEntities/SignEntity.cpp
+++ b/src/BlockEntities/SignEntity.cpp
@@ -15,6 +15,7 @@
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)
{
+ ASSERT((a_Y >= 0) && (a_Y < cChunkDef::Height));
}
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 9fb178bc3..99e48df95 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -71,7 +71,7 @@ cChunk::cChunk(
cChunk * a_NeighborXM, cChunk * a_NeighborXP, cChunk * a_NeighborZM, cChunk * a_NeighborZP,
cAllocationPool<cChunkData::sChunkSection> & a_Pool
) :
- m_IsValid(false),
+ m_Presence(cpInvalid),
m_IsLightValid(false),
m_IsDirty(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_World->GetChunkMap()->ChunkValidated();
+ m_Presence = a_Presence;
+ if (a_Presence == cpPresent)
+ {
+ 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)
{
+ // Set as queued again:
+ SetPresence(cpQueued);
+
// Tell all clients attached to this chunk that they want this chunk:
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr)
{
@@ -191,7 +205,11 @@ void cChunk::MarkRegenerating(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)
{
m_IsDirty = false;
- SetValid();
+ SetPresence(cpPresent);
}
@@ -232,12 +250,17 @@ void cChunk::MarkLoaded(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)
{
+ ASSERT(m_Presence == cpPresent);
+
a_Callback.HeightMap(&m_HeightMap);
a_Callback.BiomeData(&m_BiomeMap);
@@ -272,6 +297,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
{
ASSERT(a_SetChunkData.IsHeightMapValid());
ASSERT(a_SetChunkData.AreBiomesValid());
+ ASSERT(IsQueued());
memcpy(m_BiomeMap, a_SetChunkData.GetBiomes(), sizeof(m_BiomeMap));
memcpy(m_HeightMap, a_SetChunkData.GetHeightMap(), sizeof(m_HeightMap));
@@ -317,7 +343,7 @@ void cChunk::SetAllData(cSetChunkData & a_SetChunkData)
CreateBlockEntities();
// 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:
WakeUpSimulators();
@@ -1319,11 +1345,11 @@ void cChunk::CreateBlockEntities(void)
case E_BLOCK_JUKEBOX:
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(
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;
@@ -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)
{
- 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);
}
diff --git a/src/Chunk.h b/src/Chunk.h
index 0f4928b90..f282694c2 100644
--- a/src/Chunk.h
+++ b/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:
+ /** 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(
int a_ChunkX, int a_ChunkZ, // Chunk coords
cChunkMap * a_ChunkMap, cWorld * a_World, // Parent objects
@@ -75,11 +83,25 @@ public:
cChunk(cChunk & other);
~cChunk();
- bool IsValid(void) const {return m_IsValid; } // Returns true if the chunk block data is valid (loaded / generated)
- void SetValid(void); // Also wakes up any calls to cChunkMap::GetHeight()
- 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
- bool HasLoadFailed(void) const {return m_HasLoadFailed; } // Returns true if the chunk failed to load and hasn't been generated since then
+ /** Returns true iff the chunk block data is valid (loaded / generated) */
+ bool IsValid(void) const {return (m_Presence == cpPresent); }
+
+ /** Returns true iff the chunk is in the queue for loading / generating */
+ 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 IsLightValid(void) const {return m_IsLightValid; }
@@ -94,7 +116,10 @@ public:
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 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 */
void GetAllData(cChunkDataCallback & a_Callback);
@@ -135,7 +160,6 @@ public:
void TickBlock(int a_RelX, int a_RelY, int a_RelZ);
int GetPosX(void) const { return m_PosX; }
- int GetPosY(void) const { return m_PosY; }
int GetPosZ(void) const { return m_PosZ; }
cWorld * GetWorld(void) const { return m_World; }
@@ -434,7 +458,12 @@ private:
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_IsDirty; // True if the chunk has changed since it was last 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 */
int m_StayCount;
- int m_PosX, m_PosY, m_PosZ;
+ int m_PosX, m_PosZ;
cWorld * m_World;
cChunkMap * m_ChunkMap;
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index 8c765c8c9..9c105c5af 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -145,10 +145,9 @@ cChunkMap::cChunkLayer * cChunkMap::GetLayerForChunk(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());
+ 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)
{
// 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;
}
- 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;
}
@@ -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
- cChunkLayer * Layer = GetLayerForChunk( a_ChunkX, a_ChunkZ);
+ ASSERT(m_CSLayers.IsLockedByCurrentThread()); // m_CSLayers should already be locked by the operation that called us
+
+ cChunkLayer * Layer = GetLayerForChunk(a_ChunkX, a_ChunkZ);
if (Layer == NULL)
{
// 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;
}
- 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;
@@ -200,7 +203,8 @@ cChunkPtr cChunkMap::GetChunkNoGen( 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);
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)
{
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)
{
cCSLock Lock(m_CSLayers);
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 8c564d0de..7354536d4 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -133,6 +133,9 @@ public:
/** Copies the chunk's blocktypes into a_Blocks; returns true if successful */
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 HasChunkAnyClients (int a_ChunkX, int a_ChunkZ);
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 */
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 */
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 756410989..b0da6965a 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -1670,7 +1670,11 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
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.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp
index 175e4ef33..60ad4e3eb 100644
--- a/src/Generating/BioGen.cpp
+++ b/src/Generating/BioGen.cpp
@@ -227,7 +227,7 @@ cBioGenMulticache::cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_Cache
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;
}
@@ -251,7 +251,7 @@ void cBioGenMulticache::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMa
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;
tmp->InitializeBiomeGen(a_IniFile);
diff --git a/src/Generating/BioGen.h b/src/Generating/BioGen.h
index a4cf95a72..20d199611 100644
--- a/src/Generating/BioGen.h
+++ b/src/Generating/BioGen.h
@@ -87,16 +87,20 @@ class cBioGenMulticache :
typedef cBiomeGen super;
public:
- /*
- a_CacheSize defines the size of each singular cache
- a_CachesLength defines how many caches are used for the multicache
+ /*
+ a_CacheSize defines the size of each singular cache
+ 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();
protected:
- size_t m_CachesLength;
- std::vector<cBiomeGen*> m_Caches;
+ typedef std::vector<cBiomeGen *> cBiomeGens;
+
+
+ size_t m_CachesLength;
+ cBiomeGens m_Caches;
+
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp
index 4fa9729ec..d615456c1 100644
--- a/src/Generating/ChunkGenerator.cpp
+++ b/src/Generating/ChunkGenerator.cpp
@@ -112,6 +112,8 @@ void cChunkGenerator::Stop(void)
void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate)
{
+ ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
+
{
cCSLock Lock(m_CS);
@@ -283,7 +285,8 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ)
{
ASSERT(m_PluginInterface != NULL);
ASSERT(m_ChunkSink != NULL);
-
+ ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
+
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h
index e880a6766..190d9e616 100644
--- a/src/Generating/ChunkGenerator.h
+++ b/src/Generating/ChunkGenerator.h
@@ -106,6 +106,10 @@ public:
If this callback returns false, the chunk is not generated.
*/
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;
} ;
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index d70438bf3..69068d231 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -230,29 +230,30 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
// Add a cache, if requested:
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)
- {
- LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
- CacheSize, 4
- );
- CacheSize = 4;
- }
- LOGD("Using a cache for biomegen of size %d.", CacheSize);
- m_UnderlyingBiomeGen = m_BiomeGen;
- if (MultiCacheLength > 0)
- {
- LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength);
- m_BiomeGen = new cBioGenMulticache(m_UnderlyingBiomeGen, CacheSize, MultiCacheLength);
- }
- else
- {
- m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize);
- }
-
+ return;
+ }
+
+ int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 4);
+ if (CacheSize < 4)
+ {
+ LOGWARNING("Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d",
+ CacheSize, 4
+ );
+ CacheSize = 4;
+ }
+ LOGD("Using a cache for biomegen of size %d.", CacheSize);
+ m_UnderlyingBiomeGen = m_BiomeGen;
+ if (MultiCacheLength > 0)
+ {
+ LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength);
+ m_BiomeGen = new cBioGenMulticache(m_UnderlyingBiomeGen, CacheSize, MultiCacheLength);
+ }
+ else
+ {
+ m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize);
}
}
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 1091b877f..f24ef320d 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -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)
{
ASSERT(m_State == 3); // In game mode?
+ ASSERT((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height));
cPacketizer Pkt(*this, 0x33);
Pkt.WriteInt(a_BlockX);
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index ccfa19eb6..d3100d0fb 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -71,7 +71,9 @@ public:
virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) 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 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 SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) 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 SendEntityStatus (const cEntity & a_Entity, char a_Status) 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 SendGameMode (eGameMode a_GameMode) override;
virtual void SendHealth (void) override;
@@ -93,10 +97,9 @@ public:
virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators) override;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) 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 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 SendPlayerMaxSpeed (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 SendRemoveEntityEffect (const cEntity & a_Entity, int a_EffectID) 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 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 SendSpawnFallingBlock (const cFallingBlock & a_FallingBlock) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override;
diff --git a/src/SetChunkData.cpp b/src/SetChunkData.cpp
index bfe59fbcb..707dfb9e8 100644
--- a/src/SetChunkData.cpp
+++ b/src/SetChunkData.cpp
@@ -44,7 +44,6 @@ cSetChunkData::cSetChunkData(
// Check the params' validity:
ASSERT(a_BlockTypes != NULL);
ASSERT(a_BlockMetas != NULL);
- ASSERT(a_Biomes != NULL);
// Copy block types and metas:
memcpy(m_BlockTypes, a_BlockTypes, sizeof(cChunkDef::BlockTypes));
diff --git a/src/WebAdmin.cpp b/src/WebAdmin.cpp
index 23eedbd14..341c64236 100644
--- a/src/WebAdmin.cpp
+++ b/src/WebAdmin.cpp
@@ -131,8 +131,24 @@ bool cWebAdmin::Start(void)
m_TemplateScript.RegisterAPILibs();
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_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);
@@ -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)
{
if (!a_Request.HasAuth())
@@ -298,17 +336,64 @@ void cWebAdmin::HandleWebadminRequest(cHTTPConnection & a_Connection, cHTTPReque
void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & 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;
Resp.SetContentType("text/html");
a_Connection.Send(Resp);
- a_Connection.Send(LoginForm, sizeof(LoginForm) - 1);
+ a_Connection.Send(m_LoginTemplate);
+ a_Connection.FinishResponse();
+}
+
+
+
+
+
+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();
}
@@ -316,6 +401,41 @@ void cWebAdmin::HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest &
+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 Page;
@@ -382,6 +502,7 @@ AString cWebAdmin::GetDefaultPage(void)
+
AString cWebAdmin::GetBaseURL( const AString& a_URL)
{
return GetBaseURL(StringSplit(a_URL, "/"));
@@ -528,7 +649,7 @@ void cWebAdmin::OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest &
}
else
{
- // TODO: Handle other requests
+ HandleFileRequest(a_Connection, a_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)
-
diff --git a/src/WebAdmin.h b/src/WebAdmin.h
index aefc1d145..94b95dbcf 100644
--- a/src/WebAdmin.h
+++ b/src/WebAdmin.h
@@ -116,6 +116,9 @@ public:
/** Stops the HTTP server, if it was started. */
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 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) */
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:
/** Common base class for request body data handlers */
class cRequestData
@@ -205,6 +211,9 @@ protected:
/** The Lua template script to provide templates: */
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 */
cHTTPServer m_HTTPServer;
@@ -214,6 +223,9 @@ protected:
/** Handles requests for the root page */
void HandleRootRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
+ /** Handles requests for a file */
+ void HandleFileRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
+
// cHTTPServer::cCallbacks overrides:
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;
diff --git a/src/World.cpp b/src/World.cpp
index 2a3336dee..e669f6fa0 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2374,6 +2374,8 @@ void cWorld::MarkChunkSaved (int a_ChunkX, int a_ChunkZ)
void cWorld::QueueSetChunkData(const cSetChunkDataPtr & a_SetChunkData)
{
+ ASSERT(IsChunkQueued(a_SetChunkData->GetChunkX(), a_SetChunkData->GetChunkZ()));
+
// Validate biomes, if needed:
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
{
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)
{
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)
{
return m_World->HasChunkAnyClients(a_ChunkX, a_ChunkZ);
diff --git a/src/World.h b/src/World.h
index 49932ac9d..6316c6811 100644
--- a/src/World.h
+++ b/src/World.h
@@ -279,7 +279,12 @@ public:
/** Gets the chunk's blocks, only the block types */
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;
/** 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 */
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: */
void ChunkLoadFailed(int a_ChunkX, int a_ChunkZ);
@@ -822,6 +821,7 @@ private:
virtual void OnChunkGenerated (cChunkDesc & a_ChunkDesc) override;
virtual bool IsChunkValid (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:
virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) override;
diff --git a/src/WorldStorage/ScoreboardSerializer.cpp b/src/WorldStorage/ScoreboardSerializer.cpp
index da8236e0d..e30eecf67 100644
--- a/src/WorldStorage/ScoreboardSerializer.cpp
+++ b/src/WorldStorage/ScoreboardSerializer.cpp
@@ -283,37 +283,37 @@ bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT)
bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false;
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");
- 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");
- 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");
- 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");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
{
AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0);
}
CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles");
- if (CurrLine >= 0)
+ if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
{
CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0);
}
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 4d2f92173..fe309ce4e 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -323,7 +323,13 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
return false;
}
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);
return false;
@@ -589,7 +595,7 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
// Get the BlockEntity's position
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.");
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)
{
+ ASSERT((a_BlockY >= 0) && (a_BlockY < cChunkDef::Height));
+
// Load the specific BlockEntity type:
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 ChunkOffset = ChunkLocation >> 8;
- if (ChunkOffset <= 2)
+ if (ChunkOffset < 2)
{
return false;
}
diff --git a/src/WorldStorage/WorldStorage.cpp b/src/WorldStorage/WorldStorage.cpp
index 667a28470..179cf9393 100644
--- a/src/WorldStorage/WorldStorage.cpp
+++ b/src/WorldStorage/WorldStorage.cpp
@@ -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();
}
@@ -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)
{
+ ASSERT(m_World->IsChunkValid(a_ChunkX, a_ChunkZ));
+
m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkZ));
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)
{
- 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)
{
- sChunkLoad ToLoad(0, 0, false);
+ cChunkCoords ToLoad(0, 0);
bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
- if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ))
+
+ if (ShouldLoad)
{
- if (ToLoad.m_Generate)
- {
- // 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 LoadChunk(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)
{
- if (m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
- {
- // Already loaded (can happen, since the queue is async)
- return true;
- }
+ ASSERT(m_World->IsChunkQueued(a_ChunkX, a_ChunkZ));
cChunkCoords Coords(a_ChunkX, a_ChunkZ);
diff --git a/src/WorldStorage/WorldStorage.h b/src/WorldStorage/WorldStorage.h
index 5f89ead53..fc7e9f84c 100644
--- a/src/WorldStorage/WorldStorage.h
+++ b/src/WorldStorage/WorldStorage.h
@@ -64,12 +64,9 @@ public:
cWorldStorage(void);
~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);
- /// 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 UnqueueSave(const cChunkCoords & a_Chunk);
@@ -84,38 +81,10 @@ public:
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;
AString m_StorageSchemaName;
- sChunkLoadQueue m_LoadQueue;
+ cChunkCoordsQueue m_LoadQueue;
cChunkCoordsQueue m_SaveQueue;
/// All the storage schemas (all used for loading)
@@ -123,7 +92,11 @@ protected:
/// The one storage schema used for saving
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);
virtual void Execute(void) override;