Merge branch 'master' into c++11Events
@ -37,6 +37,21 @@ if(DEFINED ENV{MCSERVER_BUILD_ID})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We need C++11 features, Visual Studio has those from VS2012, but it needs a new platform toolset for those; VS2013 supports them natively:
|
||||
# Adapted from http://binglongx.wordpress.com/2013/06/28/set-non-default-platform-toolset-in-cmake/
|
||||
if(MSVC OR MSVC_IDE)
|
||||
if( MSVC_VERSION LESS 1700 ) # VC10- / VS2010-
|
||||
message(FATAL_ERROR "The project requires C++11 features. "
|
||||
"You need at least Visual Studio 11 (Microsoft Visual Studio 2012), "
|
||||
"with Microsoft Visual C++ Compiler Nov 2012 CTP (v120_CTP_Nov2012).")
|
||||
elseif( MSVC_VERSION EQUAL 1700 ) # VC11 / VS2012
|
||||
message( "VC11: using Microsoft Visual Studio 2012 "
|
||||
"with Microsoft Visual C++ Compiler Nov 2012 CTP (v120_CTP_Nov2012)" )
|
||||
set(CMAKE_GENERATOR_TOOLSET "v120_CTP_Nov2012" CACHE STRING "Platform Toolset" FORCE)
|
||||
else() # VC12+, assuming C++11 supported.
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This has to be done before any flags have been set up.
|
||||
if(${BUILD_TOOLS})
|
||||
add_subdirectory(Tools/MCADefrag/)
|
||||
|
@ -123,35 +123,47 @@ return
|
||||
|
||||
cSplashPotionEntity =
|
||||
{
|
||||
Desc = "",
|
||||
Functions = {},
|
||||
Desc = [[
|
||||
Represents a thrown splash potion.
|
||||
]],
|
||||
Functions =
|
||||
{
|
||||
GetEntityEffect = { Params = "", Return = "{{cEntityEffect}}", Notes = "Returns the entity effect in this potion" },
|
||||
GetEntityEffectType = { Params = "", Return = "{{cEntityEffect|Entity effect type}}", Notes = "Returns the effect type of this potion" },
|
||||
GetPotionColor = { Params = "", Return = "number", Notes = "Returns the color index of the particles emitted by this potion" },
|
||||
SetEntityEffect = { Params = "{{cEntityEffect}}", Return = "", Notes = "Sets the entity effect for this potion" },
|
||||
SetEntityEffectType = { Params = "{{cEntityEffect|Entity effect type}}", Return = "", Notes = "Sets the effect type of this potion" },
|
||||
SetPotionColor = { Params = "number", Return = "", Notes = "Sets the color index of the particles for this potion" },
|
||||
},
|
||||
Inherits = "cProjectileEntity",
|
||||
}, -- cSplashPotionEntity
|
||||
|
||||
cThrownEggEntity =
|
||||
{
|
||||
Desc = "",
|
||||
Desc = [[
|
||||
Represents a thrown egg.
|
||||
]],
|
||||
Functions = {},
|
||||
Inherits = "cProjectileEntity",
|
||||
}, -- cThrownEggEntity
|
||||
|
||||
cThrownEnderPearlEntity =
|
||||
{
|
||||
Desc = "",
|
||||
Desc = "Represents a thrown ender pearl.",
|
||||
Functions = {},
|
||||
Inherits = "cProjectileEntity",
|
||||
}, -- cThrownEnderPearlEntity
|
||||
|
||||
cThrownSnowballEntity =
|
||||
{
|
||||
Desc = "",
|
||||
Desc = "Represents a thrown snowball.",
|
||||
Functions = {},
|
||||
Inherits = "cProjectileEntity",
|
||||
}, -- cThrownSnowballEntity
|
||||
|
||||
cWitherSkullEntity =
|
||||
{
|
||||
Desc = "",
|
||||
Desc = "Represents a wither skull being shot.",
|
||||
Functions = {},
|
||||
Inherits = "cProjectileEntity",
|
||||
}, -- cWitherSkullEntity
|
||||
|
2
MCServer/webadmin/files/guest.html
Normal file
@ -0,0 +1,2 @@
|
||||
Hello! Welcome to the MCServer WebAdmin.<br>
|
||||
This is a default message, edit <b>files/guest.html</b> to add your own custom message.
|
BIN
MCServer/webadmin/files/header.png
Normal file
After Width: | Height: | Size: 221 B |
BIN
MCServer/webadmin/files/home.gif
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
MCServer/webadmin/files/loading.gif
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
MCServer/webadmin/files/log_out.png
Normal file
After Width: | Height: | Size: 995 B |
219
MCServer/webadmin/files/login.css
Normal file
@ -0,0 +1,219 @@
|
||||
/* Copyright Justin S and MCServer Team, licensed under CC-BY-SA 3.0 */
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
background: #fff url(header.png) repeat-x top left;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover, a:active {
|
||||
color: #000;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #069;
|
||||
}
|
||||
|
||||
.row1 {
|
||||
border-bottom: 1px solid #000;
|
||||
height: 100px;
|
||||
max-height: 100px;
|
||||
}
|
||||
|
||||
.row2 {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.contention {
|
||||
color: #000;
|
||||
text-align: left;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
button {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #ccc;
|
||||
padding: 3px;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
margin: -3px 0;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border-top-color: #28597a;
|
||||
background: #28597a;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
button:active {
|
||||
border-top-color: #1b435e;
|
||||
background: #1b435e;
|
||||
}
|
||||
|
||||
.push10 {
|
||||
padding-bottom: 75px;
|
||||
}
|
||||
|
||||
#panel .upper {
|
||||
background: #dcdbdc url(tcat.png) repeat-x;
|
||||
border-top: 1px solid #fff;
|
||||
border-bottom: 1px solid #bbb;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
#footer {
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
#footer ul.menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#footer ul.menu li {
|
||||
margin: 0 5px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#footer .upper {
|
||||
background: #dcdbdc url(tcat.png) repeat-x;
|
||||
border-top: 1px solid #bbb;
|
||||
padding: 6px;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#footer .upper ul.bottom_links {
|
||||
float: left;
|
||||
margin: 3px 0 0 -5px;
|
||||
}
|
||||
|
||||
#footer .lower {
|
||||
background: #a1a2a2 url(thead.png) top left repeat-x;
|
||||
color: #fff;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ddd;
|
||||
overflow: hidden;
|
||||
padding: 8px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#footer .lower a:link, #footer .lower a:visited {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#footer .lower a:hover, #footer .lower a:active {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#footer .lower #current_time {
|
||||
float: right;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width: 85%;
|
||||
min-width: 970px;
|
||||
max-width: 1500px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
background: #999;
|
||||
border-top: 1px #000 solid;
|
||||
}
|
||||
|
||||
* html #footer {
|
||||
position: absolute;
|
||||
top: expression((0-(footer.offsetHeight)+(document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight)+(ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop))+'px');
|
||||
}
|
||||
|
||||
tr td.trow2:first-child {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
tr td.trow2:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.tborder {
|
||||
-moz-border-radius: 7px;
|
||||
-webkit-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.thead, .rounded_top {
|
||||
-moz-border-radius-topleft: 6px;
|
||||
-moz-border-radius-topright: 6px;
|
||||
-webkit-border-top-left-radius: 6px;
|
||||
-webkit-border-top-right-radius: 6px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
table {
|
||||
color: #000;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tborder {
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
border: 1px solid #ccc;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.thead {
|
||||
background: #a1a2a2 url(thead.png) top left repeat-x;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #8e8f8f;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.trow2 {
|
||||
background: #efefef;
|
||||
border: 1px solid;
|
||||
border-color: #fff #ddd #ddd #fff;
|
||||
}
|
||||
|
||||
.padtopp {
|
||||
padding-top: 25px;
|
||||
}
|
BIN
MCServer/webadmin/files/login.gif
Normal file
After Width: | Height: | Size: 586 B |
BIN
MCServer/webadmin/files/logo_login.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
MCServer/webadmin/files/pmfolder.gif
Normal file
After Width: | Height: | Size: 995 B |
@ -1,353 +1,433 @@
|
||||
body, html
|
||||
{
|
||||
font-family: "Open Sans", Tahoma, sans-serif;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
background-color: #fbe9e7;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
/* Copyright Justin S and MCServer Team, licensed under CC-BY-SA 3.0 */
|
||||
* {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.light { font-weight: 300; }
|
||||
.bold { font-weight: 600; }
|
||||
|
||||
#wrapper
|
||||
{
|
||||
background-color: #ff5722;
|
||||
margin: 40px auto;
|
||||
width: 99%;
|
||||
max-width: 1200px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-shadow: 0px 4px 5px rgba(0, 0, 0, 0.15);
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
body {
|
||||
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.title
|
||||
{
|
||||
font-size: 30pt;
|
||||
padding: 10px 40px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3);
|
||||
display: block;
|
||||
a:link {
|
||||
color: #555;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#sidebar
|
||||
{
|
||||
float: left;
|
||||
width: 20%;
|
||||
a:visited {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sideNav
|
||||
{
|
||||
list-style: none;
|
||||
background-color: #fafafa;
|
||||
margin: 20px 0;
|
||||
padding: 5px 0;
|
||||
width: 100%;
|
||||
box-shadow: 1px 0px 10px rgba(0, 0, 0, 0.2);
|
||||
a:hover, a:active {
|
||||
color: #000;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.sideNav li
|
||||
{
|
||||
padding: 10px;
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.sideNav li.link
|
||||
{
|
||||
padding-left: 30px;
|
||||
h1 {
|
||||
color: #069;
|
||||
text-shadow: 2px 2px #000;
|
||||
}
|
||||
|
||||
.sideNav li.link a
|
||||
{
|
||||
text-decoration: none;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
.row1 {
|
||||
border-bottom: 1px #000 solid;
|
||||
height: 100px;
|
||||
max-height: 100px;
|
||||
background: #fff url(header.png) repeat-x top left;
|
||||
}
|
||||
|
||||
#container
|
||||
{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background-color: #f5f5f5;
|
||||
.row2 {
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
margin-top: 125px;
|
||||
}
|
||||
|
||||
#main
|
||||
{
|
||||
float: right;
|
||||
width: 80%;
|
||||
padding: 0 15px 20px 15px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
.contention {
|
||||
color: #000;
|
||||
text-align: left;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.clear
|
||||
{
|
||||
clear: both;
|
||||
.push10 {
|
||||
padding-bottom: 75px;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
#panel ul.menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
table td
|
||||
{
|
||||
padding: 5px;
|
||||
#panel ul.menu li {
|
||||
margin: 0 5px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
table th
|
||||
{
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
#panel ul.menu li a {
|
||||
padding-left: 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
table tr:nth-child(odd)
|
||||
{
|
||||
background-color: rgba(0, 0, 0, 0.015);
|
||||
#panel .upper ul.top_links {
|
||||
float: right;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
p
|
||||
{
|
||||
margin: 8px 0;
|
||||
padding: 8px 3px;
|
||||
#panel .upper {
|
||||
background: #dcdbdc url(tcat.png) repeat-x;
|
||||
border-top: 1px solid #fff;
|
||||
border-bottom: 1px solid #bbb;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
text-decoration: none;
|
||||
color: #0277bd;
|
||||
-webkit-transition: color 0.1s linear;
|
||||
-moz-transition: color 0.1s linear;
|
||||
transition: color 0.1s linear;
|
||||
#footer {
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
color: #01579b;
|
||||
#footer ul.menu {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.welcome-msg
|
||||
{
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
#footer ul.menu li {
|
||||
margin: 0 5px;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.username
|
||||
{
|
||||
text-transform: capitalize;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
#footer .upper {
|
||||
background: #dcdbdc url(tcat.png) repeat-x;
|
||||
border-top: 1px solid #bbb;
|
||||
padding: 6px;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
color: black;
|
||||
#footer .upper ul.bottom_links {
|
||||
float: left;
|
||||
margin: 3px 0 0 -5px;
|
||||
}
|
||||
|
||||
input, select
|
||||
{
|
||||
padding: 8px;
|
||||
#footer .lower {
|
||||
background: #a1a2a2 url(thead.png) top left repeat-x;
|
||||
color: #fff;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ddd;
|
||||
overflow: hidden;
|
||||
padding: 8px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
form
|
||||
{
|
||||
padding: 4px;
|
||||
#footer .lower a:link,#footer .lower a:visited {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.info input[type="submit"], .info button, .info input[type="button"],
|
||||
.warn input[type="submit"], .warn button, .warn input[type="button"],
|
||||
.err input[type="submit"], .err button, .err input[type="button"]
|
||||
{
|
||||
float: right;
|
||||
#footer .lower a:hover,#footer .lower a:active {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.err
|
||||
{
|
||||
color: white;
|
||||
display: block;
|
||||
background-color: #e51c23 !important;
|
||||
padding: 15px;
|
||||
line-height: 30px;
|
||||
min-height: 30px;
|
||||
#footer .lower #current_time {
|
||||
float: right;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.err:before
|
||||
{
|
||||
content: "ERROR: ";
|
||||
.wrapper {
|
||||
width: 85%;
|
||||
min-width: 970px;
|
||||
max-width: 1500px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.warn
|
||||
{
|
||||
color: white;
|
||||
display: block;
|
||||
background-color: #ff5722 !important;
|
||||
padding: 15px;
|
||||
line-height: 30px;
|
||||
min-height: 30px;
|
||||
#footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
background: #999;
|
||||
border-top: 1px #000 solid;
|
||||
}
|
||||
|
||||
.warn:before
|
||||
{
|
||||
content: "WARNING: ";
|
||||
* html #footer {
|
||||
position: absolute;
|
||||
top: expression((0-(footer.offsetHeight)+(document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight)+(ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop))+'px');
|
||||
}
|
||||
|
||||
.info
|
||||
{
|
||||
color: white;
|
||||
display: block;
|
||||
background-color: #5677fc !important;
|
||||
padding: 15px;
|
||||
line-height: 30px;
|
||||
min-height: 30px;
|
||||
tr td.trow1:first-child, tr td.trow2:first-child {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.info:before
|
||||
{
|
||||
content: "INFORMATION: ";
|
||||
tr td.trow1:last-child, tr td.trow2:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
#footer .fleft
|
||||
{
|
||||
float: left;
|
||||
.tborder {
|
||||
-moz-border-radius: 7px;
|
||||
-webkit-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
#footer .fright
|
||||
{
|
||||
float: right;
|
||||
text-align: right;
|
||||
.thead {
|
||||
-moz-border-radius-topleft: 6px;
|
||||
-moz-border-radius-topright: 6px;
|
||||
-webkit-border-top-left-radius: 6px;
|
||||
-webkit-border-top-right-radius: 6px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
#footer
|
||||
{
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
font-size: 9pt;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.2) inset;
|
||||
table {
|
||||
color: #000;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#footer a
|
||||
{
|
||||
text-transform: none;
|
||||
color: white;
|
||||
.tborder {
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
border: 1px solid #ccc;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
input[type="submit"], button, input[type="button"]
|
||||
{
|
||||
background-color: #ffc107;
|
||||
padding: 8px 15px 8px 15px;
|
||||
margin: 0 2px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: black;
|
||||
box-shadow: 0px 2px 3px rgba(0,0,0,0.2);
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
.thead {
|
||||
background: #a1a2a2 url(thead.png) top left repeat-x;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #8e8f8f;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover, button:hover, input[type="button"]:hover
|
||||
{
|
||||
background-color: #ffca28;
|
||||
.tcat {
|
||||
background: #dcdbdc url(tcat.png) repeat-x;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #bbb;
|
||||
padding: 6px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
input[type="submit"]:active, button:active, input[type="button"]:active
|
||||
{
|
||||
background-color: #ffd54f;
|
||||
-webkit-transform: translateY(1px);
|
||||
-moz-transform: translateY(1px);
|
||||
transform: translateY(1px);
|
||||
.trow1 {
|
||||
background: #f5f5f5;
|
||||
border: 1px solid;
|
||||
border-color: #fff #ddd #ddd #fff;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
border: none;
|
||||
height: 1px;
|
||||
background-color: rgba(0, 0, 0, 0.12);
|
||||
.trow2 {
|
||||
background: #efefef;
|
||||
border: 1px solid;
|
||||
border-color: #fff #ddd #ddd #fff;
|
||||
padding: 15px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
h4
|
||||
{
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 12px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
.padtopp {
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
|
||||
/**** PAGE SPECIFIC CSS ****/
|
||||
|
||||
/* remove the * for disabling: */
|
||||
|
||||
.page-core-server-settings table td
|
||||
{
|
||||
text-align: center;
|
||||
width: 25%;
|
||||
table {
|
||||
color: #000;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.page-core-server-settings.no-param table td:nth-child(1) a,
|
||||
.page-core-server-settings.param-tab-general table td:nth-child(1) a
|
||||
{
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
.tborder {
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
border: 1px solid #ccc;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.page-core-server-settings.param-tab-monsters table td:nth-child(2) a
|
||||
{
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
.thead {
|
||||
background: #a1a2a2 url(thead.png) top left repeat-x;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #8e8f8f;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.page-core-server-settings.param-tab-worlds table td:nth-child(3) a
|
||||
{
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
.tcat {
|
||||
background: #dcdbdc url(tcat.png) repeat-x;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #bbb;
|
||||
padding: 6px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.page-core-server-settings.param-tab-world table td:nth-child(4) a
|
||||
{
|
||||
font-weight: 600;
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
.trow1 {
|
||||
background: #f5f5f5;
|
||||
border: 1px solid;
|
||||
border-color: #fff #ddd #ddd #fff;
|
||||
}
|
||||
|
||||
.page-core-permissions form table tr,
|
||||
.page-core-permissions form table td,
|
||||
.page-core-permissions form table th
|
||||
{
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
.trow2 {
|
||||
background: #efefef;
|
||||
border: 1px solid;
|
||||
border-color: #fff #ddd #ddd #fff;
|
||||
}
|
||||
|
||||
.page-core-permissions form table tr:nth-child(1) th
|
||||
{
|
||||
width: 35%;
|
||||
.smalltext {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.page-core-permissions form table tr:nth-child(1) td
|
||||
{
|
||||
width: 65%;
|
||||
textarea {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #ccc;
|
||||
padding: 2px;
|
||||
line-height: 1.4;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.page-core-permissions form table td input
|
||||
{
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
margin: 0;
|
||||
select {
|
||||
background: #fff;
|
||||
padding: 3px;
|
||||
border: 1px solid #ccc;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
}
|
||||
|
||||
#ChatDiv
|
||||
{
|
||||
margin-bottom: 10px;
|
||||
.usercp_nav_item {
|
||||
display: block;
|
||||
padding: 1px 0 1px 23px;
|
||||
}
|
||||
|
||||
#ChatMessage
|
||||
{
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
.usercp_nav_pmfolder {
|
||||
background: url(pmfolder.gif) no-repeat left center;
|
||||
}
|
||||
|
||||
/**/
|
||||
.usercp_nav_sub_pmfolder {
|
||||
padding-left: 40px;
|
||||
background: url(sub_pmfolder.gif) no-repeat left center;
|
||||
}
|
||||
|
||||
.usercp_nav_home {
|
||||
background: url(home.gif) no-repeat left center;
|
||||
}
|
||||
|
||||
.pagehead {
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table th {
|
||||
border-bottom: 1px solid rgba(0,0,0,0.12);
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table tr:nth-child(odd) {
|
||||
background-color: rgba(0,0,0,0.015);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 4px 0;
|
||||
padding: 4px 3px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
-webkit-transition: color .1s linear;
|
||||
-moz-transition: color .1s linear;
|
||||
transition: color .1s linear;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
border: 1px solid #ccc;
|
||||
padding: 2px;
|
||||
line-height: 1.4;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
font-size: 13px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
input[type="text"]:hover {
|
||||
background-color: #E5E4E2;
|
||||
}
|
||||
|
||||
input[type="text"]:focus {
|
||||
background-color: #E5E4E2;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
height: 1px;
|
||||
background-color: rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
h4 {
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 12px;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
#ChatDiv {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#ChatMessage {
|
||||
width: 92%;
|
||||
margin-right: 5px;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
padding: 3px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
cursor: pointer;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover {
|
||||
background-color: #E5E4E2;
|
||||
}
|
||||
|
||||
button:disabled,input:disabled {
|
||||
padding: 3px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
cursor: pointer;
|
||||
font-family: Tahoma,Verdana,Arial,Sans-Serif;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
border: none!important;
|
||||
color: #fff!important;
|
||||
background-color: #ccc!important;
|
||||
}
|
||||
|
BIN
MCServer/webadmin/files/sub_pmfolder.gif
Normal file
After Width: | Height: | Size: 1022 B |
BIN
MCServer/webadmin/files/tcat.png
Normal file
After Width: | Height: | Size: 183 B |
BIN
MCServer/webadmin/files/thead.png
Normal file
After Width: | Height: | Size: 132 B |
@ -1,25 +1,70 @@
|
||||
/* Copyright Justin S and MCServer Team, licensed under CC-BY-SA 3.0 */
|
||||
<html>
|
||||
<head>
|
||||
<title>MCServer WebAdmin - Login</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link href="login.css" rel="stylesheet" type="text/css">
|
||||
<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>
|
||||
<div class="contention">
|
||||
<div class="row1">
|
||||
<div class="wrapper">
|
||||
<img src="logo_login.png" alt="MCServer Logo" class="logo">
|
||||
</div>
|
||||
</div>
|
||||
<div id="panel">
|
||||
<div class="upper">
|
||||
<div class="wrapper">
|
||||
<div>
|
||||
<form method="get" action="webadmin/" />
|
||||
<button type="submit" value="Log in" style="width:150px;height:25px;font-family:'Source Sans Pro',sans-serif;background:transparent;border:none!important;vertical-align:middle">
|
||||
<strong><img src="login.gif" style="vertical-align:bottom" /> WebAdmin Log in</strong>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2 push10">
|
||||
<div class="wrapper padtopp">
|
||||
<table border="0" cellspacing="0" cellpadding="5" class="tborder" style="margin-bottom:5px">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="thead rounded_top">
|
||||
<div style="float:left!important"><strong>MCServer WebAdmin</strong></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="trow2 post_content">
|
||||
<div class="post_body">
|
||||
<iframe width="100%" height="100%" style="border:none;min-height:350px;max-height:450px" src="/guest.html"></iframe>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<div class="upper">
|
||||
<div class="wrapper">
|
||||
<ul class="menu bottom_links">
|
||||
<li><a href="http://www.mc-server.org" target="_blank">MCServer</a></li>
|
||||
<li><a href="http://forum.mc-server.org" target="_blank">Forums</a></li>
|
||||
<li><a href="http://builds.cuberite.org" target="_blank">Buildserver</a></li>
|
||||
<li><a href="http://mc-server.xoft.cz/LuaAPI" target="_blank">API Documentation</a></li>
|
||||
<li><a href="http://book.mc-server.org/" target="_blank">User's Manual</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lower">
|
||||
<div class="wrapper">
|
||||
<span id="current_time"><strong>Current time:</strong> <script type="text/javascript">document.write('Time: <strong><span id="date-time">',new Date().toLocaleString(),"</span></strong>");if(document.getElementById){onload=function(){setInterval("document.getElementById ('date-time').firstChild.data = new Date().toLocaleString()",50)}};</script></span>
|
||||
<span id="copyright">Copyright © <a href="http://www.mc-server.org" target="_blank">MCServer Team</a> 2014.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
1
MCServer/webadmin/temp.html
Normal file
@ -0,0 +1 @@
|
||||
|
@ -81,22 +81,56 @@ function ShowPage(WebAdmin, TemplateRequest)
|
||||
end
|
||||
|
||||
Output([[
|
||||
<!DOCTYPE html>
|
||||
/* Copyright Justin S and MCServer Team, licensed under CC-BY-SA 3.0 */
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<title>]] .. Title .. [[</title>
|
||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600,300' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||
<title>]] .. Title .. [[</title>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<div id="containerHolder">
|
||||
<a href="./" class="title light">MCServer</a>
|
||||
<div id="container">
|
||||
<div id="sidebar">
|
||||
<ul class="sideNav">
|
||||
<li class='link'><a href=']] .. BaseURL .. [['>Home</a></li>
|
||||
<div class="contention">
|
||||
<div class="pagehead">
|
||||
<div class="row1">
|
||||
<div class="wrapper">
|
||||
<img src="/logo_login.png" alt="MCServer Logo" class="logo">
|
||||
</div>
|
||||
</div>
|
||||
<div id="panel">
|
||||
<div class="upper">
|
||||
<div class="wrapper">
|
||||
<ul class="menu top_links">
|
||||
<li><a>Server Name: <strong>]] .. cRoot:Get():GetServer():GetServerID() .. [[</strong></a></li>
|
||||
<li><a>Memory: <strong>]] .. MemoryUsageKiB / 1024 .. [[MB</strong></a></li>
|
||||
<li><a>Chunks: <strong>]] .. NumChunks .. [[</strong></a></li>
|
||||
</ul>
|
||||
<div class="welcome"><strong>Welcome back, ]] .. TemplateRequest.Request.Username .. [[</strong> <a href=".././"><img src="/log_out.png" style="vertical-align:bottom;"> Log Out</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2 push10">
|
||||
<div class="wrapper padtopp">
|
||||
<table width="100%" border="0" align="center">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="180" valign="top">
|
||||
<table border="0" cellspacing="0" cellpadding="5" class="tborder">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="thead"><strong>Menu</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="trow1 smalltext"><a href=']] .. BaseURL .. [[' class='usercp_nav_item usercp_nav_home'>Home</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tcat"><div><span class="smalltext"><strong><font color="#000">Server Management</font></strong></span></div></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody style="" id="usercppms_e">
|
||||
<tr>
|
||||
<td class="trow1 smalltext">
|
||||
]])
|
||||
|
||||
|
||||
@ -105,30 +139,59 @@ function ShowPage(WebAdmin, TemplateRequest)
|
||||
local PluginWebTitle = value:GetWebTitle()
|
||||
local TabNames = value:GetTabNames()
|
||||
if (GetTableSize(TabNames) > 0) then
|
||||
Output("<li>"..PluginWebTitle.."</li>\n");
|
||||
Output("<div><a class='usercp_nav_item usercp_nav_pmfolder' style='text-decoration:none;'><b>"..PluginWebTitle.."</b></a></div>\n");
|
||||
|
||||
for webname,prettyname in pairs(TabNames) do
|
||||
Output("<li class='link'><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "'>" .. prettyname .. "</a></li>\n")
|
||||
Output("<div><a href='" .. BaseURL .. PluginWebTitle .. "/" .. webname .. "' class='usercp_nav_item usercp_nav_sub_pmfolder'>" .. prettyname .. "</a></div>\n")
|
||||
end
|
||||
|
||||
Output("<br>\n");
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Output([[
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="main" class="page-]] .. string.lower(PluginPage.PluginName .. "-" .. string.gsub(PluginPage.TabName, "[^a-zA-Z0-9]+", "-")) .. reqParamsClass .. [[">
|
||||
<h2 class="welcome-msg">Welcome <span class="username">]] .. TemplateRequest.Request.Username .. [[</span></h2>
|
||||
|
||||
<hr/>
|
||||
|
||||
<h3>]] .. SubTitle .. [[</h3>
|
||||
]] .. PageContent .. [[</div>
|
||||
<div class="clear"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
<td valign="top" style='padding-left:25px;'>
|
||||
<table border="0" cellspacing="0" cellpadding="5" class="tborder">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="thead" colspan="2"><strong>]] .. SubTitle .. [[</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="trow2">]] .. PageContent .. [[</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
<div class="upper">
|
||||
<div class="wrapper">
|
||||
<ul class="menu bottom_links">
|
||||
<li><a href="http://www.mc-server.org" target="_blank">MCServer</a></li>
|
||||
<li><a href="http://forum.mc-server.org" target="_blank">Forums</a></li>
|
||||
<li><a href="http://builds.cuberite.org" target="_blank">Buildserver</a></li>
|
||||
<li><a href="http://mc-server.xoft.cz/LuaAPI" target="_blank">API Documentation</a></li>
|
||||
<li><a href="http://book.mc-server.org/" target="_blank">User's Manual</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lower">
|
||||
<div class="wrapper">
|
||||
<span id="current_time"><strong>Current time:</strong> <script type="text/javascript">document.write('Time: <strong><span id="date-time">',new Date().toLocaleString(),"</span></strong>");if(document.getElementById){onload=function(){setInterval("document.getElementById ('date-time').firstChild.data = new Date().toLocaleString()",50)}};</script></span>
|
||||
<span id="copyright">Copyright © <a href="http://www.mc-server.org" target="_blank">MCServer Team</a> 2014.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer"><div class="fleft">running MCServer using <span class="bold">]] .. MemoryUsageKiB / 1024 .. [[MB</span> of memory; <span class="bold">]] .. NumChunks .. [[</span> chunks</div><div class="fright">design by <a href="//www.github.com/WebFreak001">WebFreak001</a></div><div class="clear"></div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -10,6 +10,8 @@ We currently support Release 1.7 and 1.8 (not beta) Minecraft protocol versions.
|
||||
Installation
|
||||
------------
|
||||
|
||||
[![Install on DigitalOcean](http://doinstall.bearbin.net/button.svg)](http://doinstall.bearbin.net/install?url=https://github.com/mc-server/MCServer)
|
||||
|
||||
For Linux there is an easy installation method, just run this in your terminal:
|
||||
|
||||
curl -s https://raw.githubusercontent.com/mc-server/MCServer/master/easyinstall.sh | sh
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include "Globals.h"
|
||||
#include "BiomeView.h"
|
||||
#include "QtChunk.h"
|
||||
#include <QPainter>
|
||||
#include <QResizeEvent>
|
||||
#include "Region.h"
|
||||
|
||||
|
||||
|
||||
@ -14,6 +14,116 @@ static const int DELTA_STEP = 120; // The normal per-notch wheel delta
|
||||
|
||||
|
||||
|
||||
/** Map for converting biome values to colors. Initialized from biomeColors[]. */
|
||||
static uchar biomeToColor[256 * 4];
|
||||
|
||||
/** Map for converting biome values to colors. Used to initialize biomeToColor[].*/
|
||||
static struct
|
||||
{
|
||||
EMCSBiome m_Biome;
|
||||
uchar m_Color[3];
|
||||
} biomeColors[] =
|
||||
{
|
||||
{ biOcean, { 0x00, 0x00, 0x70 }, },
|
||||
{ biPlains, { 0x8d, 0xb3, 0x60 }, },
|
||||
{ biDesert, { 0xfa, 0x94, 0x18 }, },
|
||||
{ biExtremeHills, { 0x60, 0x60, 0x60 }, },
|
||||
{ biForest, { 0x05, 0x66, 0x21 }, },
|
||||
{ biTaiga, { 0x0b, 0x66, 0x59 }, },
|
||||
{ biSwampland, { 0x2f, 0xff, 0xda }, },
|
||||
{ biRiver, { 0x30, 0x30, 0xaf }, },
|
||||
{ biHell, { 0x7f, 0x00, 0x00 }, },
|
||||
{ biSky, { 0x00, 0x7f, 0xff }, },
|
||||
{ biFrozenOcean, { 0xa0, 0xa0, 0xdf }, },
|
||||
{ biFrozenRiver, { 0xa0, 0xa0, 0xff }, },
|
||||
{ biIcePlains, { 0xff, 0xff, 0xff }, },
|
||||
{ biIceMountains, { 0xa0, 0xa0, 0xa0 }, },
|
||||
{ biMushroomIsland, { 0xff, 0x00, 0xff }, },
|
||||
{ biMushroomShore, { 0xa0, 0x00, 0xff }, },
|
||||
{ biBeach, { 0xfa, 0xde, 0x55 }, },
|
||||
{ biDesertHills, { 0xd2, 0x5f, 0x12 }, },
|
||||
{ biForestHills, { 0x22, 0x55, 0x1c }, },
|
||||
{ biTaigaHills, { 0x16, 0x39, 0x33 }, },
|
||||
{ biExtremeHillsEdge, { 0x7f, 0x8f, 0x7f }, },
|
||||
{ biJungle, { 0x53, 0x7b, 0x09 }, },
|
||||
{ biJungleHills, { 0x2c, 0x42, 0x05 }, },
|
||||
|
||||
{ biJungleEdge, { 0x62, 0x8b, 0x17 }, },
|
||||
{ biDeepOcean, { 0x00, 0x00, 0x30 }, },
|
||||
{ biStoneBeach, { 0xa2, 0xa2, 0x84 }, },
|
||||
{ biColdBeach, { 0xfa, 0xf0, 0xc0 }, },
|
||||
{ biBirchForest, { 0x30, 0x74, 0x44 }, },
|
||||
{ biBirchForestHills, { 0x1f, 0x5f, 0x32 }, },
|
||||
{ biRoofedForest, { 0x40, 0x51, 0x1a }, },
|
||||
{ biColdTaiga, { 0x31, 0x55, 0x4a }, },
|
||||
{ biColdTaigaHills, { 0x59, 0x7d, 0x72 }, },
|
||||
{ biMegaTaiga, { 0x59, 0x66, 0x51 }, },
|
||||
{ biMegaTaigaHills, { 0x59, 0x66, 0x59 }, },
|
||||
{ biExtremeHillsPlus, { 0x50, 0x70, 0x50 }, },
|
||||
{ biSavanna, { 0xbd, 0xb2, 0x5f }, },
|
||||
{ biSavannaPlateau, { 0xa7, 0x9d, 0x64 }, },
|
||||
{ biMesa, { 0xd9, 0x45, 0x15 }, },
|
||||
{ biMesaPlateauF, { 0xb0, 0x97, 0x65 }, },
|
||||
{ biMesaPlateau, { 0xca, 0x8c, 0x65 }, },
|
||||
|
||||
// M variants:
|
||||
{ biSunflowerPlains, { 0xb5, 0xdb, 0x88 }, },
|
||||
{ biDesertM, { 0xff, 0xbc, 0x40 }, },
|
||||
{ biExtremeHillsM, { 0x88, 0x88, 0x88 }, },
|
||||
{ biFlowerForest, { 0x2d, 0x8e, 0x49 }, },
|
||||
{ biTaigaM, { 0x33, 0x8e, 0x81 }, },
|
||||
{ biSwamplandM, { 0x07, 0xf9, 0xb2 }, },
|
||||
{ biIcePlainsSpikes, { 0xb4, 0xdc, 0xdc }, },
|
||||
{ biJungleM, { 0x7b, 0xa3, 0x31 }, },
|
||||
{ biJungleEdgeM, { 0x62, 0x8b, 0x17 }, },
|
||||
{ biBirchForestM, { 0x58, 0x9c, 0x6c }, },
|
||||
{ biBirchForestHillsM, { 0x47, 0x87, 0x5a }, },
|
||||
{ biRoofedForestM, { 0x68, 0x79, 0x42 }, },
|
||||
{ biColdTaigaM, { 0x24, 0x3f, 0x36 }, },
|
||||
{ biMegaSpruceTaiga, { 0x45, 0x4f, 0x3e }, },
|
||||
{ biMegaSpruceTaigaHills, { 0x45, 0x4f, 0x4e }, },
|
||||
{ biExtremeHillsPlusM, { 0x78, 0x98, 0x78 }, },
|
||||
{ biSavannaM, { 0xe5, 0xda, 0x87 }, },
|
||||
{ biSavannaPlateauM, { 0xa7, 0x9d, 0x74 }, },
|
||||
{ biMesaBryce, { 0xff, 0x6d, 0x3d }, },
|
||||
{ biMesaPlateauFM, { 0xd8, 0xbf, 0x8d }, },
|
||||
{ biMesaPlateauM, { 0xf2, 0xb4, 0x8d }, },
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static class BiomeColorsInitializer
|
||||
{
|
||||
public:
|
||||
BiomeColorsInitializer(void)
|
||||
{
|
||||
// Reset all colors to gray:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(biomeToColor); i++)
|
||||
{
|
||||
biomeToColor[i] = 0x7f;
|
||||
}
|
||||
|
||||
// Set known biomes to their colors:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++)
|
||||
{
|
||||
uchar * color = &biomeToColor[4 * biomeColors[i].m_Biome];
|
||||
color[0] = biomeColors[i].m_Color[2];
|
||||
color[1] = biomeColors[i].m_Color[1];
|
||||
color[2] = biomeColors[i].m_Color[0];
|
||||
color[3] = 0xff;
|
||||
}
|
||||
}
|
||||
} biomeColorInitializer;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BiomeView:
|
||||
|
||||
BiomeView::BiomeView(QWidget * parent) :
|
||||
super(parent),
|
||||
m_X(0),
|
||||
@ -40,7 +150,7 @@ BiomeView::BiomeView(QWidget * parent) :
|
||||
redraw();
|
||||
|
||||
// Add a chunk-update callback mechanism:
|
||||
connect(&m_Cache, SIGNAL(chunkAvailable(int, int)), this, SLOT(chunkAvailable(int, int)));
|
||||
connect(&m_Cache, SIGNAL(regionAvailable(int, int)), this, SLOT(regionAvailable(int, int)));
|
||||
|
||||
// Allow mouse and keyboard interaction:
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
@ -143,9 +253,15 @@ void BiomeView::redraw()
|
||||
|
||||
|
||||
|
||||
void BiomeView::chunkAvailable(int a_ChunkX, int a_ChunkZ)
|
||||
void BiomeView::regionAvailable(int a_RegionX, int a_RegionZ)
|
||||
{
|
||||
drawChunk(a_ChunkX, a_ChunkZ);
|
||||
for (int z = 0; z < 32; z++)
|
||||
{
|
||||
for (int x = 0; x < 32; x++)
|
||||
{
|
||||
drawChunk(a_RegionX * 32 + x, a_RegionZ * 32 + z);
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
@ -175,8 +291,11 @@ void BiomeView::drawChunk(int a_ChunkX, int a_ChunkZ)
|
||||
return;
|
||||
}
|
||||
|
||||
//fetch the chunk:
|
||||
ChunkPtr chunk = m_Cache.fetch(a_ChunkX, a_ChunkZ);
|
||||
// Fetch the region:
|
||||
int regionX;
|
||||
int regionZ;
|
||||
Region::chunkToRegion(a_ChunkX, a_ChunkZ, regionX, regionZ);
|
||||
RegionPtr region = m_Cache.fetch(regionX, regionZ);
|
||||
|
||||
// Figure out where on the screen this chunk should be drawn:
|
||||
// first find the center chunk
|
||||
@ -194,11 +313,10 @@ void BiomeView::drawChunk(int a_ChunkX, int a_ChunkZ)
|
||||
centerx += (a_ChunkX - centerchunkx) * chunksize;
|
||||
centery += (a_ChunkZ - centerchunkz) * chunksize;
|
||||
|
||||
int srcoffset = 0;
|
||||
uchar * bits = m_Image.bits();
|
||||
int imgstride = m_Image.bytesPerLine();
|
||||
|
||||
int skipx = 0,skipy = 0;
|
||||
int skipx = 0, skipy = 0;
|
||||
int blockwidth = chunksize, blockheight = chunksize;
|
||||
// now if we're off the screen we need to crop
|
||||
if (centerx < 0)
|
||||
@ -227,29 +345,52 @@ void BiomeView::drawChunk(int a_ChunkX, int a_ChunkZ)
|
||||
int imgoffset = centerx * 4 + centery * imgstride;
|
||||
|
||||
// If the chunk is valid, use its data; otherwise use the empty placeholder:
|
||||
const uchar * src = m_EmptyChunkImage;
|
||||
if (chunk.get() != nullptr)
|
||||
const short * src = m_EmptyChunkBiomes;
|
||||
if (region.get() != nullptr)
|
||||
{
|
||||
src = chunk->getImage();
|
||||
int relChunkX = a_ChunkX - regionX * 32;
|
||||
int relChunkZ = a_ChunkZ - regionZ * 32;
|
||||
Chunk & chunk = region->getRelChunk(relChunkX, relChunkZ);
|
||||
if (chunk.isValid())
|
||||
{
|
||||
src = chunk.getBiomes();
|
||||
}
|
||||
}
|
||||
|
||||
// Blit or scale-blit the image:
|
||||
// Scale-blit the image:
|
||||
for (int z = skipy; z < blockheight; z++, imgoffset += imgstride)
|
||||
{
|
||||
srcoffset = floor((double)z / m_Zoom) * 16 * 4;
|
||||
if (m_Zoom == 1.0)
|
||||
size_t srcoffset = static_cast<size_t>(std::floor((double)z / m_Zoom)) * 16;
|
||||
int imgxoffset = imgoffset;
|
||||
for (int x = skipx; x < blockwidth; x++)
|
||||
{
|
||||
memcpy(bits + imgoffset, src + srcoffset + skipx * 4, (blockwidth - skipx) * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
int xofs = 0;
|
||||
for (int x = skipx; x < blockwidth; x++, xofs +=4)
|
||||
short biome = src[srcoffset + static_cast<size_t>(std::floor((double)x / m_Zoom))];
|
||||
const uchar * color;
|
||||
if (biome < 0)
|
||||
{
|
||||
memcpy(bits + imgoffset + xofs, src + srcoffset + (int)floor((double)x / m_Zoom) * 4, 4);
|
||||
static const uchar emptyBiome1[] = { 0x44, 0x44, 0x44, 0xff };
|
||||
static const uchar emptyBiome2[] = { 0x88, 0x88, 0x88, 0xff };
|
||||
color = ((x & 8) ^ (z & 8)) ? emptyBiome1 : emptyBiome2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (biome * 4 >= ARRAYCOUNT(biomeToColor))
|
||||
{
|
||||
static const uchar errorImage[] = { 0xff, 0x00, 0x00, 0xff };
|
||||
color = errorImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = biomeToColor + biome * 4;
|
||||
}
|
||||
}
|
||||
bits[imgxoffset] = color[0];
|
||||
bits[imgxoffset + 1] = color[1];
|
||||
bits[imgxoffset + 2] = color[2];
|
||||
bits[imgxoffset + 3] = color[3];
|
||||
imgxoffset += 4;
|
||||
} // for x
|
||||
} // for z
|
||||
}
|
||||
|
||||
|
||||
@ -317,11 +458,12 @@ void BiomeView::mouseMoveEvent(QMouseEvent * a_Event)
|
||||
// Update the status bar info text:
|
||||
int blockX = floor((a_Event->x() - width() / 2) / m_Zoom + m_X);
|
||||
int blockZ = floor((a_Event->y() - height() / 2) / m_Zoom + m_Z);
|
||||
int chunkX, chunkZ;
|
||||
int relX = blockX, relY, relZ = blockZ;
|
||||
cChunkDef::AbsoluteToRelative(relX, relY, relZ, chunkX, chunkZ);
|
||||
auto chunk = m_Cache.fetch(chunkX, chunkZ);
|
||||
int biome = (chunk.get() != nullptr) ? chunk->getBiome(relX, relZ) : biInvalidBiome;
|
||||
int regionX, regionZ;
|
||||
Region::blockToRegion(blockX, blockZ, regionX, regionZ);
|
||||
int relX = blockX - regionX * 512;
|
||||
int relZ = blockZ - regionZ * 512;
|
||||
auto region = m_Cache.fetch(regionX, regionZ);
|
||||
int biome = (region.get() != nullptr) ? region->getRelBiome(relX, relZ) : biInvalidBiome;
|
||||
emit hoverChanged(blockX, blockZ, biome);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <QWidget>
|
||||
#include <memory>
|
||||
#include "ChunkCache.h"
|
||||
#include "RegionCache.h"
|
||||
#include "ChunkSource.h"
|
||||
|
||||
|
||||
@ -51,8 +51,8 @@ public slots:
|
||||
/** Redraw the entire widget area. */
|
||||
void redraw();
|
||||
|
||||
/** A specified chunk has become available, redraw it. */
|
||||
void chunkAvailable(int a_ChunkX, int a_ChunkZ);
|
||||
/** A specified region has become available, redraw it. */
|
||||
void regionAvailable(int a_RegionX, int a_RegionZ);
|
||||
|
||||
/** Reloads the current chunk source and redraws the entire workspace. */
|
||||
void reload();
|
||||
@ -62,7 +62,7 @@ protected:
|
||||
double m_Zoom;
|
||||
|
||||
/** Cache for the loaded chunk data. */
|
||||
ChunkCache m_Cache;
|
||||
RegionCache m_Cache;
|
||||
|
||||
/** The entire view's contents in an offscreen image. */
|
||||
QImage m_Image;
|
||||
@ -79,6 +79,9 @@ protected:
|
||||
/** Data used for rendering a chunk that hasn't been loaded yet */
|
||||
uchar m_EmptyChunkImage[16 * 16 * 4];
|
||||
|
||||
/** Data placeholder for chunks that aren't valid. */
|
||||
short m_EmptyChunkBiomes[16 * 16];
|
||||
|
||||
|
||||
/** Draws the specified chunk into m_Image */
|
||||
void drawChunk(int a_ChunkX, int a_ChunkZ);
|
||||
|
@ -1,126 +0,0 @@
|
||||
#include "Globals.h"
|
||||
#include "ChunkCache.h"
|
||||
#include <QMutexLocker>
|
||||
#include <QThreadPool>
|
||||
#include "ChunkSource.h"
|
||||
#include "ChunkLoader.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ChunkCache::ChunkCache(QObject * parent) :
|
||||
super(parent)
|
||||
{
|
||||
m_Cache.setMaxCost(1024 * 1024 * 1024); // 1 GiB of memory for the cache
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ChunkPtr ChunkCache::fetch(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
// Retrieve from the cache:
|
||||
quint32 hash = getChunkHash(a_ChunkX, a_ChunkZ);
|
||||
ChunkPtr * res;
|
||||
{
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
res = m_Cache[hash];
|
||||
// If succesful and chunk loaded, return the retrieved value:
|
||||
if ((res != nullptr) && (*res)->isValid())
|
||||
{
|
||||
return *res;
|
||||
}
|
||||
}
|
||||
|
||||
// If the chunk is in cache but not valid, it means it has been already queued for rendering, do nothing now:
|
||||
if (res != nullptr)
|
||||
{
|
||||
return ChunkPtr(nullptr);
|
||||
}
|
||||
|
||||
// There's no such item in the cache, create it now:
|
||||
res = new ChunkPtr(new Chunk);
|
||||
if (res == nullptr)
|
||||
{
|
||||
return ChunkPtr(nullptr);
|
||||
}
|
||||
{
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_Cache.insert(hash, res, sizeof(Chunk));
|
||||
}
|
||||
|
||||
// Queue the chunk for rendering:
|
||||
queueChunkRender(a_ChunkX, a_ChunkZ, *res);
|
||||
|
||||
// Return failure, the chunk is not yet rendered:
|
||||
return ChunkPtr(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ChunkCache::setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource)
|
||||
{
|
||||
// Replace the chunk source:
|
||||
m_ChunkSource = a_ChunkSource;
|
||||
|
||||
// Clear the cache:
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ChunkCache::reload()
|
||||
{
|
||||
assert(m_ChunkSource.get() != nullptr);
|
||||
|
||||
// Reload the chunk source:
|
||||
m_ChunkSource->reload();
|
||||
|
||||
// Clear the cache:
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ChunkCache::gotChunk(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
emit chunkAvailable(a_ChunkX, a_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
quint32 ChunkCache::getChunkHash(int a_ChunkX, int a_ChunkZ)
|
||||
{
|
||||
// Simply join the two coords into a single int
|
||||
// The coords will never be larger than 16-bits, so we can do this safely
|
||||
return (((static_cast<quint32>(a_ChunkX) & 0xffff) << 16) | (static_cast<quint32>(a_ChunkZ) & 0xffff));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ChunkCache::queueChunkRender(int a_ChunkX, int a_ChunkZ, ChunkPtr & a_Chunk)
|
||||
{
|
||||
// Create a new loader task:
|
||||
ChunkLoader * loader = new ChunkLoader(a_ChunkX, a_ChunkZ, a_Chunk, m_ChunkSource);
|
||||
connect(loader, SIGNAL(loaded(int, int)), this, SLOT(gotChunk(int, int)));
|
||||
|
||||
QThreadPool::globalInstance()->start(loader);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
#include "Globals.h"
|
||||
#include "ChunkLoader.h"
|
||||
#include "ChunkSource.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ChunkLoader::ChunkLoader(int a_ChunkX, int a_ChunkZ, ChunkPtr a_Chunk, ChunkSourcePtr a_ChunkSource) :
|
||||
m_ChunkX(a_ChunkX),
|
||||
m_ChunkZ(a_ChunkZ),
|
||||
m_Chunk(a_Chunk),
|
||||
m_ChunkSource(a_ChunkSource)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ChunkLoader::run()
|
||||
{
|
||||
m_ChunkSource->getChunkBiomes(m_ChunkX, m_ChunkZ, m_Chunk);
|
||||
emit loaded(m_ChunkX, m_ChunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
|
||||
// fwd:
|
||||
class Chunk;
|
||||
typedef std::shared_ptr<Chunk> ChunkPtr;
|
||||
|
||||
class ChunkSource;
|
||||
typedef std::shared_ptr<ChunkSource> ChunkSourcePtr;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ChunkLoader :
|
||||
public QObject,
|
||||
public QRunnable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ChunkLoader(int a_ChunkX, int a_ChunkZ, ChunkPtr a_Chunk, ChunkSourcePtr a_ChunkSource);
|
||||
virtual ~ChunkLoader() {}
|
||||
|
||||
signals:
|
||||
void loaded(int a_ChunkX, int a_ChunkZ);
|
||||
|
||||
protected:
|
||||
virtual void run() override;
|
||||
|
||||
private:
|
||||
int m_ChunkX, m_ChunkZ;
|
||||
ChunkPtr m_Chunk;
|
||||
ChunkSourcePtr m_ChunkSource;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -24,14 +24,14 @@ BioGenSource::BioGenSource(cIniFilePtr a_IniFile) :
|
||||
|
||||
|
||||
|
||||
void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk)
|
||||
void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk)
|
||||
{
|
||||
cChunkDef::BiomeMap biomes;
|
||||
{
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes);
|
||||
}
|
||||
a_DestChunk->setBiomes(biomes);
|
||||
int tag;
|
||||
cBiomeGenPtr biomeGen = getBiomeGen(tag);
|
||||
biomeGen->GenBiomes(a_ChunkX, a_ChunkZ, biomes);
|
||||
releaseBiomeGen(std::move(biomeGen), tag);
|
||||
a_DestChunk.setBiomes(biomes);
|
||||
}
|
||||
|
||||
|
||||
@ -40,10 +40,53 @@ void BioGenSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChu
|
||||
|
||||
void BioGenSource::reload()
|
||||
{
|
||||
int seed = m_IniFile->GetValueSetI("Seed", "Seed", 0);
|
||||
bool unused = false;
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_BiomeGen = cBiomeGen::CreateBiomeGen(*m_IniFile, seed, unused);
|
||||
m_CurrentTag += 1;
|
||||
m_BiomeGens.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cBiomeGenPtr BioGenSource::getBiomeGen(int & a_Tag)
|
||||
{
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
a_Tag = m_CurrentTag;
|
||||
if (m_BiomeGens.empty())
|
||||
{
|
||||
// Create a new biogen:
|
||||
lock.unlock();
|
||||
int seed = m_IniFile->GetValueSetI("Seed", "Seed", 0);
|
||||
bool unused;
|
||||
cBiomeGenPtr res = cBiomeGen::CreateBiomeGen(*m_IniFile, seed, unused);
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return an existing biogen:
|
||||
cBiomeGenPtr res = m_BiomeGens.back();
|
||||
m_BiomeGens.pop_back();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BioGenSource::releaseBiomeGen(cBiomeGenPtr && a_BiomeGen, int a_Tag)
|
||||
{
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
|
||||
// If the tag differs, the source has been reloaded and this biogen is old, dispose:
|
||||
if (a_Tag != m_CurrentTag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The tag is the same, put the biogen back to list:
|
||||
m_BiomeGens.push_back(std::move(a_BiomeGen));
|
||||
}
|
||||
|
||||
|
||||
@ -160,7 +203,7 @@ AnvilSource::AnvilSource(QString a_WorldRegionFolder) :
|
||||
|
||||
|
||||
|
||||
void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk)
|
||||
void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk)
|
||||
{
|
||||
// Load the compressed data:
|
||||
AString compressedChunkData = getCompressedChunkData(a_ChunkX, a_ChunkZ);
|
||||
@ -200,7 +243,7 @@ void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChun
|
||||
{
|
||||
biomeMap[i] = (EMCSBiome)GetBEInt(beBiomes + 4 * i);
|
||||
}
|
||||
a_DestChunk->setBiomes(biomeMap);
|
||||
a_DestChunk.setBiomes(biomeMap);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -216,7 +259,7 @@ void AnvilSource::getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChun
|
||||
{
|
||||
biomeMap[i] = EMCSBiome(vanillaBiomes[i]);
|
||||
}
|
||||
a_DestChunk->setBiomes(biomeMap);
|
||||
a_DestChunk.setBiomes(biomeMap);
|
||||
}
|
||||
|
||||
|
||||
@ -260,7 +303,7 @@ AnvilSource::AnvilFilePtr AnvilSource::getAnvilFile(int a_ChunkX, int a_ChunkZ)
|
||||
|
||||
// Search the cache for the file:
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
for (auto itr = m_Files.cbegin(), end = m_Files.cend(); itr != end; ++itr)
|
||||
for (auto itr = m_Files.begin(), end = m_Files.end(); itr != end; ++itr)
|
||||
{
|
||||
if (((*itr)->m_RegionX == RegionX) && ((*itr)->m_RegionZ == RegionZ))
|
||||
{
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// fwd:
|
||||
class cBiomeGen;
|
||||
typedef std::shared_ptr<cBiomeGen> cBiomeGenPtr;
|
||||
typedef SharedPtr<cBiomeGen> cBiomeGenPtr;
|
||||
class cIniFile;
|
||||
typedef std::shared_ptr<cIniFile> cIniFilePtr;
|
||||
|
||||
@ -26,7 +26,7 @@ public:
|
||||
|
||||
/** Fills the a_DestChunk with the biomes for the specified coords.
|
||||
It is expected to be thread-safe and re-entrant. Usually QThread::idealThreadCount() threads are used. */
|
||||
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) = 0;
|
||||
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) = 0;
|
||||
|
||||
/** Forces a fresh reload of the source. Useful mainly for the generator, whose underlying definition file may have been changed. */
|
||||
virtual void reload() = 0;
|
||||
@ -45,7 +45,7 @@ public:
|
||||
BioGenSource(cIniFilePtr a_IniFile);
|
||||
|
||||
// ChunkSource overrides:
|
||||
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
|
||||
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) override;
|
||||
virtual void reload(void) override;
|
||||
|
||||
protected:
|
||||
@ -53,10 +53,30 @@ protected:
|
||||
cIniFilePtr m_IniFile;
|
||||
|
||||
/** The generator used for generating biomes. */
|
||||
cBiomeGenPtr m_BiomeGen;
|
||||
std::vector<cBiomeGenPtr> m_BiomeGens;
|
||||
|
||||
/** Guards m_BiomeGen against multithreaded access. */
|
||||
/** Guards m_BiomeGens against multithreaded access. */
|
||||
QMutex m_Mtx;
|
||||
|
||||
/** Keeps track of the current settings of the biomegens.
|
||||
Incremented by one each time reload() is called. Provides the means of releasing old biomegens that were
|
||||
in use while reload() was being processed and thus couldn't be changed back then. releaseBiomeGen() does
|
||||
the job of filtering the biogens before reusing them. */
|
||||
int m_CurrentTag;
|
||||
|
||||
|
||||
/** Retrieves one cBiomeGenPtr from m_BiomeGens.
|
||||
If there's no biogen available there, creates a new one based on the ini file.
|
||||
When done with it, the caller should call releaseBiomeGen() to put the biogen back to m_BiomeGens.
|
||||
a_Tag receives the value of m_CurrentTag from when the lock was held; it should be passed to
|
||||
releaseBiomeGen() together with the biogen. */
|
||||
cBiomeGenPtr getBiomeGen(int & a_Tag);
|
||||
|
||||
/** Marks the specified biogen as available for reuse (puts it back into m_BiomeGens).
|
||||
a_Tag is the value of m_CurrentTag from the time when the biogen was retrieved; if it is different from
|
||||
current m_CurrentTagValue, the biogen will be disposed of (because reload() has been called in the
|
||||
meantime). */
|
||||
void releaseBiomeGen(cBiomeGenPtr && a_BiomeGen, int a_Tag);
|
||||
};
|
||||
|
||||
|
||||
@ -70,7 +90,7 @@ public:
|
||||
AnvilSource(QString a_WorldRegionFolder);
|
||||
|
||||
// ChunkSource overrides:
|
||||
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, ChunkPtr a_DestChunk) override;
|
||||
virtual void getChunkBiomes(int a_ChunkX, int a_ChunkZ, Chunk & a_DestChunk) override;
|
||||
virtual void reload() override;
|
||||
|
||||
protected:
|
||||
|
@ -14,6 +14,8 @@ static const QString s_GeneratorNames[] =
|
||||
QString("Checkerboard"),
|
||||
QString("Constant"),
|
||||
QString("DistortedVoronoi"),
|
||||
QString("Grown"),
|
||||
QString("GrownProt"),
|
||||
QString("MultiStepMap"),
|
||||
QString("TwoLevel"),
|
||||
QString("Voronoi"),
|
||||
|
@ -8,12 +8,13 @@
|
||||
#include <QSettings>
|
||||
#include <QDirIterator>
|
||||
#include <QStatusBar>
|
||||
#include "src/IniFile.h"
|
||||
#include "ChunkSource.h"
|
||||
#include "src/IniFile.h"
|
||||
#include "src/Generating/BioGen.h"
|
||||
#include "src/StringCompression.h"
|
||||
#include "src/WorldStorage/FastNBT.h"
|
||||
#include "GeneratorSetup.h"
|
||||
#include "RegionLoader.h"
|
||||
|
||||
|
||||
|
||||
@ -31,7 +32,8 @@ const double MainWindow::m_ViewZooms[] =
|
||||
MainWindow::MainWindow(QWidget * parent) :
|
||||
QMainWindow(parent),
|
||||
m_GeneratorSetup(nullptr),
|
||||
m_LineSeparator(nullptr)
|
||||
m_LineSeparator(nullptr),
|
||||
m_CurrentZoomLevel(2)
|
||||
{
|
||||
initMinecraftPath();
|
||||
|
||||
@ -40,6 +42,7 @@ MainWindow::MainWindow(QWidget * parent) :
|
||||
connect(m_BiomeView, SIGNAL(decreaseZoom()), this, SLOT(decreaseZoom()));
|
||||
connect(m_BiomeView, SIGNAL(wheelUp()), this, SLOT(increaseZoom()));
|
||||
connect(m_BiomeView, SIGNAL(wheelDown()), this, SLOT(decreaseZoom()));
|
||||
m_BiomeView->setZoomLevel(m_ViewZooms[m_CurrentZoomLevel]);
|
||||
|
||||
m_StatusBar = new QStatusBar();
|
||||
this->setStatusBar(m_StatusBar);
|
||||
@ -70,7 +73,7 @@ MainWindow::MainWindow(QWidget * parent) :
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
|
||||
RegionLoader::shutdown();
|
||||
}
|
||||
|
||||
|
||||
@ -172,7 +175,8 @@ void MainWindow::setViewZoom()
|
||||
{
|
||||
return;
|
||||
}
|
||||
double newZoom = m_ViewZooms[action->data().toInt()];
|
||||
m_CurrentZoomLevel = action->data().toInt();
|
||||
double newZoom = m_ViewZooms[m_CurrentZoomLevel];
|
||||
m_BiomeView->setZoomLevel(newZoom);
|
||||
action->setChecked(true);
|
||||
}
|
||||
@ -284,15 +288,11 @@ void MainWindow::createActions()
|
||||
{
|
||||
m_actViewZoom[i] = new QAction(tr("&Zoom %1%").arg(std::floor(m_ViewZooms[i] * 100)), this);
|
||||
m_actViewZoom[i]->setCheckable(true);
|
||||
if ((int)(m_ViewZooms[i] * 16) == 16)
|
||||
{
|
||||
m_actViewZoom[i]->setChecked(true);
|
||||
m_CurrentZoomLevel = i;
|
||||
}
|
||||
m_actViewZoom[i]->setData(QVariant(i));
|
||||
zoomGroup->addAction(m_actViewZoom[i]);
|
||||
connect(m_actViewZoom[i], SIGNAL(triggered()), this, SLOT(setViewZoom()));
|
||||
}
|
||||
m_actViewZoom[m_CurrentZoomLevel]->setChecked(true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,76 +12,86 @@ TARGET = QtBiomeVisualiser
|
||||
TEMPLATE = app
|
||||
|
||||
|
||||
SOURCES +=\
|
||||
MainWindow.cpp \
|
||||
BiomeView.cpp \
|
||||
../../src/Generating/BioGen.cpp \
|
||||
../../src/VoronoiMap.cpp \
|
||||
../../src/Noise.cpp \
|
||||
../../src/StringUtils.cpp \
|
||||
../../src/LoggerListeners.cpp \
|
||||
../../src/Logger.cpp \
|
||||
../../src/IniFile.cpp \
|
||||
../../src/OSSupport/File.cpp \
|
||||
../../src/OSSupport/CriticalSection.cpp \
|
||||
../../src/OSSupport/IsThread.cpp \
|
||||
../../src/BiomeDef.cpp \
|
||||
ChunkCache.cpp \
|
||||
ChunkSource.cpp \
|
||||
ChunkLoader.cpp \
|
||||
../../src/StringCompression.cpp \
|
||||
../../src/WorldStorage/FastNBT.cpp \
|
||||
../../lib/zlib/adler32.c \
|
||||
../../lib/zlib/compress.c \
|
||||
../../lib/zlib/crc32.c \
|
||||
../../lib/zlib/deflate.c \
|
||||
../../lib/zlib/gzclose.c \
|
||||
../../lib/zlib/gzlib.c \
|
||||
../../lib/zlib/gzread.c \
|
||||
../../lib/zlib/gzwrite.c \
|
||||
../../lib/zlib/infback.c \
|
||||
../../lib/zlib/inffast.c \
|
||||
../../lib/zlib/inflate.c \
|
||||
../../lib/zlib/inftrees.c \
|
||||
../../lib/zlib/trees.c \
|
||||
../../lib/zlib/uncompr.c \
|
||||
../../lib/zlib/zutil.c \
|
||||
GeneratorSetup.cpp \
|
||||
QtBiomeVisualiser.cpp \
|
||||
QtChunk.cpp
|
||||
SOURCES += \
|
||||
MainWindow.cpp \
|
||||
BiomeView.cpp \
|
||||
../../src/Generating/BioGen.cpp \
|
||||
../../src/VoronoiMap.cpp \
|
||||
../../src/Noise.cpp \
|
||||
../../src/StringUtils.cpp \
|
||||
../../src/LoggerListeners.cpp \
|
||||
../../src/Logger.cpp \
|
||||
../../src/IniFile.cpp \
|
||||
../../src/OSSupport/File.cpp \
|
||||
../../src/OSSupport/CriticalSection.cpp \
|
||||
../../src/OSSupport/IsThread.cpp \
|
||||
../../src/BiomeDef.cpp \
|
||||
../../src/StringCompression.cpp \
|
||||
../../src/WorldStorage/FastNBT.cpp \
|
||||
../../lib/zlib/adler32.c \
|
||||
../../lib/zlib/compress.c \
|
||||
../../lib/zlib/crc32.c \
|
||||
../../lib/zlib/deflate.c \
|
||||
../../lib/zlib/gzclose.c \
|
||||
../../lib/zlib/gzlib.c \
|
||||
../../lib/zlib/gzread.c \
|
||||
../../lib/zlib/gzwrite.c \
|
||||
../../lib/zlib/infback.c \
|
||||
../../lib/zlib/inffast.c \
|
||||
../../lib/zlib/inflate.c \
|
||||
../../lib/zlib/inftrees.c \
|
||||
../../lib/zlib/trees.c \
|
||||
../../lib/zlib/uncompr.c \
|
||||
../../lib/zlib/zutil.c \
|
||||
GeneratorSetup.cpp \
|
||||
QtBiomeVisualiser.cpp \
|
||||
QtChunk.cpp \
|
||||
RegionCache.cpp \
|
||||
Region.cpp \
|
||||
ChunkSource.cpp \
|
||||
RegionLoader.cpp
|
||||
|
||||
|
||||
|
||||
HEADERS += \
|
||||
MainWindow.h \
|
||||
QtChunk.h \
|
||||
Globals.h \
|
||||
BiomeView.h \
|
||||
../../src/Generating/BioGen.h \
|
||||
../../src/Generating/IntGen.h \
|
||||
../../src/Generating/ProtIntGen.h \
|
||||
../../src/VoronoiMap.h \
|
||||
../../src/Noise.h \
|
||||
../../src/StringUtils.h \
|
||||
../../src/LoggerListeners.h \
|
||||
../../src/Logger.h \
|
||||
../../src/IniFile.h \
|
||||
../../src/OSSupport/File.h \
|
||||
../../src/OSSupport/CriticalSection.h \
|
||||
../../src/OSSupport/IsThread.h \
|
||||
../../src/BiomeDef.h \
|
||||
../../src/StringCompression.h \
|
||||
../../src/WorldStorage/FastNBT.h \
|
||||
../../lib/zlib/crc32.h \
|
||||
../../lib/zlib/deflate.h \
|
||||
../../lib/zlib/gzguts.h \
|
||||
../../lib/zlib/inffast.h \
|
||||
../../lib/zlib/inffixed.h \
|
||||
../../lib/zlib/inflate.h \
|
||||
../../lib/zlib/inftrees.h \
|
||||
../../lib/zlib/trees.h \
|
||||
../../lib/zlib/zconf.h \
|
||||
../../lib/zlib/zlib.h \
|
||||
../../lib/zlib/zutil.h \
|
||||
GeneratorSetup.h \
|
||||
QtChunk.h \
|
||||
RegionCache.h \
|
||||
Region.h \
|
||||
ChunkSource.h \
|
||||
RegionLoader.h
|
||||
|
||||
|
||||
HEADERS += MainWindow.h \
|
||||
Globals.h \
|
||||
BiomeView.h \
|
||||
../../src/Generating/BioGen.h \
|
||||
../../src/VoronoiMap.h \
|
||||
../../src/Noise.h \
|
||||
../../src/StringUtils.h \
|
||||
../../src/LoggerListeners.h \
|
||||
../../src/Logger.h \
|
||||
../../src/IniFile.h \
|
||||
../../src/OSSupport/File.h \
|
||||
../../src/OSSupport/CriticalSection.h \
|
||||
../../src/OSSupport/IsThread.h \
|
||||
../../src/BiomeDef.h \
|
||||
ChunkCache.h \
|
||||
ChunkSource.h \
|
||||
ChunkLoader.h \
|
||||
../../src/StringCompression.h \
|
||||
../../src/WorldStorage/FastNBT.h \
|
||||
../../lib/zlib/crc32.h \
|
||||
../../lib/zlib/deflate.h \
|
||||
../../lib/zlib/gzguts.h \
|
||||
../../lib/zlib/inffast.h \
|
||||
../../lib/zlib/inffixed.h \
|
||||
../../lib/zlib/inflate.h \
|
||||
../../lib/zlib/inftrees.h \
|
||||
../../lib/zlib/trees.h \
|
||||
../../lib/zlib/zconf.h \
|
||||
../../lib/zlib/zlib.h \
|
||||
../../lib/zlib/zutil.h \
|
||||
GeneratorSetup.h \
|
||||
QtChunk.h
|
||||
|
||||
INCLUDEPATH += $$_PRO_FILE_PWD_ \
|
||||
$$_PRO_FILE_PWD_/../../lib \
|
||||
|
@ -5,138 +5,6 @@
|
||||
|
||||
|
||||
|
||||
/** Map for converting biome values to colors. Initialized from biomeColors[]. */
|
||||
static uchar biomeToColor[256 * 4];
|
||||
|
||||
/** Map for converting biome values to colors. Used to initialize biomeToColor[].*/
|
||||
static struct
|
||||
{
|
||||
EMCSBiome m_Biome;
|
||||
uchar m_Color[3];
|
||||
} biomeColors[] =
|
||||
{
|
||||
{ biOcean, { 0x00, 0x00, 0x70 }, },
|
||||
{ biPlains, { 0x8d, 0xb3, 0x60 }, },
|
||||
{ biDesert, { 0xfa, 0x94, 0x18 }, },
|
||||
{ biExtremeHills, { 0x60, 0x60, 0x60 }, },
|
||||
{ biForest, { 0x05, 0x66, 0x21 }, },
|
||||
{ biTaiga, { 0x0b, 0x66, 0x59 }, },
|
||||
{ biSwampland, { 0x2f, 0xff, 0xda }, },
|
||||
{ biRiver, { 0x30, 0x30, 0xaf }, },
|
||||
{ biHell, { 0x7f, 0x00, 0x00 }, },
|
||||
{ biSky, { 0x00, 0x7f, 0xff }, },
|
||||
{ biFrozenOcean, { 0xa0, 0xa0, 0xdf }, },
|
||||
{ biFrozenRiver, { 0xa0, 0xa0, 0xff }, },
|
||||
{ biIcePlains, { 0xff, 0xff, 0xff }, },
|
||||
{ biIceMountains, { 0xa0, 0xa0, 0xa0 }, },
|
||||
{ biMushroomIsland, { 0xff, 0x00, 0xff }, },
|
||||
{ biMushroomShore, { 0xa0, 0x00, 0xff }, },
|
||||
{ biBeach, { 0xfa, 0xde, 0x55 }, },
|
||||
{ biDesertHills, { 0xd2, 0x5f, 0x12 }, },
|
||||
{ biForestHills, { 0x22, 0x55, 0x1c }, },
|
||||
{ biTaigaHills, { 0x16, 0x39, 0x33 }, },
|
||||
{ biExtremeHillsEdge, { 0x7f, 0x8f, 0x7f }, },
|
||||
{ biJungle, { 0x53, 0x7b, 0x09 }, },
|
||||
{ biJungleHills, { 0x2c, 0x42, 0x05 }, },
|
||||
|
||||
{ biJungleEdge, { 0x62, 0x8b, 0x17 }, },
|
||||
{ biDeepOcean, { 0x00, 0x00, 0x30 }, },
|
||||
{ biStoneBeach, { 0xa2, 0xa2, 0x84 }, },
|
||||
{ biColdBeach, { 0xfa, 0xf0, 0xc0 }, },
|
||||
{ biBirchForest, { 0x30, 0x74, 0x44 }, },
|
||||
{ biBirchForestHills, { 0x1f, 0x5f, 0x32 }, },
|
||||
{ biRoofedForest, { 0x40, 0x51, 0x1a }, },
|
||||
{ biColdTaiga, { 0x31, 0x55, 0x4a }, },
|
||||
{ biColdTaigaHills, { 0x59, 0x7d, 0x72 }, },
|
||||
{ biMegaTaiga, { 0x59, 0x66, 0x51 }, },
|
||||
{ biMegaTaigaHills, { 0x59, 0x66, 0x59 }, },
|
||||
{ biExtremeHillsPlus, { 0x50, 0x70, 0x50 }, },
|
||||
{ biSavanna, { 0xbd, 0xb2, 0x5f }, },
|
||||
{ biSavannaPlateau, { 0xa7, 0x9d, 0x64 }, },
|
||||
{ biMesa, { 0xd9, 0x45, 0x15 }, },
|
||||
{ biMesaPlateauF, { 0xb0, 0x97, 0x65 }, },
|
||||
{ biMesaPlateau, { 0xca, 0x8c, 0x65 }, },
|
||||
|
||||
// M variants:
|
||||
{ biSunflowerPlains, { 0xb5, 0xdb, 0x88 }, },
|
||||
{ biDesertM, { 0xff, 0xbc, 0x40 }, },
|
||||
{ biExtremeHillsM, { 0x88, 0x88, 0x88 }, },
|
||||
{ biFlowerForest, { 0x2d, 0x8e, 0x49 }, },
|
||||
{ biTaigaM, { 0x33, 0x8e, 0x81 }, },
|
||||
{ biSwamplandM, { 0x07, 0xf9, 0xb2 }, },
|
||||
{ biIcePlainsSpikes, { 0xb4, 0xdc, 0xdc }, },
|
||||
{ biJungleM, { 0x7b, 0xa3, 0x31 }, },
|
||||
{ biJungleEdgeM, { 0x62, 0x8b, 0x17 }, },
|
||||
{ biBirchForestM, { 0x58, 0x9c, 0x6c }, },
|
||||
{ biBirchForestHillsM, { 0x47, 0x87, 0x5a }, },
|
||||
{ biRoofedForestM, { 0x68, 0x79, 0x42 }, },
|
||||
{ biColdTaigaM, { 0x24, 0x3f, 0x36 }, },
|
||||
{ biMegaSpruceTaiga, { 0x45, 0x4f, 0x3e }, },
|
||||
{ biMegaSpruceTaigaHills, { 0x45, 0x4f, 0x4e }, },
|
||||
{ biExtremeHillsPlusM, { 0x78, 0x98, 0x78 }, },
|
||||
{ biSavannaM, { 0xe5, 0xda, 0x87 }, },
|
||||
{ biSavannaPlateauM, { 0xa7, 0x9d, 0x74 }, },
|
||||
{ biMesaBryce, { 0xff, 0x6d, 0x3d }, },
|
||||
{ biMesaPlateauFM, { 0xd8, 0xbf, 0x8d }, },
|
||||
{ biMesaPlateauM, { 0xf2, 0xb4, 0x8d }, },
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static class BiomeColorsInitializer
|
||||
{
|
||||
public:
|
||||
BiomeColorsInitializer(void)
|
||||
{
|
||||
// Reset all colors to gray:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(biomeToColor); i++)
|
||||
{
|
||||
biomeToColor[i] = 0x7f;
|
||||
}
|
||||
|
||||
// Set known biomes to their colors:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(biomeColors); i++)
|
||||
{
|
||||
uchar * color = &biomeToColor[4 * biomeColors[i].m_Biome];
|
||||
color[0] = biomeColors[i].m_Color[2];
|
||||
color[1] = biomeColors[i].m_Color[1];
|
||||
color[2] = biomeColors[i].m_Color[0];
|
||||
color[3] = 0xff;
|
||||
}
|
||||
}
|
||||
} biomeColorInitializer;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Converts biomes in an array into the chunk image data. */
|
||||
static void biomesToImage(const cChunkDef::BiomeMap & a_Biomes, Chunk::Image & a_Image)
|
||||
{
|
||||
// Make sure the two arrays are of the same size, compile-time.
|
||||
// Note that a_Image is actually 4 items per pixel, so the array is 4 times bigger:
|
||||
static const char Check1[4 * ARRAYCOUNT(a_Biomes) - ARRAYCOUNT(a_Image) + 1] = {};
|
||||
static const char Check2[ARRAYCOUNT(a_Image) - 4 * ARRAYCOUNT(a_Biomes) + 1] = {};
|
||||
|
||||
// Convert the biomes into color:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(a_Biomes); i++)
|
||||
{
|
||||
a_Image[4 * i + 0] = biomeToColor[4 * a_Biomes[i] + 0];
|
||||
a_Image[4 * i + 1] = biomeToColor[4 * a_Biomes[i] + 1];
|
||||
a_Image[4 * i + 2] = biomeToColor[4 * a_Biomes[i] + 2];
|
||||
a_Image[4 * i + 3] = biomeToColor[4 * a_Biomes[i] + 3];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Chunk:
|
||||
|
||||
Chunk::Chunk() :
|
||||
m_IsValid(false)
|
||||
{
|
||||
@ -146,20 +14,12 @@ Chunk::Chunk() :
|
||||
|
||||
|
||||
|
||||
const uchar * Chunk::getImage(void) const
|
||||
{
|
||||
ASSERT(m_IsValid);
|
||||
return m_Image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Chunk::setBiomes(const cChunkDef::BiomeMap & a_Biomes)
|
||||
{
|
||||
memcpy(m_Biomes, a_Biomes, sizeof(m_Biomes));
|
||||
renderBiomes();
|
||||
for (size_t idx = 0; idx < ARRAYCOUNT(a_Biomes); ++idx)
|
||||
{
|
||||
m_Biomes[idx] = static_cast<short>(a_Biomes[idx]);
|
||||
}
|
||||
m_IsValid = true;
|
||||
}
|
||||
|
||||
@ -173,16 +33,7 @@ EMCSBiome Chunk::getBiome(int a_RelX, int a_RelZ)
|
||||
{
|
||||
return biInvalidBiome;
|
||||
}
|
||||
return cChunkDef::GetBiome(m_Biomes, a_RelX, a_RelZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Chunk::renderBiomes()
|
||||
{
|
||||
biomesToImage(m_Biomes, m_Image);
|
||||
return static_cast<EMCSBiome>(m_Biomes[a_RelX + 16 * a_RelZ]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,9 +18,6 @@ public:
|
||||
/** Returns true iff the chunk data is valid - loaded or generated. */
|
||||
bool isValid(void) const { return m_IsValid; }
|
||||
|
||||
/** Returns the image of the chunk's biomes. Assumes that the chunk is valid. */
|
||||
const uchar * getImage(void) const;
|
||||
|
||||
/** Sets the biomes to m_Biomes and renders them into m_Image. */
|
||||
void setBiomes(const cChunkDef::BiomeMap & a_Biomes);
|
||||
|
||||
@ -28,19 +25,16 @@ public:
|
||||
Coords must be valid inside this chunk. */
|
||||
EMCSBiome getBiome(int a_RelX, int a_RelZ);
|
||||
|
||||
/** Returns the raw biome data for this chunk. */
|
||||
const short * getBiomes(void) const { return m_Biomes; }
|
||||
|
||||
protected:
|
||||
/** Flag that specifies if the chunk data is valid - loaded or generated. */
|
||||
bool m_IsValid;
|
||||
|
||||
/** Cached rendered image of this chunk's biomes. Updated in render(). */
|
||||
Image m_Image;
|
||||
|
||||
/** Biomes comprising the chunk, in the X + 16 * Z ordering. */
|
||||
cChunkDef::BiomeMap m_Biomes;
|
||||
|
||||
|
||||
/** Renders biomes from m_Biomes into m_Image. */
|
||||
void renderBiomes();
|
||||
/** Biomes comprising the chunk, in the X + 16 * Z ordering.
|
||||
Typed as short to save on memory, converted automatically when needed. */
|
||||
short m_Biomes[16 * 16];
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<Chunk> ChunkPtr;
|
||||
|
72
Tools/QtBiomeVisualiser/Region.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Region.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Region::Region()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Chunk & Region::getRelChunk(int a_RelChunkX, int a_RelChunkZ)
|
||||
{
|
||||
ASSERT(a_RelChunkX >= 0);
|
||||
ASSERT(a_RelChunkZ >= 0);
|
||||
ASSERT(a_RelChunkX < 32);
|
||||
ASSERT(a_RelChunkZ < 32);
|
||||
|
||||
return m_Chunks[a_RelChunkX + a_RelChunkZ * 32];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int Region::getRelBiome(int a_RelBlockX, int a_RelBlockZ)
|
||||
{
|
||||
ASSERT(a_RelBlockX >= 0);
|
||||
ASSERT(a_RelBlockZ >= 0);
|
||||
ASSERT(a_RelBlockX < 512);
|
||||
ASSERT(a_RelBlockZ < 512);
|
||||
|
||||
int chunkX = a_RelBlockX / 16;
|
||||
int chunkZ = a_RelBlockZ / 16;
|
||||
Chunk & chunk = m_Chunks[chunkX + 32 * chunkZ];
|
||||
if (chunk.isValid())
|
||||
{
|
||||
return chunk.getBiome(a_RelBlockX - 16 * chunkX, a_RelBlockZ - 16 * chunkZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
return biInvalidBiome;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void Region::blockToRegion(int a_BlockX, int a_BlockZ, int & a_RegionX, int & a_RegionZ)
|
||||
{
|
||||
a_RegionX = static_cast<int>(std::floor(static_cast<float>(a_BlockX) / 512));
|
||||
a_RegionZ = static_cast<int>(std::floor(static_cast<float>(a_BlockZ) / 512));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Region::chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ)
|
||||
{
|
||||
a_RegionX = static_cast<int>(std::floor(static_cast<float>(a_ChunkX) / 32));
|
||||
a_RegionZ = static_cast<int>(std::floor(static_cast<float>(a_ChunkZ) / 32));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
46
Tools/QtBiomeVisualiser/Region.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "QtChunk.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Region
|
||||
{
|
||||
public:
|
||||
Region();
|
||||
|
||||
/** Retrieves the chunk with the specified relative coords. */
|
||||
Chunk & getRelChunk(int a_RelChunkX, int a_RelChunkZ);
|
||||
|
||||
/** Returns true iff the chunk data for all chunks has been loaded.
|
||||
This doesn't mean that all the chunks are valid, only that the entire region has been processed and should
|
||||
be displayed. */
|
||||
bool isValid(void) const { return m_IsValid; }
|
||||
|
||||
/** Returns the biome in the block coords relative to this region.
|
||||
Returns biInvalidBiome if the underlying chunk is not valid. */
|
||||
int getRelBiome(int a_RelBlockX, int a_RelBlockZ);
|
||||
|
||||
/** Converts block coordinates into region coordinates. */
|
||||
static void blockToRegion(int a_BlockX, int a_BlockZ, int & a_RegionX, int & a_RegionZ);
|
||||
|
||||
/** Converts chunk coordinates into region coordinates. */
|
||||
static void chunkToRegion(int a_ChunkX, int a_ChunkZ, int & a_RegionX, int & a_RegionZ);
|
||||
|
||||
protected:
|
||||
friend class RegionLoader;
|
||||
|
||||
|
||||
Chunk m_Chunks[32 * 32];
|
||||
|
||||
/** True iff the data for all the chunks has been loaded.
|
||||
This doesn't mean that all the chunks are valid, only that the entire region has been processed and should
|
||||
be displayed. */
|
||||
bool m_IsValid;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
138
Tools/QtBiomeVisualiser/RegionCache.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
#include "Globals.h"
|
||||
#include "RegionCache.h"
|
||||
#include <QMutexLocker>
|
||||
#include <QThreadPool>
|
||||
#include "ChunkSource.h"
|
||||
#include "RegionLoader.h"
|
||||
#include "Region.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RegionCache::RegionCache(QObject * parent) :
|
||||
super(parent)
|
||||
{
|
||||
m_Cache.setMaxCost(1024 * 1024 * 1024); // 1 GiB of memory for the cache
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RegionPtr RegionCache::fetch(int a_RegionX, int a_RegionZ)
|
||||
{
|
||||
// Retrieve from the cache:
|
||||
quint32 hash = getRegionHash(a_RegionX, a_RegionZ);
|
||||
RegionPtr * res;
|
||||
{
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
res = m_Cache[hash];
|
||||
// If succesful and region loaded, return the retrieved value:
|
||||
if ((res != nullptr) && (*res)->isValid())
|
||||
{
|
||||
return *res;
|
||||
}
|
||||
}
|
||||
|
||||
// If the region is in cache but not valid, it means it has been already queued for rendering, do nothing now:
|
||||
if (res != nullptr)
|
||||
{
|
||||
return RegionPtr(nullptr);
|
||||
}
|
||||
|
||||
// There's no such item in the cache, create it now:
|
||||
try
|
||||
{
|
||||
res = new RegionPtr(new Region);
|
||||
}
|
||||
catch (const std::bad_alloc &)
|
||||
{
|
||||
/* Allocation failed (32-bit process hit the 2 GiB barrier?)
|
||||
This may happen even with the cache set to 1 GiB, because it contains shared ptrs and so they may be
|
||||
held by another place in the code even when they are removed from cache.
|
||||
*/
|
||||
return RegionPtr(nullptr);
|
||||
}
|
||||
if (res == nullptr)
|
||||
{
|
||||
return RegionPtr(nullptr);
|
||||
}
|
||||
{
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_Cache.insert(hash, res, sizeof(Region));
|
||||
}
|
||||
|
||||
// Queue the region for rendering:
|
||||
queueRegionRender(a_RegionX, a_RegionZ, *res);
|
||||
|
||||
// Return failure, the region is not yet rendered:
|
||||
return RegionPtr(nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RegionCache::setChunkSource(std::shared_ptr<ChunkSource> a_ChunkSource)
|
||||
{
|
||||
// Replace the chunk source:
|
||||
m_ChunkSource = a_ChunkSource;
|
||||
|
||||
// Clear the cache:
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RegionCache::reload()
|
||||
{
|
||||
assert(m_ChunkSource.get() != nullptr);
|
||||
|
||||
// Reload the chunk source:
|
||||
m_ChunkSource->reload();
|
||||
|
||||
// Clear the cache:
|
||||
QMutexLocker lock(&m_Mtx);
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RegionCache::gotRegion(int a_RegionX, int a_RegionZ)
|
||||
{
|
||||
emit regionAvailable(a_RegionX, a_RegionZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
quint32 RegionCache::getRegionHash(int a_RegionX, int a_RegionZ)
|
||||
{
|
||||
// Simply join the two coords into a single int
|
||||
// The coords will never be larger than 16-bits, so we can do this safely
|
||||
return (((static_cast<quint32>(a_RegionX) & 0xffff) << 16) | (static_cast<quint32>(a_RegionZ) & 0xffff));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RegionCache::queueRegionRender(int a_RegionX, int a_RegionZ, RegionPtr & a_Region)
|
||||
{
|
||||
// Create a new loader task:
|
||||
RegionLoader * loader = new RegionLoader(a_RegionX, a_RegionZ, a_Region, m_ChunkSource);
|
||||
connect(loader, SIGNAL(loaded(int, int)), this, SLOT(gotRegion(int, int)));
|
||||
|
||||
QThreadPool::globalInstance()->start(loader);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -9,8 +9,9 @@
|
||||
|
||||
|
||||
|
||||
class Chunk;
|
||||
typedef std::shared_ptr<Chunk> ChunkPtr;
|
||||
// fwd:
|
||||
class Region;
|
||||
typedef std::shared_ptr<Region> RegionPtr;
|
||||
|
||||
class ChunkSource;
|
||||
|
||||
@ -18,19 +19,19 @@ class ChunkSource;
|
||||
|
||||
|
||||
|
||||
/** Caches chunk data for reuse */
|
||||
class ChunkCache :
|
||||
/** Caches regions' chunk data for reuse */
|
||||
class RegionCache :
|
||||
public QObject
|
||||
{
|
||||
typedef QObject super;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ChunkCache(QObject * parent = NULL);
|
||||
explicit RegionCache(QObject * parent = NULL);
|
||||
|
||||
/** Retrieves the specified chunk from the cache.
|
||||
Only returns valid chunks; if the chunk is invalid, queues it for rendering and returns an empty ptr. */
|
||||
ChunkPtr fetch(int a_ChunkX, int a_ChunkZ);
|
||||
/** Retrieves the specified region from the cache.
|
||||
Only returns valid regions; if the region is invalid, queues it for rendering and returns an empty ptr. */
|
||||
RegionPtr fetch(int a_RegionX, int a_RegionZ);
|
||||
|
||||
/** Replaces the chunk source used by the biome view to get the chunk biome data.
|
||||
The cache is then invalidated. */
|
||||
@ -43,16 +44,16 @@ public:
|
||||
void reload();
|
||||
|
||||
signals:
|
||||
void chunkAvailable(int a_ChunkX, int a_ChunkZ);
|
||||
void regionAvailable(int a_RegionX, int a_RegionZ);
|
||||
|
||||
protected slots:
|
||||
void gotChunk(int a_ChunkX, int a_ChunkZ);
|
||||
void gotRegion(int a_RegionX, int a_RegionZ);
|
||||
|
||||
protected:
|
||||
/** The cache of the chunks */
|
||||
QCache<quint32, ChunkPtr> m_Cache;
|
||||
QCache<quint32, RegionPtr> m_Cache;
|
||||
|
||||
/** Locks te cache against multithreaded access */
|
||||
/** Locks the cache against multithreaded access */
|
||||
QMutex m_Mtx;
|
||||
|
||||
/** The source used to get the biome data. */
|
||||
@ -60,10 +61,10 @@ protected:
|
||||
|
||||
|
||||
/** Returns the hash used by the chunk in the cache */
|
||||
quint32 getChunkHash(int a_ChunkX, int a_ChunkZ);
|
||||
quint32 getRegionHash(int a_RegionX, int a_RegionZ);
|
||||
|
||||
/** Queues the specified chunk for rendering by m_ChunkSource. */
|
||||
void queueChunkRender(int a_ChunkX, int a_ChunkZ, ChunkPtr & a_Chunk);
|
||||
/** Queues the specified region for rendering by m_RegionSource. */
|
||||
void queueRegionRender(int a_RegionX, int a_RegionZ, RegionPtr & a_Region);
|
||||
};
|
||||
|
||||
|
49
Tools/QtBiomeVisualiser/RegionLoader.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "Globals.h"
|
||||
#include "RegionLoader.h"
|
||||
#include "ChunkSource.h"
|
||||
#include "Region.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
volatile bool RegionLoader::m_IsShuttingDown = false;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
RegionLoader::RegionLoader(int a_RegionX, int a_RegionZ, RegionPtr a_Region, ChunkSourcePtr a_ChunkSource) :
|
||||
m_RegionX(a_RegionX),
|
||||
m_RegionZ(a_RegionZ),
|
||||
m_Region(a_Region),
|
||||
m_ChunkSource(a_ChunkSource)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void RegionLoader::run()
|
||||
{
|
||||
// Load all the chunks in this region:
|
||||
for (int z = 0; z < 32; z++)
|
||||
{
|
||||
for (int x = 0; x < 32; x++)
|
||||
{
|
||||
m_ChunkSource->getChunkBiomes(m_RegionX * 32 + x, m_RegionZ * 32 + z, m_Region->getRelChunk(x, z));
|
||||
if (m_IsShuttingDown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_Region->m_IsValid = true;
|
||||
|
||||
emit loaded(m_RegionX, m_RegionZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
56
Tools/QtBiomeVisualiser/RegionLoader.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
|
||||
// fwd:
|
||||
class Region;
|
||||
typedef std::shared_ptr<Region> RegionPtr;
|
||||
|
||||
class ChunkSource;
|
||||
typedef std::shared_ptr<ChunkSource> ChunkSourcePtr;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class RegionLoader :
|
||||
public QObject,
|
||||
public QRunnable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RegionLoader(int a_RegionX, int a_RegionZ, RegionPtr a_Region, ChunkSourcePtr a_ChunkSource);
|
||||
virtual ~RegionLoader() {}
|
||||
|
||||
/** Signals to all loaders that the app is shutting down and the loading should be aborted. */
|
||||
static void shutdown() { m_IsShuttingDown = true; }
|
||||
|
||||
signals:
|
||||
void loaded(int a_RegionX, int a_RegionZ);
|
||||
|
||||
protected:
|
||||
virtual void run() override;
|
||||
|
||||
private:
|
||||
/** Coords of the region to be loaded. */
|
||||
int m_RegionX, m_RegionZ;
|
||||
|
||||
/** The region to be loaded. */
|
||||
RegionPtr m_Region;
|
||||
|
||||
/** The chunk source to be used for individual chunks within the region. */
|
||||
ChunkSourcePtr m_ChunkSource;
|
||||
|
||||
/** Flag that is set upon app exit to terminate the queued loaders faster. */
|
||||
static volatile bool m_IsShuttingDown;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
11
app.yml
Normal file
@ -0,0 +1,11 @@
|
||||
name: MCServer
|
||||
image: ubuntu-14-04-x64
|
||||
config:
|
||||
#cloud-config
|
||||
packages:
|
||||
- curl
|
||||
- screen
|
||||
runcmd:
|
||||
- mkdir /minecraft
|
||||
- cd /minecraft && curl -s https://raw.githubusercontent.com/mc-server/MCServer/master/easyinstall.sh | sh
|
||||
- cd /minecraft/MCServer && screen -S mcserver -d -m ./MCServer
|
@ -247,7 +247,11 @@ public:
|
||||
template <typename FnT, typename... Args>
|
||||
bool Call(const FnT & a_Function, Args &&... args)
|
||||
{
|
||||
PushFunction(a_Function);
|
||||
if (!PushFunction(a_Function))
|
||||
{
|
||||
// Pushing the function failed
|
||||
return false;
|
||||
}
|
||||
return PushCallPop(args...);
|
||||
}
|
||||
|
||||
|
@ -160,3 +160,65 @@ bool IsBiomeNoDownfall(EMCSBiome a_Biome)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool IsBiomeVeryCold(EMCSBiome a_Biome)
|
||||
{
|
||||
switch (a_Biome)
|
||||
{
|
||||
case biFrozenOcean:
|
||||
case biFrozenRiver:
|
||||
case biIcePlains:
|
||||
case biIceMountains:
|
||||
case biColdBeach:
|
||||
case biColdTaiga:
|
||||
case biColdTaigaHills:
|
||||
case biIcePlainsSpikes:
|
||||
case biColdTaigaM:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool IsBiomeCold(EMCSBiome a_Biome)
|
||||
{
|
||||
switch (a_Biome)
|
||||
{
|
||||
case biExtremeHills:
|
||||
case biTaiga:
|
||||
case biTaigaHills:
|
||||
case biExtremeHillsEdge:
|
||||
case biStoneBeach:
|
||||
case biMegaTaiga:
|
||||
case biMegaTaigaHills:
|
||||
case biExtremeHillsPlus:
|
||||
case biExtremeHillsM:
|
||||
case biTaigaM:
|
||||
case biColdTaigaM:
|
||||
case biMegaSpruceTaiga:
|
||||
case biMegaSpruceTaigaHills:
|
||||
case biExtremeHillsPlusM:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -113,5 +113,20 @@ extern AString BiomeToString(int a_Biome);
|
||||
/** Returns true if the biome has no downfall - deserts and savannas */
|
||||
extern bool IsBiomeNoDownfall(EMCSBiome a_Biome);
|
||||
|
||||
/** Returns true if the biome is an ocean biome. */
|
||||
inline bool IsBiomeOcean(int a_Biome)
|
||||
{
|
||||
return ((a_Biome == biOcean) || (a_Biome == biDeepOcean));
|
||||
}
|
||||
|
||||
/** Returns true if the biome is very cold
|
||||
(has snow on ground everywhere, turns top water to ice, has snowfall instead of rain everywhere).
|
||||
Doesn't report mildly cold biomes (where it snows above certain elevation), use IsBiomeCold() for those. */
|
||||
extern bool IsBiomeVeryCold(EMCSBiome a_Biome);
|
||||
|
||||
/** Returns true if the biome is cold
|
||||
(has snow and snowfall at higher elevations but not at regular heights).
|
||||
Doesn't report Very Cold biomes, use IsBiomeVeryCold() for those. */
|
||||
extern bool IsBiomeCold(EMCSBiome a_Biome);
|
||||
|
||||
// tolua_end
|
||||
|
@ -217,7 +217,12 @@ BLOCKTYPE BlockStringToType(const AString & a_BlockTypeString)
|
||||
|
||||
bool StringToItem(const AString & a_ItemTypeString, cItem & a_Item)
|
||||
{
|
||||
return gsBlockIDMap.ResolveItem(TrimString(a_ItemTypeString), a_Item);
|
||||
AString ItemName = TrimString(a_ItemTypeString);
|
||||
if (ItemName.substr(0, 10) == "minecraft:")
|
||||
{
|
||||
ItemName = ItemName.substr(10);
|
||||
}
|
||||
return gsBlockIDMap.ResolveItem(ItemName, a_Item);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
// The following hackery is to allow typed C++ enum for C++ code, yet have ToLua process the values.
|
||||
// ToLua doesn't understand typed enums, so we use preprocessor to hide it from ToLua.
|
||||
|
||||
enum ENUM_BLOCK_ID : BLOCKTYPE
|
||||
#if 0
|
||||
enum ENUM_BLOCK_ID // tolua_export
|
||||
#endif
|
||||
// tolua_begin
|
||||
enum ENUM_BLOCK_ID
|
||||
{
|
||||
E_BLOCK_AIR = 0,
|
||||
E_BLOCK_STONE = 1,
|
||||
@ -221,6 +227,10 @@ enum ENUM_BLOCK_ID
|
||||
};
|
||||
// tolua_end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
enum ENUM_ITEM_ID
|
||||
{
|
||||
|
@ -822,6 +822,7 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
|
||||
int MinChunkX, MinChunkZ, MaxChunkX, MaxChunkZ;
|
||||
cChunkDef::BlockToChunk(a_MinBlockX, a_MinBlockZ, MinChunkX, MinChunkZ);
|
||||
cChunkDef::BlockToChunk(a_MaxBlockX, a_MaxBlockZ, MaxChunkX, MaxChunkZ);
|
||||
cCSLock Lock(m_CSLayers);
|
||||
for (int z = MinChunkZ; z <= MaxChunkZ; z++)
|
||||
{
|
||||
int MinZ = std::max(a_MinBlockZ, z * cChunkDef::Width);
|
||||
|
@ -184,7 +184,7 @@ void cChunkSender::Execute(void)
|
||||
while (!m_ShouldTerminate)
|
||||
{
|
||||
cCSLock Lock(m_CS);
|
||||
while (m_ChunksReady.empty() && m_SendChunksLowPriority.empty() && m_SendChunksHighPriority.empty())
|
||||
while (m_ChunksReady.empty() && m_SendChunksLowPriority.empty() && m_SendChunksMediumPriority.empty() && m_SendChunksHighPriority.empty())
|
||||
{
|
||||
int RemoveCount = m_RemoveCount;
|
||||
m_RemoveCount = 0;
|
||||
|
@ -557,7 +557,7 @@ void cClientHandle::UnloadOutOfRangeChunks(void)
|
||||
for (cChunkCoordsList::iterator itr = ChunksToRemove.begin(); itr != ChunksToRemove.end(); ++itr)
|
||||
{
|
||||
m_Player->GetWorld()->RemoveChunkClient(itr->m_ChunkX, itr->m_ChunkZ, this);
|
||||
m_Protocol->SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||
SendUnloadChunk(itr->m_ChunkX, itr->m_ChunkZ);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,10 @@
|
||||
|
||||
#include "Globals.h"
|
||||
#include "BioGen.h"
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include "IntGen.h"
|
||||
#include "ProtIntGen.h"
|
||||
#include "../IniFile.h"
|
||||
#include "../LinearUpscale.h"
|
||||
|
||||
@ -916,6 +920,214 @@ void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile)
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cBioGenGrown:
|
||||
|
||||
class cBioGenGrown:
|
||||
public cBiomeGen
|
||||
{
|
||||
public:
|
||||
cBioGenGrown(int a_Seed)
|
||||
{
|
||||
auto FinalRivers =
|
||||
std::make_shared<cIntGenSmooth<8>> (a_Seed + 1,
|
||||
std::make_shared<cIntGenZoom <10>> (a_Seed + 2,
|
||||
std::make_shared<cIntGenRiver <7>> (a_Seed + 3,
|
||||
std::make_shared<cIntGenZoom <9>> (a_Seed + 4,
|
||||
std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
|
||||
std::make_shared<cIntGenZoom <8>> (a_Seed + 8,
|
||||
std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
|
||||
std::make_shared<cIntGenZoom <8>> (a_Seed + 9,
|
||||
std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
|
||||
std::make_shared<cIntGenZoom <8>> (a_Seed + 10,
|
||||
std::make_shared<cIntGenSmooth<6>> (a_Seed + 5,
|
||||
std::make_shared<cIntGenSmooth<8>> (a_Seed + 6,
|
||||
std::make_shared<cIntGenZoom <10>> (a_Seed + 11,
|
||||
std::make_shared<cIntGenChoice<2, 7>>(a_Seed + 12
|
||||
))))))))))))));
|
||||
|
||||
auto alteration =
|
||||
std::make_shared<cIntGenZoom <8>>(a_Seed,
|
||||
std::make_shared<cIntGenLandOcean<6>>(a_Seed, 20
|
||||
));
|
||||
|
||||
auto alteration2 =
|
||||
std::make_shared<cIntGenZoom <8>>(a_Seed + 1,
|
||||
std::make_shared<cIntGenZoom <6>>(a_Seed + 2,
|
||||
std::make_shared<cIntGenZoom <5>>(a_Seed + 1,
|
||||
std::make_shared<cIntGenZoom <4>>(a_Seed + 2,
|
||||
std::make_shared<cIntGenLandOcean<4>>(a_Seed + 1, 10
|
||||
)))));
|
||||
|
||||
auto FinalBiomes =
|
||||
std::make_shared<cIntGenSmooth <8>> (a_Seed + 1,
|
||||
std::make_shared<cIntGenZoom <10>>(a_Seed + 15,
|
||||
std::make_shared<cIntGenSmooth <7>> (a_Seed + 1,
|
||||
std::make_shared<cIntGenZoom <9>> (a_Seed + 16,
|
||||
std::make_shared<cIntGenBeaches <6>> (
|
||||
std::make_shared<cIntGenZoom <8>> (a_Seed + 1,
|
||||
std::make_shared<cIntGenAddIslands <6>> (a_Seed + 2004, 10,
|
||||
std::make_shared<cIntGenAddToOcean <6>> (a_Seed + 10, 500, biDeepOcean,
|
||||
std::make_shared<cIntGenReplaceRandomly<8>> (a_Seed + 1, biPlains, biSunflowerPlains, 20,
|
||||
std::make_shared<cIntGenMBiomes <8>> (a_Seed + 5, alteration2,
|
||||
std::make_shared<cIntGenAlternateBiomes<8>> (a_Seed + 1, alteration,
|
||||
std::make_shared<cIntGenBiomeEdges <8>> (a_Seed + 3,
|
||||
std::make_shared<cIntGenZoom <10>>(a_Seed + 2,
|
||||
std::make_shared<cIntGenZoom <7>> (a_Seed + 4,
|
||||
std::make_shared<cIntGenReplaceRandomly<5>> (a_Seed + 99, biIcePlains, biIcePlainsSpikes, 50,
|
||||
std::make_shared<cIntGenZoom <5>> (a_Seed + 8,
|
||||
std::make_shared<cIntGenAddToOcean <4>> (a_Seed + 10, 300, biDeepOcean,
|
||||
std::make_shared<cIntGenAddToOcean <6>> (a_Seed + 9, 8, biMushroomIsland,
|
||||
std::make_shared<cIntGenBiomes <8>> (a_Seed + 3000,
|
||||
std::make_shared<cIntGenAddIslands <8>> (a_Seed + 2000, 200,
|
||||
std::make_shared<cIntGenZoom <8>> (a_Seed + 5,
|
||||
std::make_shared<cIntGenRareBiomeGroups<6>> (a_Seed + 5, 50,
|
||||
std::make_shared<cIntGenBiomeGroupEdges<6>> (
|
||||
std::make_shared<cIntGenAddIslands <8>> (a_Seed + 2000, 200,
|
||||
std::make_shared<cIntGenZoom <8>> (a_Seed + 7,
|
||||
std::make_shared<cIntGenSetRandomly <6>> (a_Seed + 8, 50, bgOcean,
|
||||
std::make_shared<cIntGenReplaceRandomly<6>> (a_Seed + 101, bgIce, bgTemperate, 150,
|
||||
std::make_shared<cIntGenAddIslands <6>> (a_Seed + 2000, 200,
|
||||
std::make_shared<cIntGenSetRandomly <6>> (a_Seed + 9, 50, bgOcean,
|
||||
std::make_shared<cIntGenZoom <6>> (a_Seed + 10,
|
||||
std::make_shared<cIntGenLandOcean <5>> (a_Seed + 100, 30
|
||||
)))))))))))))))))))))))))))))));
|
||||
|
||||
m_Gen =
|
||||
std::make_shared<cIntGenSmooth <16>>(a_Seed,
|
||||
std::make_shared<cIntGenZoom <18>>(a_Seed,
|
||||
std::make_shared<cIntGenSmooth <11>>(a_Seed,
|
||||
std::make_shared<cIntGenZoom <13>>(a_Seed,
|
||||
std::make_shared<cIntGenMixRivers<8>> (
|
||||
FinalBiomes, FinalRivers
|
||||
)))));
|
||||
}
|
||||
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override
|
||||
{
|
||||
cIntGen<16, 16>::Values vals;
|
||||
m_Gen->GetInts(a_ChunkX * cChunkDef::Width, a_ChunkZ * cChunkDef::Width, vals);
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
cChunkDef::SetBiome(a_Biomes, x, z, (EMCSBiome)vals[x + cChunkDef::Width * z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<cIntGen<16, 16>> m_Gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cBioGenGrown:
|
||||
|
||||
class cBioGenProtGrown:
|
||||
public cBiomeGen
|
||||
{
|
||||
public:
|
||||
cBioGenProtGrown(int a_Seed)
|
||||
{
|
||||
auto FinalRivers =
|
||||
std::make_shared<cProtIntGenSmooth>(a_Seed + 1,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 2,
|
||||
std::make_shared<cProtIntGenRiver >(a_Seed + 3,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 4,
|
||||
std::make_shared<cProtIntGenSmooth>(a_Seed + 5,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 8,
|
||||
std::make_shared<cProtIntGenSmooth>(a_Seed + 5,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 9,
|
||||
std::make_shared<cProtIntGenSmooth>(a_Seed + 5,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 10,
|
||||
std::make_shared<cProtIntGenSmooth>(a_Seed + 5,
|
||||
std::make_shared<cProtIntGenSmooth>(a_Seed + 6,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 11,
|
||||
std::make_shared<cProtIntGenChoice>(a_Seed + 12, 2
|
||||
))))))))))))));
|
||||
|
||||
auto alteration =
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed,
|
||||
std::make_shared<cProtIntGenLandOcean>(a_Seed, 20
|
||||
));
|
||||
|
||||
auto alteration2 =
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 1,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 2,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 1,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 2,
|
||||
std::make_shared<cProtIntGenLandOcean>(a_Seed + 1, 10
|
||||
)))));
|
||||
|
||||
auto FinalBiomes =
|
||||
std::make_shared<cProtIntGenSmooth >(a_Seed + 1,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 15,
|
||||
std::make_shared<cProtIntGenSmooth >(a_Seed + 1,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 16,
|
||||
std::make_shared<cProtIntGenBeaches >(
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 1,
|
||||
std::make_shared<cProtIntGenAddIslands >(a_Seed + 2004, 10,
|
||||
std::make_shared<cProtIntGenAddToOcean >(a_Seed + 10, 500, biDeepOcean,
|
||||
std::make_shared<cProtIntGenReplaceRandomly>(a_Seed + 1, biPlains, biSunflowerPlains, 20,
|
||||
std::make_shared<cProtIntGenMBiomes >(a_Seed + 5, alteration2,
|
||||
std::make_shared<cProtIntGenAlternateBiomes>(a_Seed + 1, alteration,
|
||||
std::make_shared<cProtIntGenBiomeEdges >(a_Seed + 3,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 2,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 4,
|
||||
std::make_shared<cProtIntGenReplaceRandomly>(a_Seed + 99, biIcePlains, biIcePlainsSpikes, 50,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 8,
|
||||
std::make_shared<cProtIntGenAddToOcean >(a_Seed + 10, 300, biDeepOcean,
|
||||
std::make_shared<cProtIntGenAddToOcean >(a_Seed + 9, 8, biMushroomIsland,
|
||||
std::make_shared<cProtIntGenBiomes >(a_Seed + 3000,
|
||||
std::make_shared<cProtIntGenAddIslands >(a_Seed + 2000, 200,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 5,
|
||||
std::make_shared<cProtIntGenRareBiomeGroups>(a_Seed + 5, 50,
|
||||
std::make_shared<cProtIntGenBiomeGroupEdges>(
|
||||
std::make_shared<cProtIntGenAddIslands >(a_Seed + 2000, 200,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 7,
|
||||
std::make_shared<cProtIntGenSetRandomly >(a_Seed + 8, 50, bgOcean,
|
||||
std::make_shared<cProtIntGenReplaceRandomly>(a_Seed + 101, bgIce, bgTemperate, 150,
|
||||
std::make_shared<cProtIntGenAddIslands >(a_Seed + 2000, 200,
|
||||
std::make_shared<cProtIntGenSetRandomly >(a_Seed + 9, 50, bgOcean,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed + 10,
|
||||
std::make_shared<cProtIntGenLandOcean >(a_Seed + 100, 30
|
||||
)))))))))))))))))))))))))))))));
|
||||
|
||||
m_Gen =
|
||||
std::make_shared<cProtIntGenSmooth >(a_Seed,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed,
|
||||
std::make_shared<cProtIntGenSmooth >(a_Seed,
|
||||
std::make_shared<cProtIntGenZoom >(a_Seed,
|
||||
std::make_shared<cProtIntGenMixRivers>(
|
||||
FinalBiomes, FinalRivers
|
||||
)))));
|
||||
}
|
||||
|
||||
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_Biomes) override
|
||||
{
|
||||
int vals[16 * 16];
|
||||
m_Gen->GetInts(a_ChunkX * cChunkDef::Width, a_ChunkZ * cChunkDef::Width, 16, 16, vals);
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
cChunkDef::SetBiome(a_Biomes, x, z, (EMCSBiome)vals[x + cChunkDef::Width * z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::shared_ptr<cProtIntGen> m_Gen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cBiomeGen:
|
||||
|
||||
@ -952,6 +1164,14 @@ cBiomeGenPtr cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool &
|
||||
{
|
||||
res = new cBioGenTwoLevel(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "grown") == 0)
|
||||
{
|
||||
res = new cBioGenGrown(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "grownprot") == 0)
|
||||
{
|
||||
res = new cBioGenProtGrown(a_Seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NoCaseCompare(BiomeGenName, "multistepmap") != 0)
|
||||
@ -981,3 +1201,51 @@ cBiomeGenPtr cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool &
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Performance tests:
|
||||
|
||||
// Change to 1 to enable the perf test:
|
||||
#if 0
|
||||
|
||||
class cBioGenPerfTest
|
||||
{
|
||||
public:
|
||||
cBioGenPerfTest()
|
||||
{
|
||||
std::cout << "BioGen performance tests commencing, please wait..." << std::endl;
|
||||
TestGen("MultiStepMap", std::make_unique<cBioGenMultiStepMap>(1).get());
|
||||
TestGen("Grown", std::make_unique<cBioGenGrown>(1).get());
|
||||
TestGen("GrownProt", std::make_unique<cBioGenProtGrown>(1).get());
|
||||
std::cout << "BioGen performance tests complete." << std::endl;
|
||||
}
|
||||
|
||||
protected:
|
||||
void TestGen(const AString && a_GenName, cBiomeGen * a_BioGen)
|
||||
{
|
||||
// Initialize the default settings for the generator:
|
||||
cIniFile iniFile;
|
||||
a_BioGen->InitializeBiomeGen(iniFile);
|
||||
|
||||
// Generate the biomes:
|
||||
auto start = std::chrono::system_clock::now();
|
||||
for (int z = 0; z < 100; z++)
|
||||
{
|
||||
for (int x = 0; x < 100; x++)
|
||||
{
|
||||
cChunkDef::BiomeMap biomes;
|
||||
a_BioGen->GenBiomes(x, z, biomes);
|
||||
} // for x
|
||||
} // for z
|
||||
auto dur = std::chrono::system_clock::now() - start;
|
||||
double milliseconds = static_cast<double>((std::chrono::duration_cast<std::chrono::milliseconds>(dur)).count());
|
||||
|
||||
std::cout << a_GenName << ": " << 1000.0 * 100.0 * 100.0 / milliseconds << " chunks per second" << std::endl;
|
||||
}
|
||||
} g_BioGenPerfTest;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -46,6 +46,7 @@ SET (HDRS
|
||||
FinishGen.h
|
||||
GridStructGen.h
|
||||
HeiGen.h
|
||||
IntGen.h
|
||||
MineShafts.h
|
||||
NetherFortGen.h
|
||||
Noise3DGenerator.h
|
||||
@ -53,6 +54,7 @@ SET (HDRS
|
||||
PieceGenerator.h
|
||||
Prefab.h
|
||||
PrefabPiecePool.h
|
||||
ProtIntGen.h
|
||||
RainbowRoadsGen.h
|
||||
Ravines.h
|
||||
RoughRavines.h
|
||||
|
@ -227,15 +227,15 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] =
|
||||
/* biMesaPlateau */ { 2.0f, 2.0f}, // 39
|
||||
|
||||
// biomes 40 .. 128 are unused, 89 empty placeholders here:
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 40 .. 49
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 50 .. 59
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 60 .. 69
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 70 .. 79
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 80 .. 89
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 90 .. 99
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 100 .. 109
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 110 .. 119
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, // 120 .. 128
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 40 .. 49
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 50 .. 59
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 60 .. 69
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 70 .. 79
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 80 .. 89
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 90 .. 99
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 100 .. 109
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 110 .. 119
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 120 .. 128
|
||||
|
||||
// Release 1.7 /* biome variants:
|
||||
/* biSunflowerPlains */ { 1.0f, 1.0f}, // 129
|
||||
@ -246,22 +246,22 @@ const cDistortedHeightmap::sGenParam cDistortedHeightmap::m_GenParam[256] =
|
||||
/* biSwamplandM */ { 0.0f, 0.0f}, // 134
|
||||
|
||||
// Biomes 135 .. 139 unused, 5 empty placeholders here:
|
||||
{}, {}, {}, {}, {}, // 135 .. 139
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 135 .. 139
|
||||
|
||||
/* biIcePlainsSpikes */ { 1.0f, 1.0f}, // 140
|
||||
|
||||
// Biomes 141 .. 148 unused, 8 empty placeholders here:
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, // 141 .. 148
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 141 .. 148
|
||||
|
||||
/* biJungleM */ { 4.0f, 4.0f}, // 149
|
||||
{}, // 150
|
||||
{0.0f, 0.0f}, // 150
|
||||
/* biJungleEdgeM */ { 3.0f, 3.0f}, // 151
|
||||
{}, {}, {}, // 152 .. 154
|
||||
{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, // 152 .. 154
|
||||
/* biBirchForestM */ { 3.0f, 3.0f}, // 155
|
||||
/* biBirchForestHillsM */ { 5.0f, 5.0f}, // 156
|
||||
/* biRoofedForestM */ { 2.0f, 2.0f}, // 157
|
||||
/* biColdTaigaM */ { 1.0f, 1.0f}, // 158
|
||||
{}, // 159
|
||||
{0.0f, 0.0f}, // 159
|
||||
/* biMegaSpruceTaiga */ { 3.0f, 3.0f}, // 160
|
||||
/* biMegaSpruceTaigaHills */ { 3.0f, 3.0f}, // 161
|
||||
/* biExtremeHillsPlusM */ {32.0f, 32.0f}, // 162
|
||||
|
@ -414,6 +414,11 @@ void cFinishGenSnow::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// There's no snow in the other biomes.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for z
|
||||
@ -454,6 +459,11 @@ void cFinishGenIce::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// No icy water in other biomes.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // for z
|
||||
|
@ -16,81 +16,6 @@
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cTerrainHeightGen:
|
||||
|
||||
cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault)
|
||||
{
|
||||
AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", "");
|
||||
if (HeightGenName.empty())
|
||||
{
|
||||
LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\".");
|
||||
HeightGenName = "Biomal";
|
||||
}
|
||||
|
||||
a_CacheOffByDefault = false;
|
||||
cTerrainHeightGen * res = nullptr;
|
||||
if (NoCaseCompare(HeightGenName, "flat") == 0)
|
||||
{
|
||||
res = new cHeiGenFlat;
|
||||
a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "classic") == 0)
|
||||
{
|
||||
res = new cHeiGenClassic(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0)
|
||||
{
|
||||
res = new cDistortedHeightmap(a_Seed, a_BiomeGen);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "End") == 0)
|
||||
{
|
||||
res = new cEndGen(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "Mountains") == 0)
|
||||
{
|
||||
res = new cHeiGenMountains(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
|
||||
{
|
||||
res = new cNoise3DComposable(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "biomal") == 0)
|
||||
{
|
||||
res = new cHeiGenBiomal(a_Seed, a_BiomeGen);
|
||||
|
||||
/*
|
||||
// Performance-testing:
|
||||
LOGINFO("Measuring performance of cHeiGenBiomal...");
|
||||
clock_t BeginTick = clock();
|
||||
for (int x = 0; x < 500; x++)
|
||||
{
|
||||
cChunkDef::HeightMap Heights;
|
||||
res->GenHeightMap(x * 5, x * 5, Heights);
|
||||
}
|
||||
clock_t Duration = clock() - BeginTick;
|
||||
LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
|
||||
//*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match found, force-set the default and retry
|
||||
LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str());
|
||||
a_IniFile.DeleteValue("Generator", "HeightGen");
|
||||
a_IniFile.SetValue("Generator", "HeightGen", "Biomal");
|
||||
return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
|
||||
}
|
||||
|
||||
// Read the settings:
|
||||
res->InitializeHeightGen(a_IniFile);
|
||||
|
||||
return cTerrainHeightGenPtr(res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cHeiGenFlat:
|
||||
|
||||
@ -430,15 +355,15 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
|
||||
/* biMesaPlateau */ { 0.1f, 1.0f, 0.05f, 1.5f, 0.01f, 4.0f, 80},
|
||||
|
||||
// biomes 40 .. 128 are unused, 89 empty placeholders here:
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 40 .. 49
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 50 .. 59
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 60 .. 69
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 70 .. 79
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 80 .. 89
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 90 .. 99
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 100 .. 109
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, // 110 .. 119
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, // 120 .. 128
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 40 .. 49
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 50 .. 59
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 60 .. 69
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 70 .. 79
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 80 .. 89
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 90 .. 99
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 100 .. 109
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 110 .. 119
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 120 .. 128
|
||||
|
||||
/* biSunflowerPlains */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 129
|
||||
/* biDesertM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 130
|
||||
@ -448,22 +373,22 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
|
||||
/* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134
|
||||
|
||||
// Biomes 135 .. 139 unused, 5 empty placeholders here:
|
||||
{}, {}, {}, {}, {}, // 135 .. 139
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 135 .. 139
|
||||
|
||||
/* biIcePlainsSpikes */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 140
|
||||
|
||||
// Biomes 141 .. 148 unused, 8 empty placeholders here:
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, // 141 .. 148
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 141 .. 148
|
||||
|
||||
/* biJungleM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 149
|
||||
{}, // 150
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 150
|
||||
/* biJungleEdgeM */ { 0.1f, 3.0f, 0.05f, 6.0f, 0.01f, 6.0f, 70}, // 151
|
||||
{}, {}, {}, // 152 .. 154
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 152 .. 154
|
||||
/* biBirchForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 155
|
||||
/* biBirchForestHillsM */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 156
|
||||
/* biRoofedForestM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 157
|
||||
/* biColdTaigaM */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 158
|
||||
{}, // 159
|
||||
{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0}, // 159
|
||||
/* biMegaSpruceTaiga */ { 0.1f, 1.0f, 0.05f, 2.0f, 0.01f, 4.0f, 70}, // 160
|
||||
/* biMegaSpruceTaigaHills */ { 0.2f, 2.0f, 0.05f, 10.0f, 0.01f, 8.0f, 80}, // 161
|
||||
/* biExtremeHillsPlusM */ { 0.2f, 4.0f, 0.05f, 20.0f, 0.01f, 16.0f, 120}, // 162
|
||||
@ -611,3 +536,283 @@ NOISE_DATATYPE cHeiGenBiomal::GetHeightAt(int a_RelX, int a_RelZ, int a_ChunkX,
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cHeiGenMinMax:
|
||||
|
||||
class cHeiGenMinMax:
|
||||
public cTerrainHeightGen
|
||||
{
|
||||
typedef cTerrainHeightGen super;
|
||||
|
||||
/** Size of the averaging process, in columns (for each direction). Must be less than 16. */
|
||||
static const int AVERAGING_SIZE = 4;
|
||||
|
||||
public:
|
||||
cHeiGenMinMax(int a_Seed, cBiomeGenPtr a_BiomeGen):
|
||||
m_Noise(a_Seed),
|
||||
m_BiomeGen(a_BiomeGen),
|
||||
m_TotalWeight(0)
|
||||
{
|
||||
// Initialize the weights:
|
||||
for (int z = 0; z <= AVERAGING_SIZE * 2; z++)
|
||||
{
|
||||
for (int x = 0; x <= AVERAGING_SIZE * 2; x++)
|
||||
{
|
||||
m_Weights[z][x] = 1 + 2 * AVERAGING_SIZE - std::abs(x - AVERAGING_SIZE) - std::abs(z - AVERAGING_SIZE);
|
||||
m_TotalWeight += m_Weights[z][x];
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the Perlin generator:
|
||||
m_Perlin.AddOctave(0.04f, 0.2f);
|
||||
m_Perlin.AddOctave(0.02f, 0.1f);
|
||||
m_Perlin.AddOctave(0.01f, 0.05f);
|
||||
}
|
||||
|
||||
|
||||
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
|
||||
{
|
||||
// Generate the biomes for the 3*3 neighbors:
|
||||
cChunkDef::BiomeMap neighborBiomes[3][3];
|
||||
for (int z = 0; z < 3; z++) for (int x = 0; x < 3; x++)
|
||||
{
|
||||
m_BiomeGen->GenBiomes(a_ChunkX + x - 1, a_ChunkZ + z - 1, neighborBiomes[z][x]);
|
||||
}
|
||||
|
||||
// Get the min and max heights based on the biomes:
|
||||
double minHeight[cChunkDef::Width * cChunkDef::Width];
|
||||
double maxHeight[cChunkDef::Width * cChunkDef::Width];
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
// For each column, sum the min and max values of the neighborhood around it:
|
||||
double min = 0, max = 0;
|
||||
for (int relz = 0; relz <= AVERAGING_SIZE * 2; relz++)
|
||||
{
|
||||
int bz = z + 16 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start
|
||||
int cz = bz / 16; // Chunk Z coord relative to the neighborBiomes start
|
||||
bz = bz % 16; // Biome Z coord relative to cz in neighborBiomes
|
||||
for (int relx = 0; relx <= AVERAGING_SIZE * 2; relx++)
|
||||
{
|
||||
int bx = x + 16 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start
|
||||
int cx = bx / 16; // Chunk X coord relative to the neighborBiomes start
|
||||
bx = bx % 16; // Biome X coord relative to cz in neighborBiomes
|
||||
|
||||
// Get the biome's min and max heights:
|
||||
double bmin, bmax;
|
||||
getBiomeMinMax(cChunkDef::GetBiome(neighborBiomes[cz][cx], bx, bz), bmin, bmax);
|
||||
|
||||
// Add them to the total, with the weight depending on their relative position to the column:
|
||||
min += bmin * m_Weights[relz][relx];
|
||||
max += bmax * m_Weights[relz][relx];
|
||||
} // for relx
|
||||
} // for relz
|
||||
minHeight[x + z * cChunkDef::Width] = min / m_TotalWeight;
|
||||
maxHeight[x + z * cChunkDef::Width] = max / m_TotalWeight;
|
||||
} // for x
|
||||
} // for z
|
||||
|
||||
// Generate the base noise:
|
||||
NOISE_DATATYPE noise[cChunkDef::Width * cChunkDef::Width];
|
||||
NOISE_DATATYPE workspace[cChunkDef::Width * cChunkDef::Width];
|
||||
NOISE_DATATYPE startX = static_cast<float>(a_ChunkX * cChunkDef::Width);
|
||||
NOISE_DATATYPE endX = startX + cChunkDef::Width - 1;
|
||||
NOISE_DATATYPE startZ = static_cast<float>(a_ChunkZ * cChunkDef::Width);
|
||||
NOISE_DATATYPE endZ = startZ + cChunkDef::Width - 1;
|
||||
m_Perlin.Generate2D(noise, 16, 16, startX, endX, startZ, endZ, workspace);
|
||||
|
||||
// Make the height by ranging the noise between min and max:
|
||||
for (int z = 0; z < cChunkDef::Width; z++)
|
||||
{
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
double min = minHeight[x + z * cChunkDef::Width];
|
||||
double max = maxHeight[x + z * cChunkDef::Width];
|
||||
double h = (max + min) / 2 + noise[x + z * cChunkDef::Width] * (max - min);
|
||||
cChunkDef::SetHeight(a_HeightMap, x, z, static_cast<HEIGHTTYPE>(h));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void InitializeHeightGen(cIniFile & a_IniFile)
|
||||
{
|
||||
// No settings available
|
||||
}
|
||||
|
||||
protected:
|
||||
cNoise m_Noise;
|
||||
|
||||
cPerlinNoise m_Perlin;
|
||||
|
||||
/** The biome generator to query for the underlying biomes. */
|
||||
cBiomeGenPtr m_BiomeGen;
|
||||
|
||||
/** Weights applied to each of the min / max values in the neighborhood of the currently evaluated column. */
|
||||
double m_Weights[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1];
|
||||
|
||||
/** Sum of all the m_Weights items. */
|
||||
double m_TotalWeight;
|
||||
|
||||
|
||||
/** Returns the minimum and maximum heights for the given biome. */
|
||||
void getBiomeMinMax(EMCSBiome a_Biome, double & a_Min, double & a_Max)
|
||||
{
|
||||
switch (a_Biome)
|
||||
{
|
||||
case biBeach: a_Min = 61; a_Max = 64; break;
|
||||
case biBirchForest: a_Min = 63; a_Max = 75; break;
|
||||
case biBirchForestHills: a_Min = 63; a_Max = 90; break;
|
||||
case biBirchForestHillsM: a_Min = 63; a_Max = 90; break;
|
||||
case biBirchForestM: a_Min = 63; a_Max = 75; break;
|
||||
case biColdBeach: a_Min = 61; a_Max = 64; break;
|
||||
case biColdTaiga: a_Min = 63; a_Max = 75; break;
|
||||
case biColdTaigaHills: a_Min = 63; a_Max = 90; break;
|
||||
case biColdTaigaM: a_Min = 63; a_Max = 75; break;
|
||||
case biDeepOcean: a_Min = 30; a_Max = 60; break;
|
||||
case biDesert: a_Min = 63; a_Max = 70; break;
|
||||
case biDesertHills: a_Min = 63; a_Max = 85; break;
|
||||
case biDesertM: a_Min = 63; a_Max = 70; break;
|
||||
case biEnd: a_Min = 10; a_Max = 100; break;
|
||||
case biExtremeHills: a_Min = 60; a_Max = 120; break;
|
||||
case biExtremeHillsEdge: a_Min = 63; a_Max = 100; break;
|
||||
case biExtremeHillsM: a_Min = 60; a_Max = 120; break;
|
||||
case biExtremeHillsPlus: a_Min = 60; a_Max = 140; break;
|
||||
case biExtremeHillsPlusM: a_Min = 60; a_Max = 140; break;
|
||||
case biFlowerForest: a_Min = 63; a_Max = 75; break;
|
||||
case biForest: a_Min = 63; a_Max = 75; break;
|
||||
case biForestHills: a_Min = 63; a_Max = 90; break;
|
||||
case biFrozenOcean: a_Min = 45; a_Max = 64; break;
|
||||
case biFrozenRiver: a_Min = 60; a_Max = 62; break;
|
||||
case biIceMountains: a_Min = 63; a_Max = 90; break;
|
||||
case biIcePlains: a_Min = 63; a_Max = 70; break;
|
||||
case biIcePlainsSpikes: a_Min = 60; a_Max = 70; break;
|
||||
case biJungle: a_Min = 60; a_Max = 80; break;
|
||||
case biJungleEdge: a_Min = 62; a_Max = 75; break;
|
||||
case biJungleEdgeM: a_Min = 62; a_Max = 75; break;
|
||||
case biJungleHills: a_Min = 60; a_Max = 90; break;
|
||||
case biJungleM: a_Min = 60; a_Max = 75; break;
|
||||
case biMegaSpruceTaiga: a_Min = 63; a_Max = 75; break;
|
||||
case biMegaSpruceTaigaHills: a_Min = 63; a_Max = 90; break;
|
||||
case biMegaTaiga: a_Min = 63; a_Max = 75; break;
|
||||
case biMegaTaigaHills: a_Min = 63; a_Max = 90; break;
|
||||
case biMesa: a_Min = 63; a_Max = 90; break;
|
||||
case biMesaBryce: a_Min = 60; a_Max = 67; break;
|
||||
case biMesaPlateau: a_Min = 75; a_Max = 85; break;
|
||||
case biMesaPlateauF: a_Min = 80; a_Max = 90; break;
|
||||
case biMesaPlateauFM: a_Min = 80; a_Max = 90; break;
|
||||
case biMesaPlateauM: a_Min = 75; a_Max = 85; break;
|
||||
case biMushroomIsland: a_Min = 63; a_Max = 90; break;
|
||||
case biMushroomShore: a_Min = 60; a_Max = 75; break;
|
||||
case biNether: a_Min = 10; a_Max = 100; break;
|
||||
case biOcean: a_Min = 45; a_Max = 64; break;
|
||||
case biPlains: a_Min = 63; a_Max = 70; break;
|
||||
case biRiver: a_Min = 60; a_Max = 62; break;
|
||||
case biRoofedForest: a_Min = 63; a_Max = 75; break;
|
||||
case biRoofedForestM: a_Min = 63; a_Max = 75; break;
|
||||
case biSavanna: a_Min = 63; a_Max = 75; break;
|
||||
case biSavannaM: a_Min = 63; a_Max = 80; break;
|
||||
case biSavannaPlateau: a_Min = 75; a_Max = 100; break;
|
||||
case biSavannaPlateauM: a_Min = 80; a_Max = 160; break;
|
||||
case biStoneBeach: a_Min = 60; a_Max = 64; break;
|
||||
case biSunflowerPlains: a_Min = 63; a_Max = 70; break;
|
||||
case biSwampland: a_Min = 60; a_Max = 67; break;
|
||||
case biSwamplandM: a_Min = 61; a_Max = 67; break;
|
||||
case biTaiga: a_Min = 63; a_Max = 75; break;
|
||||
case biTaigaHills: a_Min = 63; a_Max = 90; break;
|
||||
case biTaigaM: a_Min = 63; a_Max = 80; break;
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unknown biome");
|
||||
a_Min = 10;
|
||||
a_Max = 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cTerrainHeightGen:
|
||||
|
||||
cTerrainHeightGenPtr cTerrainHeightGen::CreateHeightGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, int a_Seed, bool & a_CacheOffByDefault)
|
||||
{
|
||||
AString HeightGenName = a_IniFile.GetValueSet("Generator", "HeightGen", "");
|
||||
if (HeightGenName.empty())
|
||||
{
|
||||
LOGWARN("[Generator] HeightGen value not set in world.ini, using \"Biomal\".");
|
||||
HeightGenName = "Biomal";
|
||||
}
|
||||
|
||||
a_CacheOffByDefault = false;
|
||||
cTerrainHeightGen * res = nullptr;
|
||||
if (NoCaseCompare(HeightGenName, "flat") == 0)
|
||||
{
|
||||
res = new cHeiGenFlat;
|
||||
a_CacheOffByDefault = true; // We're generating faster than a cache would retrieve data
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "classic") == 0)
|
||||
{
|
||||
res = new cHeiGenClassic(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0)
|
||||
{
|
||||
res = new cDistortedHeightmap(a_Seed, a_BiomeGen);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "End") == 0)
|
||||
{
|
||||
res = new cEndGen(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "MinMax") == 0)
|
||||
{
|
||||
res = new cHeiGenMinMax(a_Seed, a_BiomeGen);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "Mountains") == 0)
|
||||
{
|
||||
res = new cHeiGenMountains(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
|
||||
{
|
||||
res = new cNoise3DComposable(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(HeightGenName, "biomal") == 0)
|
||||
{
|
||||
res = new cHeiGenBiomal(a_Seed, a_BiomeGen);
|
||||
|
||||
/*
|
||||
// Performance-testing:
|
||||
LOGINFO("Measuring performance of cHeiGenBiomal...");
|
||||
clock_t BeginTick = clock();
|
||||
for (int x = 0; x < 500; x++)
|
||||
{
|
||||
cChunkDef::HeightMap Heights;
|
||||
res->GenHeightMap(x * 5, x * 5, Heights);
|
||||
}
|
||||
clock_t Duration = clock() - BeginTick;
|
||||
LOGINFO("HeightGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
|
||||
//*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match found, force-set the default and retry
|
||||
LOGWARN("Unknown HeightGen \"%s\", using \"Biomal\" instead.", HeightGenName.c_str());
|
||||
a_IniFile.DeleteValue("Generator", "HeightGen");
|
||||
a_IniFile.SetValue("Generator", "HeightGen", "Biomal");
|
||||
return CreateHeightGen(a_IniFile, a_BiomeGen, a_Seed, a_CacheOffByDefault);
|
||||
}
|
||||
|
||||
// Read the settings:
|
||||
res->InitializeHeightGen(a_IniFile);
|
||||
|
||||
return cTerrainHeightGenPtr(res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1406
src/Generating/IntGen.h
Normal file
1351
src/Generating/ProtIntGen.h
Normal file
@ -9,7 +9,7 @@
|
||||
// Email: Shane.Hill@dsto.defence.gov.au
|
||||
// Reason: Remove dependancy on MFC. Code should compile on any
|
||||
// platform.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
!! MODIFIED BY FAKETRUTH and xoft !!
|
||||
@ -79,7 +79,7 @@ bool cIniFile::ReadFile(const AString & a_FileName, bool a_AllowExampleRedirect)
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFirstLine = true;
|
||||
bool IsFirstLine = true;
|
||||
|
||||
while (getline(f, line))
|
||||
{
|
||||
@ -866,7 +866,7 @@ AString cIniFile::CheckCase(const AString & s) const
|
||||
|
||||
void cIniFile::RemoveBom(AString & a_line) const
|
||||
{
|
||||
// The BOM sequence for UTF-8 is 0xEF,0xBB,0xBF
|
||||
// The BOM sequence for UTF-8 is 0xEF, 0xBB, 0xBF
|
||||
static unsigned const char BOM[] = { 0xEF, 0xBB, 0xBF };
|
||||
|
||||
// The BOM sequence, if present, is always th e first three characters of the input.
|
||||
|
@ -9,7 +9,7 @@
|
||||
// Email: Shane.Hill@dsto.defence.gov.au
|
||||
// Reason: Remove dependancy on MFC. Code should compile on any
|
||||
// platform. Tested on Windows/Linux/Irix
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
!! MODIFIED BY FAKETRUTH and madmaxoft!!
|
||||
|
@ -604,6 +604,28 @@ void cNBTChunkSerializer::AddMonsterEntity(cMonster * a_Monster)
|
||||
m_Writer.AddByte("IsConverting", (((const cZombie *)a_Monster)->IsConverting() ? 1 : 0));
|
||||
break;
|
||||
}
|
||||
case mtInvalidType:
|
||||
case mtBlaze:
|
||||
case mtCaveSpider:
|
||||
case mtChicken:
|
||||
case mtCow:
|
||||
case mtEnderDragon:
|
||||
case mtGhast:
|
||||
case mtGiant:
|
||||
case mtIronGolem:
|
||||
case mtMooshroom:
|
||||
case mtOcelot:
|
||||
case mtPig:
|
||||
case mtSilverfish:
|
||||
case mtSnowGolem:
|
||||
case mtSpider:
|
||||
case mtSquid:
|
||||
case mtWitch:
|
||||
case mtZombiePigman:
|
||||
{
|
||||
// Other mobs have no special tags.
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
@ -696,11 +696,28 @@ cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a
|
||||
bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||
{
|
||||
int Type = a_NBT.FindChildByName(a_TagIdx, "id");
|
||||
if ((Type < 0) || (a_NBT.GetType(Type) != TAG_Short))
|
||||
if (Type <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
a_Item.m_ItemType = a_NBT.GetShort(Type);
|
||||
|
||||
if (a_NBT.GetType(Type) == TAG_String)
|
||||
{
|
||||
if (!StringToItem(a_NBT.GetString(Type), a_Item))
|
||||
{
|
||||
// Can't resolve item type
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (a_NBT.GetType(Type) == TAG_Short)
|
||||
{
|
||||
a_Item.m_ItemType = a_NBT.GetShort(Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a_Item.m_ItemType < 0)
|
||||
{
|
||||
a_Item.Empty();
|
||||
|