1
0

Merge branch 'master' into ViewDistance

This commit is contained in:
Howaner 2014-11-14 22:33:54 +01:00
commit a0e1e43fc1
41 changed files with 4782 additions and 566 deletions

View File

@ -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/)

View File

@ -2137,6 +2137,7 @@ cPluginManager.AddHook(cPluginManager.HOOK_CHAT, OnChatMessage);
BroadcastChatWarning = { Params = "MessageText", Return = "", Notes = "Broadcasts the specified message to all players, with its message type set to mtWarning. Use for concerning events, such as plugin reload etc." },
CreateAndInitializeWorld = { Params = "WorldName", Return = "{{cWorld|cWorld}}", Notes = "Creates a new world and initializes it. If there is a world whith the same name it returns nil.<br/><br/><b>NOTE</b>This function is currently unsafe, do not use!" },
FindAndDoWithPlayer = { Params = "PlayerName, CallbackFunction", Return = "", Notes = "Calls the given callback function for all players with names partially (or fully) matching the name string provided." },
DoWithPlayerByUUID = { Params = "PlayerUUID, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is the player with the uuid, calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}}, [CallbackData])</pre> The function returns false if the player was not found, or whatever bool value the callback returned if the player was found." },
ForEachPlayer = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each player. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|cPlayer}})</pre>" },
ForEachWorld = { Params = "CallbackFunction", Return = "", Notes = "Calls the given callback function for each world. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cWorld|cWorld}})</pre>" },
Get = { Params = "", Return = "Root object", Notes = "(STATIC)This function returns the cRoot object." },
@ -2406,6 +2407,7 @@ end
{ Params = "{{Vector3i|BlockCoords}}, BlockType, BlockMeta", Return = "", Notes = "Sets the block at the specified coords, without waking up the simulators or replacing the block entities for the previous block type. Do not use if the block being replaced has a block entity tied to it!" },
},
FindAndDoWithPlayer = { Params = "PlayerNameHint, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is a player of a name similar to the specified name (weighted-match), calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}}, [CallbackData])</pre> The function returns false if the player was not found, or whatever bool value the callback returned if the player was found. Note that the name matching is very loose, so it is a good idea to check the player name in the callback function." },
DoWithPlayerByUUID = { Params = "PlayerUUID, CallbackFunction, [CallbackData]", Return = "bool", Notes = "If there is the player with the uuid, calls the CallbackFunction with the {{cPlayer}} parameter representing the player. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cPlayer|Player}}, [CallbackData])</pre> The function returns false if the player was not found, or whatever bool value the callback returned if the player was found." },
ForEachBlockEntityInChunk = { Params = "ChunkX, ChunkZ, CallbackFunction, [CallbackData]", Return = "bool", Notes = "Calls the specified callback for each block entity in the chunk. Returns true if all block entities in the chunk have been processed (including when there are zero block entities), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cBlockEntity|BlockEntity}}, [CallbackData])</pre> The callback should return false or no value to continue with the next block entity, or true to abort the enumeration. Use {{tolua}}.cast() to cast the Callback's BlockEntity parameter to the correct {{cBlockEntity}} descendant." },
ForEachChestInChunk = { Params = "ChunkX, ChunkZ, CallbackFunction, [CallbackData]", Return = "bool", Notes = "Calls the specified callback for each chest in the chunk. Returns true if all chests in the chunk have been processed (including when there are zero chests), or false if the callback has aborted the enumeration by returning true. The CallbackFunction has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cChestEntity|ChestEntity}}, [CallbackData])</pre> The callback should return false or no value to continue with the next chest, or true to abort the enumeration." },
ForEachEntity = { Params = "CallbackFunction, [CallbackData]", Return = "bool", Notes = "Calls the specified callback for each entity in the loaded world. Returns true if all the entities have been processed (including when there are zero entities), or false if the callback function has aborted the enumeration by returning true. The callback function has the following signature: <pre class=\"prettyprint lang-lua\">function Callback({{cEntity|Entity}}, [CallbackData])</pre> The callback should return false or no value to continue with the next entity, or true to abort the enumeration." },

View 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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 B

View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 995 B

View File

@ -1,353 +1,427 @@
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%;
height:100%;
min-height: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: 25px;
margin-bottom: 25px;
}
#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;
margin-bottom:75px;
}
.clear
{
clear: both;
.push25 {
}
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 ul.menu {
margin: 0;
padding: 0;
list-style: none;
}
a:hover
{
color: #01579b;
#footer ul.menu li {
margin: 0 5px;
display: inline;
}
.welcome-msg
{
color: rgba(0, 0, 0, 0.54);
#footer .upper {
background: #dcdbdc url(tcat.png) repeat-x;
border-top: 1px solid #bbb;
padding: 6px;
overflow: hidden;
font-size: 12px;
}
.username
{
text-transform: capitalize;
color: rgba(0, 0, 0, 0.87);
#footer .upper ul.bottom_links {
float: left;
margin: 3px 0 0 -5px;
}
a:hover
{
color: black;
#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;
}
input, select
{
padding: 8px;
#footer .lower a:link,#footer .lower a:visited {
color: #fff;
font-weight: 700;
}
form
{
padding: 4px;
#footer .lower a:hover,#footer .lower a:active {
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 #current_time {
float: right;
padding-right: 6px;
}
.err
{
color: white;
display: block;
background-color: #e51c23 !important;
padding: 15px;
line-height: 30px;
min-height: 30px;
.wrapper {
width: 85%;
min-width: 970px;
max-width: 1500px;
margin: auto;
}
.err:before
{
content: "ERROR: ";
#footer {
position: fixed;
left:0;
bottom:0;
height: 61px;
width: 100%;
background: #999;
border-top: 1px #000 solid;
border-bottom: 1px #000 solid;
}
.warn
{
color: white;
display: block;
background-color: #ff5722 !important;
padding: 15px;
line-height: 30px;
min-height: 30px;
* 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');
}
.warn:before
{
content: "WARNING: ";
tr td.trow1:first-child, tr td.trow2:first-child {
border-left: 0;
}
.info
{
color: white;
display: block;
background-color: #5677fc !important;
padding: 15px;
line-height: 30px;
min-height: 30px;
tr td.trow1:last-child, tr td.trow2:last-child {
border-right: 0;
}
.info:before
{
content: "INFORMATION: ";
.tborder {
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
}
#footer .fleft
{
float: left;
.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 .fright
{
float: right;
text-align: right;
table {
color: #000;
font-size: 13px;
}
#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;
.tborder {
background: #fff;
width: 100%;
margin: auto;
border: 1px solid #ccc;
padding: 1px;
}
#footer a
{
text-transform: none;
color: white;
.thead {
background: #a1a2a2 url(thead.png) top left repeat-x;
color: #fff;
border-bottom: 1px solid #8e8f8f;
padding: 8px;
}
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;
.tcat {
background: #dcdbdc url(tcat.png) repeat-x;
color: #fff;
border-bottom: 1px solid #bbb;
padding: 6px;
font-size: 12px;
}
input[type="submit"]:hover, button:hover, input[type="button"]:hover
{
background-color: #ffca28;
.trow1 {
background: #f5f5f5;
border: 1px solid;
border-color: #fff #ddd #ddd #fff;
}
input[type="submit"]:active, button:active, input[type="button"]:active
{
background-color: #ffd54f;
-webkit-transform: translateY(1px);
-moz-transform: translateY(1px);
transform: translateY(1px);
.trow2 {
background: #efefef;
border: 1px solid;
border-color: #fff #ddd #ddd #fff;
padding: 15px;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
hr
{
border: none;
height: 1px;
background-color: rgba(0, 0, 0, 0.12);
table {
color: #000;
font-size: 13px;
text-align: left;
}
h4
{
padding-bottom: 10px;
margin-bottom: 12px;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
.tborder {
background: #fff;
width: 100%;
margin: auto;
border: 1px solid #ccc;
padding: 1px;
}
/**** PAGE SPECIFIC CSS ****/
/* remove the * for disabling: */
.page-core-server-settings table td
{
text-align: center;
width: 25%;
.thead {
background: #a1a2a2 url(thead.png) top left repeat-x;
color: #fff;
border-bottom: 1px solid #8e8f8f;
padding: 8px;
}
.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);
.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-monsters table td:nth-child(2) 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-server-settings.param-tab-worlds table td:nth-child(3) a
{
font-weight: 600;
color: rgba(0, 0, 0, 0.87);
.trow2 {
background: #efefef;
border: 1px solid;
border-color: #fff #ddd #ddd #fff;
}
.page-core-server-settings.param-tab-world table td:nth-child(4) a
{
font-weight: 600;
color: rgba(0, 0, 0, 0.87);
.smalltext {
font-size: 11px;
}
.page-core-permissions form table tr,
.page-core-permissions form table td,
.page-core-permissions form table th
{
border: none;
background-color: transparent;
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 tr:nth-child(1) th
{
width: 35%;
select {
background: #fff;
padding: 3px;
border: 1px solid #ccc;
font-family: Tahoma,Verdana,Arial,Sans-Serif;
}
.page-core-permissions form table tr:nth-child(1) td
{
width: 65%;
.usercp_nav_item {
display: block;
padding: 1px 0 1px 23px;
}
.page-core-permissions form table td input
{
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
margin: 0;
.usercp_nav_pmfolder {
background: url(pmfolder.gif) no-repeat left center;
}
#ChatDiv
{
margin-bottom: 10px;
.usercp_nav_sub_pmfolder {
padding-left: 40px;
background: url(sub_pmfolder.gif) no-repeat left center;
}
#ChatMessage
{
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
.usercp_nav_home {
background: url(home.gif) no-repeat left center;
}
/**/
.pagehead {
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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1022 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 B

View File

@ -1,25 +1,69 @@
<!-- 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="copyright">Copyright © <a href="http://www.mc-server.org" target="_blank">MCServer Team</a> 2014.</span>
</div>
</div>
</div>
</body>
</html>

View File

@ -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 push25">
<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>&nbsp;&nbsp;&nbsp;<a href=".././"><img src="/log_out.png" style="vertical-align:bottom;"> Log Out</a></div>
</div>
</div>
</div>
</div>
<div class="row2">
<div class="wrapper">
<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,58 @@ 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 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 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="copyright">Copyright © <a href="http://www.mc-server.org" target="_blank">MCServer Team</a> 2014.</span>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,4 +1,4 @@
MCServer [![Build Status](http://img.shields.io/travis/mc-server/MCServer.svg)](https://travis-ci.org/mc-server/MCServer) [![Coverity Scan Build Status](https://scan.coverity.com/projects/1930/badge.svg)](https://scan.coverity.com/projects/1930) [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
MCServer [![Build Status](http://img.shields.io/travis/mc-server/MCServer/master.svg?style=flat)](https://travis-ci.org/mc-server/MCServer) [![Coverity Scan Build Status](https://scan.coverity.com/projects/1930/badge.svg)](https://scan.coverity.com/projects/1930) [![weekly tips](http://img.shields.io/gratipay/cuberite_team.svg?style=flat)](http://gratipay.com/cuberite_team) [![tip for next commit](http://tip4commit.com/projects/74.svg)](http://tip4commit.com/projects/74)
========
MCServer is a Minecraft server that is written in C++ and designed to be efficient with memory and CPU, as well as having a flexible Lua Plugin API.
@ -10,9 +10,11 @@ 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.github.com/mc-server/MCServer/master/easyinstall.sh | sh
curl -s https://raw.githubusercontent.com/mc-server/MCServer/master/easyinstall.sh | sh
For Windows, you just need to download a file and extract it:

View File

@ -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"),

View File

@ -32,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();
@ -41,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);
@ -286,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);
}

View File

@ -12,78 +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 \
../../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
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 \
../../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
INCLUDEPATH += $$_PRO_FILE_PWD_ \
$$_PRO_FILE_PWD_/../../lib \

11
app.yml Normal file
View 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

View File

@ -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...);
}

View File

@ -3368,6 +3368,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_beginmodule(tolua_S, "cRoot");
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith <cRoot, cPlayer, &cRoot::FindAndDoWithPlayer>);
tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_DoWith <cRoot, cPlayer, &cRoot::DoWithPlayerByUUID>);
tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>);
tolua_function(tolua_S, "ForEachWorld", tolua_ForEach<cRoot, cWorld, &cRoot::ForEachWorld>);
tolua_function(tolua_S, "GetFurnaceRecipe", tolua_cRoot_GetFurnaceRecipe);
@ -3389,6 +3390,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "DoWithFlowerPotAt", tolua_DoWithXYZ<cWorld, cFlowerPotEntity, &cWorld::DoWithFlowerPotAt>);
tolua_function(tolua_S, "DoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayer>);
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith< cWorld, cPlayer, &cWorld::FindAndDoWithPlayer>);
tolua_function(tolua_S, "DoWithPlayerByUUID", tolua_DoWith< cWorld, cPlayer, &cWorld::DoWithPlayerByUUID>);
tolua_function(tolua_S, "ForEachBlockEntityInChunk", tolua_ForEachInChunk<cWorld, cBlockEntity, &cWorld::ForEachBlockEntityInChunk>);
tolua_function(tolua_S, "ForEachChestInChunk", tolua_ForEachInChunk<cWorld, cChestEntity, &cWorld::ForEachChestInChunk>);
tolua_function(tolua_S, "ForEachEntity", tolua_ForEach< cWorld, cEntity, &cWorld::ForEachEntity>);

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -73,6 +73,10 @@ cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile
{
res = new cCompoGenNether(a_Seed);
}
else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0)
{
res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen);
}
else if (NoCaseCompare(CompoGenName, "Noise3D") == 0)
{
res = new cNoise3DComposable(a_Seed);

View File

@ -199,6 +199,11 @@ void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc)
// Get the top block + 1. This is the place where the grass would finaly be placed:
int y = a_ChunkDesc.GetHeight(x, z) + 1;
if (y >= 255)
{
continue;
}
// Check if long grass can be placed:
if (

View File

@ -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:
@ -611,3 +536,287 @@ 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, "BiomalNoise3D") == 0)
{
res = new cBiomalNoise3DComposable(a_Seed, a_BiomeGen);
}
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

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,35 @@ public:
/** Linearly interpolates between two values.
Assumes that a_Ratio is in range [0, 1]. */
inline static NOISE_DATATYPE Lerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio)
{
return a_Val1 + (a_Val2 - a_Val1) * a_Ratio;
}
/** Linearly interpolates between two values, clamping the ratio to [0, 1] first. */
inline static NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio)
{
if (a_Ratio < 0)
{
return a_Val1;
}
if (a_Ratio > 1)
{
return a_Val2;
}
return Lerp(a_Val1, a_Val2, a_Ratio);
}
////////////////////////////////////////////////////////////////////////////////
// cNoise3DGenerator:
@ -346,9 +375,10 @@ void cNoise3DGenerator::ComposeTerrain(cChunkDesc & a_ChunkDesc)
// cNoise3DComposable:
cNoise3DComposable::cNoise3DComposable(int a_Seed) :
m_Noise1(a_Seed + 1000),
m_Noise2(a_Seed + 2000),
m_Noise3(a_Seed + 3000)
m_ChoiceNoise(a_Seed),
m_DensityNoiseA(a_Seed + 1),
m_DensityNoiseB(a_Seed + 2),
m_BaseNoise(a_Seed + 3)
{
}
@ -359,13 +389,51 @@ cNoise3DComposable::cNoise3DComposable(int a_Seed) :
void cNoise3DComposable::Initialize(cIniFile & a_IniFile)
{
// Params:
// The defaults generate extreme hills terrain
m_SeaLevel = a_IniFile.GetValueSetI("Generator", "Noise3DSeaLevel", 62);
m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0);
m_HeightAmplification = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DHeightAmplification", 0.045);
m_MidPoint = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DMidPoint", 75);
m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 10);
m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 10);
m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 10);
m_AirThreshold = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0.5);
m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyX", 40);
m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyY", 40);
m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DFrequencyZ", 40);
m_BaseFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyX", 40);
m_BaseFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DBaseFrequencyZ", 40);
m_ChoiceFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyX", 40);
m_ChoiceFrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyY", 80);
m_ChoiceFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DChoiceFrequencyZ", 40);
m_AirThreshold = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DAirThreshold", 0);
int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumChoiceOctaves", 4);
int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumDensityOctaves", 6);
int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "Noise3DNumBaseOctaves", 6);
NOISE_DATATYPE BaseNoiseAmplitude = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "Noise3DBaseAmplitude", 1);
// Add octaves for the choice noise:
NOISE_DATATYPE wavlen = 1, ampl = 0.5;
for (int i = 0; i < NumChoiceOctaves; i++)
{
m_ChoiceNoise.AddOctave(wavlen, ampl);
wavlen = wavlen * 2;
ampl = ampl / 2;
}
// Add octaves for the density noises:
wavlen = 1, ampl = 1;
for (int i = 0; i < NumDensityOctaves; i++)
{
m_DensityNoiseA.AddOctave(wavlen, ampl);
m_DensityNoiseB.AddOctave(wavlen, ampl);
wavlen = wavlen * 2;
ampl = ampl / 2;
}
// Add octaves for the base noise:
wavlen = 1, ampl = BaseNoiseAmplitude;
for (int i = 0; i < NumBaseOctaves; i++)
{
m_BaseNoise.AddOctave(wavlen, ampl);
wavlen = wavlen * 2;
ampl = ampl / 2;
}
}
@ -376,119 +444,47 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ)
{
if ((a_ChunkX == m_LastChunkX) && (a_ChunkZ == m_LastChunkZ))
{
// The noise for this chunk is already generated in m_Noise
// The noise for this chunk is already generated in m_NoiseArray
return;
}
m_LastChunkX = a_ChunkX;
m_LastChunkZ = a_ChunkZ;
// Upscaling parameters:
const int UPSCALE_X = 8;
const int UPSCALE_Y = 4;
const int UPSCALE_Z = 8;
// Generate all the noises:
NOISE_DATATYPE ChoiceNoise[5 * 5 * 33];
NOISE_DATATYPE Workspace[5 * 5 * 33];
NOISE_DATATYPE DensityNoiseA[5 * 5 * 33];
NOISE_DATATYPE DensityNoiseB[5 * 5 * 33];
NOISE_DATATYPE BaseNoise[5 * 5];
NOISE_DATATYPE BlockX = static_cast<NOISE_DATATYPE>(a_ChunkX * cChunkDef::Width);
NOISE_DATATYPE BlockZ = static_cast<NOISE_DATATYPE>(a_ChunkZ * cChunkDef::Width);
// Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z":
m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace);
m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace);
m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace);
m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
// Precalculate a "height" array:
NOISE_DATATYPE Height[17 * 17]; // x + 17 * z
for (int z = 0; z < 17; z += UPSCALE_Z)
// Calculate the final noise based on the partial noises:
for (int y = 0; y < 33; y++)
{
NOISE_DATATYPE NoiseZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width + z)) / m_FrequencyZ;
for (int x = 0; x < 17; x += UPSCALE_X)
NOISE_DATATYPE AddHeight = (static_cast<NOISE_DATATYPE>(y * 8) - m_MidPoint) * m_HeightAmplification;
// If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope:
if (AddHeight < 0)
{
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX;
NOISE_DATATYPE val = std::abs(m_Noise1.CubicNoise2D(NoiseX / 5, NoiseZ / 5)) * m_HeightAmplification + 1;
Height[x + 17 * z] = val * val * val;
AddHeight *= 4;
}
}
for (int y = 0; y < 257; y += UPSCALE_Y)
{
NOISE_DATATYPE NoiseY = ((NOISE_DATATYPE)y) / m_FrequencyY;
NOISE_DATATYPE AddHeight = (y - m_MidPoint) / 20;
AddHeight *= AddHeight * AddHeight;
NOISE_DATATYPE * CurFloor = &(m_NoiseArray[y * 17 * 17]);
for (int z = 0; z < 17; z += UPSCALE_Z)
for (int z = 0; z < 5; z++)
{
NOISE_DATATYPE NoiseZ = ((NOISE_DATATYPE)(a_ChunkZ * cChunkDef::Width + z)) / m_FrequencyZ;
for (int x = 0; x < 17; x += UPSCALE_X)
for (int x = 0; x < 5; x++)
{
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX;
CurFloor[x + 17 * z] = (
m_Noise1.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * (NOISE_DATATYPE)0.5 +
m_Noise2.CubicNoise3D(NoiseX / 2, NoiseY / 2, NoiseZ / 2) +
m_Noise3.CubicNoise3D(NoiseX / 4, NoiseY / 4, NoiseZ / 4) * 2 +
AddHeight / Height[x + 17 * z]
);
int idx = x + 5 * z + 5 * 5 * y;
Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z];
}
}
// Linear-interpolate this XZ floor:
LinearUpscale2DArrayInPlace<17, 17, UPSCALE_X, UPSCALE_Z>(CurFloor);
}
// Finish the 3D linear interpolation by interpolating between each XZ-floors on the Y axis
for (int y = 1; y < cChunkDef::Height; y++)
{
if ((y % UPSCALE_Y) == 0)
{
// This is the interpolation source floor, already calculated
continue;
}
int LoFloorY = (y / UPSCALE_Y) * UPSCALE_Y;
int HiFloorY = LoFloorY + UPSCALE_Y;
NOISE_DATATYPE * LoFloor = &(m_NoiseArray[LoFloorY * 17 * 17]);
NOISE_DATATYPE * HiFloor = &(m_NoiseArray[HiFloorY * 17 * 17]);
NOISE_DATATYPE * CurFloor = &(m_NoiseArray[y * 17 * 17]);
NOISE_DATATYPE Ratio = ((NOISE_DATATYPE)(y % UPSCALE_Y)) / UPSCALE_Y;
int idx = 0;
for (int z = 0; z < cChunkDef::Width; z++)
{
for (int x = 0; x < cChunkDef::Width; x++)
{
CurFloor[idx] = LoFloor[idx] + (HiFloor[idx] - LoFloor[idx]) * Ratio;
idx += 1;
}
idx += 1; // Skipping one X column
}
}
// The noise array is now fully interpolated
/*
// DEBUG: Output two images of the array, sliced by XY and XZ:
cFile f1;
if (f1.Open(Printf("Chunk_%d_%d_XY.raw", a_ChunkX, a_ChunkZ), cFile::fmWrite))
{
for (int z = 0; z < cChunkDef::Width; z++)
{
for (int y = 0; y < cChunkDef::Height; y++)
{
int idx = y * 17 * 17 + z * 17;
unsigned char buf[16];
for (int x = 0; x < cChunkDef::Width; x++)
{
buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 128 * m_Noise[idx++]))));
}
f1.Write(buf, 16);
} // for y
} // for z
} // if (XY file open)
cFile f2;
if (f2.Open(Printf("Chunk_%d_%d_XZ.raw", a_ChunkX, a_ChunkZ), cFile::fmWrite))
{
for (int y = 0; y < cChunkDef::Height; y++)
{
for (int z = 0; z < cChunkDef::Width; z++)
{
int idx = y * 17 * 17 + z * 17;
unsigned char buf[16];
for (int x = 0; x < cChunkDef::Width; x++)
{
buf[x] = (unsigned char)(std::min(256, std::max(0, (int)(128 + 128 * m_Noise[idx++]))));
}
f2.Write(buf, 16);
} // for z
} // for y
} // if (XZ file open)
*/
LinearUpscale3DArray<NOISE_DATATYPE>(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8);
}
@ -573,3 +569,296 @@ void cNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc)
////////////////////////////////////////////////////////////////////////////////
// cBiomalNoise3DComposable:
cBiomalNoise3DComposable::cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_BiomeGen) :
m_ChoiceNoise(a_Seed),
m_DensityNoiseA(a_Seed + 1),
m_DensityNoiseB(a_Seed + 2),
m_BaseNoise(a_Seed + 3),
m_BiomeGen(a_BiomeGen)
{
// Generate the weight distribution for summing up neighboring biomes:
m_WeightSum = 0;
for (int z = 0; z <= AVERAGING_SIZE * 2; z++)
{
for (int x = 0; x <= AVERAGING_SIZE * 2; x++)
{
m_Weight[z][x] = static_cast<NOISE_DATATYPE>((5 - std::abs(5 - x)) + (5 - std::abs(5 - z)));
m_WeightSum += m_Weight[z][x];
}
}
}
void cBiomalNoise3DComposable::Initialize(cIniFile & a_IniFile)
{
// Params:
// The defaults generate extreme hills terrain
m_SeaLevel = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DSeaLevel", 62);
m_FrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyX", 40);
m_FrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyY", 40);
m_FrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DFrequencyZ", 40);
m_BaseFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyX", 40);
m_BaseFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseFrequencyZ", 40);
m_ChoiceFrequencyX = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyX", 40);
m_ChoiceFrequencyY = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyY", 80);
m_ChoiceFrequencyZ = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DChoiceFrequencyZ", 40);
m_AirThreshold = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DAirThreshold", 0);
int NumChoiceOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumChoiceOctaves", 4);
int NumDensityOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumDensityOctaves", 6);
int NumBaseOctaves = a_IniFile.GetValueSetI("Generator", "BiomalNoise3DNumBaseOctaves", 6);
NOISE_DATATYPE BaseNoiseAmplitude = (NOISE_DATATYPE)a_IniFile.GetValueSetF("Generator", "BiomalNoise3DBaseAmplitude", 1);
// Add octaves for the choice noise:
NOISE_DATATYPE wavlen = 1, ampl = 0.5;
for (int i = 0; i < NumChoiceOctaves; i++)
{
m_ChoiceNoise.AddOctave(wavlen, ampl);
wavlen = wavlen * 2;
ampl = ampl / 2;
}
// Add octaves for the density noises:
wavlen = 1, ampl = 1;
for (int i = 0; i < NumDensityOctaves; i++)
{
m_DensityNoiseA.AddOctave(wavlen, ampl);
m_DensityNoiseB.AddOctave(wavlen, ampl);
wavlen = wavlen * 2;
ampl = ampl / 2;
}
// Add octaves for the base noise:
wavlen = 1, ampl = BaseNoiseAmplitude;
for (int i = 0; i < NumBaseOctaves; i++)
{
m_BaseNoise.AddOctave(wavlen, ampl);
wavlen = wavlen * 2;
ampl = ampl / 2;
}
}
void cBiomalNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ)
{
if ((a_ChunkX == m_LastChunkX) && (a_ChunkZ == m_LastChunkZ))
{
// The noise for this chunk is already generated in m_NoiseArray
return;
}
m_LastChunkX = a_ChunkX;
m_LastChunkZ = a_ChunkZ;
// Calculate the parameters for the biomes:
ChunkParam MidPoint;
ChunkParam HeightAmp;
CalcBiomeParamArrays(a_ChunkX, a_ChunkZ, HeightAmp, MidPoint);
// Generate all the noises:
NOISE_DATATYPE ChoiceNoise[5 * 5 * 33];
NOISE_DATATYPE Workspace[5 * 5 * 33];
NOISE_DATATYPE DensityNoiseA[5 * 5 * 33];
NOISE_DATATYPE DensityNoiseB[5 * 5 * 33];
NOISE_DATATYPE BaseNoise[5 * 5];
NOISE_DATATYPE BlockX = static_cast<NOISE_DATATYPE>(a_ChunkX * cChunkDef::Width);
NOISE_DATATYPE BlockZ = static_cast<NOISE_DATATYPE>(a_ChunkZ * cChunkDef::Width);
// Note that we have to swap the coords, because noise generator uses [x + SizeX * y + SizeX * SizeY * z] ordering and we want "BlockY" to be "z":
m_ChoiceNoise.Generate3D (ChoiceNoise, 5, 5, 33, BlockX / m_ChoiceFrequencyX, (BlockX + 17) / m_ChoiceFrequencyX, BlockZ / m_ChoiceFrequencyZ, (BlockZ + 17) / m_ChoiceFrequencyZ, 0, 257 / m_ChoiceFrequencyY, Workspace);
m_DensityNoiseA.Generate3D(DensityNoiseA, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace);
m_DensityNoiseB.Generate3D(DensityNoiseB, 5, 5, 33, BlockX / m_FrequencyX, (BlockX + 17) / m_FrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, 0, 257 / m_FrequencyY, Workspace);
m_BaseNoise.Generate2D (BaseNoise, 5, 5, BlockX / m_BaseFrequencyX, (BlockX + 17) / m_BaseFrequencyX, BlockZ / m_FrequencyZ, (BlockZ + 17) / m_FrequencyZ, Workspace);
// Calculate the final noise based on the partial noises:
for (int y = 0; y < 33; y++)
{
NOISE_DATATYPE BlockHeight = static_cast<NOISE_DATATYPE>(y * 8);
for (int z = 0; z < 5; z++)
{
for (int x = 0; x < 5; x++)
{
NOISE_DATATYPE AddHeight = (BlockHeight - MidPoint[x + 5 * z]) * HeightAmp[x + 5 * z];
// If "underground", make the terrain smoother by forcing the vertical linear gradient into steeper slope:
if (AddHeight < 0)
{
AddHeight *= 4;
}
int idx = x + 5 * z + 5 * 5 * y;
Workspace[idx] = ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + BaseNoise[x + 5 * z];
}
}
}
LinearUpscale3DArray<NOISE_DATATYPE>(Workspace, 5, 5, 33, m_NoiseArray, 4, 4, 8);
}
void cBiomalNoise3DComposable::CalcBiomeParamArrays(int a_ChunkX, int a_ChunkZ, ChunkParam & a_HeightAmp, ChunkParam & a_MidPoint)
{
// Generate the 3*3 chunks of biomes around this chunk:
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[x + 3 * z]);
}
}
// Sum up the biome values:
for (int z = 0; z < 5; z++)
{
for (int x = 0; x < 5; x++)
{
NOISE_DATATYPE totalHeightAmp = 0;
NOISE_DATATYPE totalMidPoint = 0;
// Add up the biomes around this point:
for (int relz = 0; relz <= AVERAGING_SIZE * 2; ++relz)
{
int colz = 16 + z * 4 + relz - AVERAGING_SIZE; // Biome Z coord relative to the neighborBiomes start
int neicellz = colz / 16; // Chunk Z coord relative to the neighborBiomes start
int neirelz = colz % 16; // Biome Z coord relative to cz in neighborBiomes
for (int relx = 0; relx <= AVERAGING_SIZE * 2; ++relx)
{
int colx = 16 + x * 4 + relx - AVERAGING_SIZE; // Biome X coord relative to the neighborBiomes start
int neicellx = colx / 16; // Chunk X coord relative to the neighborBiomes start
int neirelx = colx % 16; // Biome X coord relative to cz in neighborBiomes
EMCSBiome biome = cChunkDef::GetBiome(neighborBiomes[neicellx + neicellz * 3], neirelx, neirelz);
NOISE_DATATYPE heightAmp, midPoint;
GetBiomeParams(biome, heightAmp, midPoint);
totalHeightAmp += heightAmp * m_Weight[relz][relx];
totalMidPoint += midPoint * m_Weight[relz][relx];
} // for relx
} // for relz
a_HeightAmp[x + 5 * z] = totalHeightAmp / m_WeightSum;
a_MidPoint[x + 5 * z] = totalMidPoint / m_WeightSum;
} // for x
} // for z
}
void cBiomalNoise3DComposable::GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint)
{
switch (a_Biome)
{
case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35; break;
case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62; break; // Needs verification
case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75; break;
case biExtremeHillsPlus: a_HeightAmp = 0.04f; a_MidPoint = 80; break;
case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break;
case biFrozenOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break;
case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63; break;
case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63; break;
case biOcean: a_HeightAmp = 0.17f; a_MidPoint = 47; break;
case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62; break; // Needs verification
case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 53; break;
case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59; break;
case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59; break;
default:
{
// Make a crazy terrain so that it stands out
a_HeightAmp = 0.001f;
a_MidPoint = 90;
break;
}
}
}
void cBiomalNoise3DComposable::GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap)
{
GenerateNoiseArrayIfNeeded(a_ChunkX, a_ChunkZ);
for (int z = 0; z < cChunkDef::Width; z++)
{
for (int x = 0; x < cChunkDef::Width; x++)
{
cChunkDef::SetHeight(a_HeightMap, x, z, m_SeaLevel);
for (int y = cChunkDef::Height - 1; y > m_SeaLevel; y--)
{
if (m_NoiseArray[y * 17 * 17 + z * 17 + x] <= m_AirThreshold)
{
cChunkDef::SetHeight(a_HeightMap, x, z, y);
break;
}
} // for y
} // for x
} // for z
}
void cBiomalNoise3DComposable::ComposeTerrain(cChunkDesc & a_ChunkDesc)
{
GenerateNoiseArrayIfNeeded(a_ChunkDesc.GetChunkX(), a_ChunkDesc.GetChunkZ());
a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
// Make basic terrain composition:
for (int z = 0; z < cChunkDef::Width; z++)
{
for (int x = 0; x < cChunkDef::Width; x++)
{
int LastAir = a_ChunkDesc.GetHeight(x, z) + 1;
bool HasHadWater = false;
for (int y = LastAir; y < m_SeaLevel; y++)
{
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER);
}
for (int y = LastAir - 1; y > 0; y--)
{
if (m_NoiseArray[x + 17 * z + 17 * 17 * y] > m_AirThreshold)
{
// "air" part
LastAir = y;
if (y < m_SeaLevel)
{
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STATIONARY_WATER);
HasHadWater = true;
}
continue;
}
// "ground" part:
if (LastAir - y > 4)
{
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_STONE);
continue;
}
if (HasHadWater)
{
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_SAND);
}
else
{
a_ChunkDesc.SetBlockType(x, y, z, (LastAir == y + 1) ? E_BLOCK_GRASS : E_BLOCK_DIRT);
}
} // for y
a_ChunkDesc.SetBlockType(x, 0, z, E_BLOCK_BEDROCK);
} // for x
} // for z
}

View File

@ -1,7 +1,11 @@
// Noise3DGenerator.h
// Generates terrain using 3D noise, rather than composing. Is a test.
// Declares cNoise3DGenerator and cNoise3DComposable classes, representing 3D-noise-based generators.
// They generate terrain shape by combining a lerp of two 3D noises with a vertical linear gradient
// cNoise3DGenerator is obsolete and unmaintained.
// cNoise3DComposable is used to test parameter combinations for single-biome worlds.
@ -74,31 +78,147 @@ public:
void Initialize(cIniFile & a_IniFile);
protected:
cNoise m_Noise1;
cNoise m_Noise2;
cNoise m_Noise3;
/** The noise that is used to choose between density noise A and B. */
cPerlinNoise m_ChoiceNoise;
/** Density 3D noise, variant A. */
cPerlinNoise m_DensityNoiseA;
/** Density 3D noise, variant B. */
cPerlinNoise m_DensityNoiseB;
/** Heightmap-like noise used to provide variance for low-amplitude biomes. */
cPerlinNoise m_BaseNoise;
int m_SeaLevel;
/** Block height of the sealevel, used for composing the terrain. */
int m_SeaLevel;
/** The main parameter of the generator, specifies the slope of the vertical linear gradient.
A higher value means a steeper slope and a smaller total amplitude of the generated terrain. */
NOISE_DATATYPE m_HeightAmplification;
NOISE_DATATYPE m_MidPoint; // Where the vertical "center" of the noise should be
/** Where the vertical "center" of the noise should be, as block height. */
NOISE_DATATYPE m_MidPoint;
// Frequency of the 3D noise's first octave:
NOISE_DATATYPE m_FrequencyX;
NOISE_DATATYPE m_FrequencyY;
NOISE_DATATYPE m_FrequencyZ;
// Frequency of the base terrain noise:
NOISE_DATATYPE m_BaseFrequencyX;
NOISE_DATATYPE m_BaseFrequencyZ;
// Frequency of the choice noise:
NOISE_DATATYPE m_ChoiceFrequencyX;
NOISE_DATATYPE m_ChoiceFrequencyY;
NOISE_DATATYPE m_ChoiceFrequencyZ;
// Threshold for when the values are considered air:
NOISE_DATATYPE m_AirThreshold;
// Cache for the last calculated chunk (reused between heightmap and composition queries):
int m_LastChunkX;
int m_LastChunkZ;
NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // x + 17 * z + 17 * 17 * y
/// Generates the 3D noise array used for terrain generation, unless the LastChunk coords are equal to coords given
/** Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords are equal to coords given */
void GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ);
// cTerrainHeightGen overrides:
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); }
// cTerrainCompositionGen overrides:
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override;
virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); }
} ;
class cBiomalNoise3DComposable :
public cTerrainHeightGen,
public cTerrainCompositionGen
{
public:
cBiomalNoise3DComposable(int a_Seed, cBiomeGenPtr a_BiomeGen);
void Initialize(cIniFile & a_IniFile);
protected:
/** Number of columns around the pixel to query for biomes for averaging. */
static const int AVERAGING_SIZE = 5;
/** Type used for a single parameter across the entire (downscaled) chunk. */
typedef NOISE_DATATYPE ChunkParam[5 * 5];
/** The noise that is used to choose between density noise A and B. */
cPerlinNoise m_ChoiceNoise;
/** Density 3D noise, variant A. */
cPerlinNoise m_DensityNoiseA;
/** Density 3D noise, variant B. */
cPerlinNoise m_DensityNoiseB;
/** Heightmap-like noise used to provide variance for low-amplitude biomes. */
cPerlinNoise m_BaseNoise;
/** The underlying biome generator. */
cBiomeGenPtr m_BiomeGen;
/** Block height of the sealevel, used for composing the terrain. */
int m_SeaLevel;
// Frequency of the 3D noise's first octave:
NOISE_DATATYPE m_FrequencyX;
NOISE_DATATYPE m_FrequencyY;
NOISE_DATATYPE m_FrequencyZ;
// Frequency of the base terrain noise:
NOISE_DATATYPE m_BaseFrequencyX;
NOISE_DATATYPE m_BaseFrequencyZ;
// Frequency of the choice noise:
NOISE_DATATYPE m_ChoiceFrequencyX;
NOISE_DATATYPE m_ChoiceFrequencyY;
NOISE_DATATYPE m_ChoiceFrequencyZ;
// Threshold for when the values are considered air:
NOISE_DATATYPE m_AirThreshold;
// Cache for the last calculated chunk (reused between heightmap and composition queries):
int m_LastChunkX;
int m_LastChunkZ;
NOISE_DATATYPE m_NoiseArray[17 * 17 * 257]; // x + 17 * z + 17 * 17 * y
/** Weights for summing up neighboring biomes. */
NOISE_DATATYPE m_Weight[AVERAGING_SIZE * 2 + 1][AVERAGING_SIZE * 2 + 1];
/** The sum of m_Weight[]. */
NOISE_DATATYPE m_WeightSum;
/** Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords are equal to coords given */
void GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ);
/** Calculates the biome-related parameters for the chunk. */
void CalcBiomeParamArrays(int a_ChunkX, int a_ChunkZ, ChunkParam & a_HeightAmp, ChunkParam & a_MidPoint);
/** Returns the parameters for the specified biome. */
void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE & a_HeightAmp, NOISE_DATATYPE & a_MidPoint);
// cTerrainHeightGen overrides:
virtual void GenHeightMap(int a_ChunkX, int a_ChunkZ, cChunkDef::HeightMap & a_HeightMap) override;
virtual void InitializeHeightGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); }
// cTerrainCompositionGen overrides:
virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override;
virtual void InitializeCompoGen(cIniFile & a_IniFile) override { Initialize(a_IniFile); }
} ;

1351
src/Generating/ProtIntGen.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -633,6 +633,22 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallbac
bool cRoot::DoWithPlayerByUUID(const AString & a_PlayerUUID, cPlayerListCallback & a_Callback)
{
for (WorldMap::iterator itr = m_WorldsByName.begin(); itr != m_WorldsByName.end();itr++)
{
if (itr->second->DoWithPlayerByUUID(a_PlayerUUID, a_Callback))
{
return true;
}
}
return false;
}
AString cRoot::GetProtocolVersionTextFromInt(int a_ProtocolVersion)
{
return cProtocolRecognizer::GetVersionTextFromInt(a_ProtocolVersion);

View File

@ -126,6 +126,9 @@ public:
/// Finds a player from a partial or complete player name and calls the callback - case-insensitive
bool FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
/** Finds the player over his uuid and calls the callback */
bool DoWithPlayerByUUID(const AString & a_PlayerUUID, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
// tolua_begin
/// Sends a chat message to all connected clients (in all worlds)

View File

@ -2732,6 +2732,23 @@ bool cWorld::FindAndDoWithPlayer(const AString & a_PlayerNameHint, cPlayerListCa
bool cWorld::DoWithPlayerByUUID(const AString & a_PlayerUUID, cPlayerListCallback & a_Callback)
{
cCSLock Lock(m_CSPlayers);
for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr)
{
if ((*itr)->GetUUID() == a_PlayerUUID)
{
return a_Callback.Item(*itr);
}
}
return false;
}
// TODO: This interface is dangerous!
cPlayer * cWorld::FindClosestPlayer(const Vector3d & a_Pos, float a_SightLimit, bool a_CheckLineOfSight)
{

View File

@ -324,6 +324,9 @@ public:
// TODO: This interface is dangerous - rewrite to DoWithClosestPlayer(pos, sight, action)
cPlayer * FindClosestPlayer(const Vector3d & a_Pos, float a_SightLimit, bool a_CheckLineOfSight = true);
/** Finds the player over his uuid and calls the callback */
bool DoWithPlayerByUUID(const AString & a_PlayerUUID, cPlayerListCallback & a_Callback); // >> EXPORTED IN MANUALBINDINGS <<
void SendPlayerList(cPlayer * a_DestPlayer); // Sends playerlist to the player
/** Adds the entity into its appropriate chunk; takes ownership of the entity ptr.