Merge branch 'master' into SslWebAdmin
This commit is contained in:
commit
28815252e6
41
COMPILING.md
41
COMPILING.md
@ -45,7 +45,30 @@ It is possible to use an external profiler to learn more about how the code perf
|
||||
|
||||
There's a script file, `MCServer/profile_run.cmd` that encapsulates most of the profiling work, have a look at the comments at the top of that script for details on how to get it to work. You'll need to change to a profiled configuration (both debug and release can be profiled).
|
||||
|
||||
## Linux, MacOS, FreeBSD etc. ##
|
||||
## OSX ##
|
||||
Install git from its [website](http://git-scm.com) or homebrew: `brew install git`.
|
||||
|
||||
Install Xcode (commandline tools are recommended) from the App Store or https://developer.apple.com/downloads.
|
||||
|
||||
Install CMake from its [website](http://cmake.org) or homebrew: `brew install cmake`.
|
||||
|
||||
### Getting the sources ###
|
||||
```
|
||||
mkdir MCServer
|
||||
cd MCServer
|
||||
git clone https://github.com/mc-server/MCServer.git .
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
### Building ###
|
||||
|
||||
Follow the instructions at [CMake on Unix-based platforms](#cmake-on-unix-based-platforms), using Xcode as cmake's generator. If no generator is specified, CMake will use the Makefile generator, in which case you must build with the `make` command.
|
||||
|
||||
After doing so, run the command `xcodebuild lib/polarssl/POLARSSL.xcodeproj` in the build directory, in order to build polarssl, a library that is required by MCServer. Lastly, run the command `xcodebuild` to build MCServer. Optionally, you may open the project files for polarssl and then MCServer in Xcode and build there.
|
||||
|
||||
|
||||
## Linux, FreeBSD etc. ##
|
||||
|
||||
Install git, cmake and gcc or clang, using your platform's package manager:
|
||||
```
|
||||
@ -61,6 +84,14 @@ git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
### Building ###
|
||||
|
||||
Follow the instructions at [CMake on Unix-based platforms](#cmake-on-unix-based-platforms).
|
||||
|
||||
After doing so, run the command `make` in the build directory, and MCServer will build.
|
||||
|
||||
## CMake on Unix-based platforms ###
|
||||
|
||||
### Release Mode ###
|
||||
|
||||
Release mode is preferred for almost all cases, it has much better speed and less console spam. However, if you are developing MCServer actively, debug mode might be better.
|
||||
@ -69,8 +100,10 @@ Assuming you are in the MCServer folder created in the initial setup step, you n
|
||||
```
|
||||
mkdir Release
|
||||
cd Release
|
||||
cmake -DCMAKE_BUILD_TYPE=RELEASE .. && make
|
||||
cmake -DCMAKE_BUILD_TYPE=RELEASE ..
|
||||
```
|
||||
NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive.
|
||||
|
||||
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer`.
|
||||
|
||||
### Debug Mode ###
|
||||
@ -81,8 +114,10 @@ Assuming you are in the MCServer folder created in the Getting the sources step,
|
||||
```
|
||||
mkdir Debug
|
||||
cd Debug
|
||||
cmake -DCMAKE_BUILD_TYPE=DEBUG .. && make
|
||||
cmake -DCMAKE_BUILD_TYPE=DEBUG ..
|
||||
```
|
||||
NOTE: CMake can generate project files for many different programs, such as Xcode, eclipse, and ninja. To use a different generator, first type `cmake --help`, and at the end, cmake will output the different generators that are available. To specify one, add `-G` followed by the name of the generator, in the `cmake` command. Note that the name is case-sensitive.
|
||||
|
||||
The executable will be built in the `MCServer/MCServer` folder and will be named `MCServer_debug`.
|
||||
|
||||
### 32 Bit Mode switch ###
|
||||
|
@ -2,23 +2,33 @@ return
|
||||
{
|
||||
HOOK_DISCONNECT =
|
||||
{
|
||||
CalledWhen = "A player has explicitly disconnected.",
|
||||
CalledWhen = [[
|
||||
A client has disconnected, either by explicitly sending the disconnect packet (in older protocols) or
|
||||
their connection was terminated
|
||||
]],
|
||||
DefaultFnName = "OnDisconnect", -- also used as pagename
|
||||
Desc = [[
|
||||
This hook is called when a client is about to be disconnected from the server, for whatever reason.
|
||||
|
||||
<p><b>Note that this hook will be removed after <1.7 protocol support is removed, as it was originally a hook for
|
||||
the client sending the server a disconnect packet, which no longer happens.</b></p>
|
||||
This hook is called when a client has disconnected from the server, for whatever reason. It is also
|
||||
called when the client sends the Disconnect packet (only in pre-1.7 protocols). This hook is not called
|
||||
for server ping connections.</p>
|
||||
<p>
|
||||
Note that the hook is called even for connections to players who failed to auth. In such a case there's
|
||||
no {{cPlayer}} object associated with the client.</p>
|
||||
<p>
|
||||
See also the {{OnHandshake|HOOK_HANDSHAKE}} hook which is called when the client connects (and presents
|
||||
a handshake message, so that they are not just status-pinging). If you need to store a per-player
|
||||
object, use the {{OnPlayerJoined|HOOK_PLAYER_JOINED}} and {{OnPlayerDestroyed|HOOK_PLAYER_DESTROYED}}
|
||||
hooks instead, those are guaranteed to have the {{cPlayer}} object associated.
|
||||
]],
|
||||
Params =
|
||||
{
|
||||
{ Name = "Player", Type = "{{cPlayer}}", Notes = "The player who has disconnected" },
|
||||
{ Name = "Client", Type = "{{cClientHandle}}", Notes = "The client who has disconnected" },
|
||||
{ Name = "Reason", Type = "string", Notes = "The reason that the client has sent in the disconnect packet" },
|
||||
},
|
||||
Returns = [[
|
||||
If the function returns false or no value, MCServer calls other plugins' callbacks for this event.
|
||||
If the function returns true, no other plugins are called for this event. In either case,
|
||||
the player is disconnected.
|
||||
the client is disconnected.
|
||||
]],
|
||||
}, -- HOOK_DISCONNECT
|
||||
}
|
||||
|
@ -27,10 +27,14 @@ local function LoadAPIFiles(a_Folder, a_DstTable)
|
||||
-- We only want .lua files from the folder:
|
||||
if (cFile:IsFile(FileName) and fnam:match(".*%.lua$")) then
|
||||
local TablesFn, Err = loadfile(FileName);
|
||||
if (TablesFn == nil) then
|
||||
if (type(TablesFn) ~= "function") then
|
||||
LOGWARNING("Cannot load API descriptions from " .. FileName .. ", Lua error '" .. Err .. "'.");
|
||||
else
|
||||
local Tables = TablesFn();
|
||||
if (type(Tables) ~= "table") then
|
||||
LOGWARNING("Cannot load API descriptions from " .. FileName .. ", returned object is not a table (" .. type(Tables) .. ").");
|
||||
break
|
||||
end
|
||||
for k, cls in pairs(Tables) do
|
||||
a_DstTable[k] = cls;
|
||||
end
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 013a32a7fb3c8a6cfe0aef892d4c7394d4e1be59
|
||||
Subproject commit 5c8557d4fdfa580c100510cde07a1a778ea2e244
|
@ -221,7 +221,7 @@ typedef unsigned char Byte;
|
||||
#if (defined(_MSC_VER) && (_MSC_VER < 1600))
|
||||
// MSVC before 2010 doesn't have std::shared_ptr, but has std::tr1::shared_ptr, defined in <memory> included earlier
|
||||
#define SharedPtr std::tr1::shared_ptr
|
||||
#elif (__cplusplus >= 201103L)
|
||||
#elif (defined(_MSC_VER) || (__cplusplus >= 201103L))
|
||||
// C++11 has std::shared_ptr in <memory>, included earlier
|
||||
#define SharedPtr std::shared_ptr
|
||||
#else
|
||||
|
@ -243,7 +243,7 @@ int cIniFile::FindKey(const AString & a_KeyName) const
|
||||
{
|
||||
if (CheckCase(names[keyID]) == CaseKeyName)
|
||||
{
|
||||
return keyID;
|
||||
return (int)keyID;
|
||||
}
|
||||
}
|
||||
return noID;
|
||||
@ -279,7 +279,7 @@ int cIniFile::AddKeyName(const AString & keyname)
|
||||
{
|
||||
names.resize(names.size() + 1, keyname);
|
||||
keys.resize(keys.size() + 1);
|
||||
return names.size() - 1;
|
||||
return (int)names.size() - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -683,7 +683,7 @@ int cIniFile::GetNumKeyComments(const int keyID) const
|
||||
{
|
||||
if (keyID < (int)keys.size())
|
||||
{
|
||||
return keys[keyID].comments.size();
|
||||
return (int)keys[keyID].comments.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ bool cLuaChunkStay::AddChunks(int a_ChunkCoordTableStackPos)
|
||||
|
||||
// Add each set of coords:
|
||||
int NumChunks = luaL_getn(L, a_ChunkCoordTableStackPos);
|
||||
m_Chunks.reserve(NumChunks);
|
||||
m_Chunks.reserve((size_t)NumChunks);
|
||||
for (int idx = 1; idx <= NumChunks; idx++)
|
||||
{
|
||||
// Push the idx-th element of the array onto stack top, check that it's a table:
|
||||
|
@ -4,12 +4,12 @@
|
||||
#include <time.h>
|
||||
// tolua_begin
|
||||
|
||||
unsigned int GetTime()
|
||||
inline unsigned int GetTime()
|
||||
{
|
||||
return (unsigned int)time(0);
|
||||
}
|
||||
|
||||
std::string GetChar( std::string & a_Str, unsigned int a_Idx )
|
||||
inline std::string GetChar( std::string & a_Str, unsigned int a_Idx )
|
||||
{
|
||||
return std::string(1, a_Str[ a_Idx ]);
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
/****************************
|
||||
* Better error reporting for Lua
|
||||
**/
|
||||
int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaError)
|
||||
static int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaError)
|
||||
{
|
||||
// Retrieve current function name
|
||||
lua_Debug entry;
|
||||
@ -57,7 +57,7 @@ int tolua_do_error(lua_State* L, const char * a_pMsg, tolua_Error * a_pToLuaErro
|
||||
|
||||
|
||||
|
||||
int lua_do_error(lua_State* L, const char * a_pFormat, ...)
|
||||
static int lua_do_error(lua_State* L, const char * a_pFormat, ...)
|
||||
{
|
||||
// Retrieve current function name
|
||||
lua_Debug entry;
|
||||
@ -235,7 +235,7 @@ static int tolua_Base64Decode(lua_State * tolua_S)
|
||||
|
||||
|
||||
|
||||
cPluginLua * GetLuaPlugin(lua_State * L)
|
||||
static cPluginLua * GetLuaPlugin(lua_State * L)
|
||||
{
|
||||
// Get the plugin identification out of LuaState:
|
||||
lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME);
|
||||
@ -1776,20 +1776,20 @@ static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
|
||||
|
||||
|
||||
|
||||
static int tolua_cPlayer_GetGroups(lua_State* tolua_S)
|
||||
static int tolua_cPlayer_GetGroups(lua_State * tolua_S)
|
||||
{
|
||||
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL);
|
||||
cPlayer * self = (cPlayer *)tolua_tousertype(tolua_S, 1, NULL);
|
||||
|
||||
const cPlayer::GroupList & AllGroups = self->GetGroups();
|
||||
|
||||
lua_createtable(tolua_S, AllGroups.size(), 0);
|
||||
lua_createtable(tolua_S, (int)AllGroups.size(), 0);
|
||||
int newTable = lua_gettop(tolua_S);
|
||||
int index = 1;
|
||||
cPlayer::GroupList::const_iterator iter = AllGroups.begin();
|
||||
while(iter != AllGroups.end())
|
||||
while (iter != AllGroups.end())
|
||||
{
|
||||
const cGroup* Group = *iter;
|
||||
tolua_pushusertype( tolua_S, (void*)Group, "const cGroup" );
|
||||
const cGroup * Group = *iter;
|
||||
tolua_pushusertype(tolua_S, (void *)Group, "const cGroup");
|
||||
lua_rawseti(tolua_S, newTable, index);
|
||||
++iter;
|
||||
++index;
|
||||
@ -1801,20 +1801,20 @@ static int tolua_cPlayer_GetGroups(lua_State* tolua_S)
|
||||
|
||||
|
||||
|
||||
static int tolua_cPlayer_GetResolvedPermissions(lua_State* tolua_S)
|
||||
static int tolua_cPlayer_GetResolvedPermissions(lua_State * tolua_S)
|
||||
{
|
||||
cPlayer* self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL);
|
||||
cPlayer * self = (cPlayer*) tolua_tousertype(tolua_S, 1, NULL);
|
||||
|
||||
cPlayer::StringList AllPermissions = self->GetResolvedPermissions();
|
||||
|
||||
lua_createtable(tolua_S, AllPermissions.size(), 0);
|
||||
lua_createtable(tolua_S, (int)AllPermissions.size(), 0);
|
||||
int newTable = lua_gettop(tolua_S);
|
||||
int index = 1;
|
||||
cPlayer::StringList::iterator iter = AllPermissions.begin();
|
||||
while(iter != AllPermissions.end())
|
||||
while (iter != AllPermissions.end())
|
||||
{
|
||||
std::string& Permission = *iter;
|
||||
tolua_pushstring( tolua_S, Permission.c_str() );
|
||||
std::string & Permission = *iter;
|
||||
lua_pushlstring(tolua_S, Permission.c_str(), Permission.length());
|
||||
lua_rawseti(tolua_S, newTable, index);
|
||||
++iter;
|
||||
++index;
|
||||
@ -2076,18 +2076,18 @@ static int tolua_get_HTTPRequest_FormData(lua_State* tolua_S)
|
||||
|
||||
static int tolua_cWebAdmin_GetPlugins(lua_State * tolua_S)
|
||||
{
|
||||
cWebAdmin* self = (cWebAdmin*) tolua_tousertype(tolua_S, 1, NULL);
|
||||
cWebAdmin * self = (cWebAdmin *)tolua_tousertype(tolua_S, 1, NULL);
|
||||
|
||||
const cWebAdmin::PluginList & AllPlugins = self->GetPlugins();
|
||||
|
||||
lua_createtable(tolua_S, AllPlugins.size(), 0);
|
||||
lua_createtable(tolua_S, (int)AllPlugins.size(), 0);
|
||||
int newTable = lua_gettop(tolua_S);
|
||||
int index = 1;
|
||||
cWebAdmin::PluginList::const_iterator iter = AllPlugins.begin();
|
||||
while(iter != AllPlugins.end())
|
||||
while (iter != AllPlugins.end())
|
||||
{
|
||||
const cWebPlugin* Plugin = *iter;
|
||||
tolua_pushusertype( tolua_S, (void*)Plugin, "const cWebPlugin" );
|
||||
const cWebPlugin * Plugin = *iter;
|
||||
tolua_pushusertype(tolua_S, (void *)Plugin, "const cWebPlugin");
|
||||
lua_rawseti(tolua_S, newTable, index);
|
||||
++iter;
|
||||
++index;
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) = 0;
|
||||
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) = 0;
|
||||
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) = 0;
|
||||
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) = 0;
|
||||
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) = 0;
|
||||
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) = 0;
|
||||
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
|
||||
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) = 0;
|
||||
|
@ -400,14 +400,14 @@ bool cPluginLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGri
|
||||
|
||||
|
||||
|
||||
bool cPluginLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason)
|
||||
bool cPluginLua::OnDisconnect(cClientHandle & a_Client, const AString & a_Reason)
|
||||
{
|
||||
cCSLock Lock(m_CriticalSection);
|
||||
bool res = false;
|
||||
cLuaRefs & Refs = m_HookMap[cPluginManager::HOOK_DISCONNECT];
|
||||
for (cLuaRefs::iterator itr = Refs.begin(), end = Refs.end(); itr != end; ++itr)
|
||||
{
|
||||
m_LuaState.Call((int)(**itr), a_Player, a_Reason, cLuaState::Return, res);
|
||||
m_LuaState.Call((int)(**itr), &a_Client, a_Reason, cLuaState::Return, res);
|
||||
if (res)
|
||||
{
|
||||
return true;
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
virtual bool OnChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override;
|
||||
virtual bool OnCollectingPickup (cPlayer * a_Player, cPickup * a_Pickup) override;
|
||||
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
|
||||
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) override;
|
||||
virtual bool OnDisconnect (cClientHandle & a_Client, const AString & a_Reason) override;
|
||||
virtual bool OnExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split) override;
|
||||
virtual bool OnExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
|
||||
virtual bool OnExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData) override;
|
||||
|
@ -143,13 +143,14 @@ void cPluginManager::ReloadPluginsNow(cIniFile & a_SettingsIni)
|
||||
}
|
||||
}
|
||||
|
||||
if (GetNumPlugins() == 0)
|
||||
size_t NumLoadedPlugins = GetNumPlugins();
|
||||
if (NumLoadedPlugins == 0)
|
||||
{
|
||||
LOG("-- No Plugins Loaded --");
|
||||
}
|
||||
else if (GetNumPlugins() > 1)
|
||||
else if (NumLoadedPlugins > 1)
|
||||
{
|
||||
LOG("-- Loaded %i Plugins --", GetNumPlugins());
|
||||
LOG("-- Loaded %i Plugins --", (int)NumLoadedPlugins);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -442,7 +443,7 @@ bool cPluginManager::CallHookCraftingNoRecipe(const cPlayer * a_Player, const cC
|
||||
|
||||
|
||||
|
||||
bool cPluginManager::CallHookDisconnect(cPlayer * a_Player, const AString & a_Reason)
|
||||
bool cPluginManager::CallHookDisconnect(cClientHandle & a_Client, const AString & a_Reason)
|
||||
{
|
||||
HookMap::iterator Plugins = m_Hooks.find(HOOK_DISCONNECT);
|
||||
if (Plugins == m_Hooks.end())
|
||||
@ -451,7 +452,7 @@ bool cPluginManager::CallHookDisconnect(cPlayer * a_Player, const AString & a_Re
|
||||
}
|
||||
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
|
||||
{
|
||||
if ((*itr)->OnDisconnect(a_Player, a_Reason))
|
||||
if ((*itr)->OnDisconnect(a_Client, a_Reason))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -1869,7 +1870,7 @@ void cPluginManager::AddHook(cPlugin * a_Plugin, int a_Hook)
|
||||
|
||||
|
||||
|
||||
unsigned int cPluginManager::GetNumPlugins() const
|
||||
size_t cPluginManager::GetNumPlugins() const
|
||||
{
|
||||
return m_Plugins.size();
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ public: // tolua_export
|
||||
/** Adds the plugin to the list of plugins called for the specified hook type. Handles multiple adds as a single add */
|
||||
void AddHook(cPlugin * a_Plugin, int a_HookType);
|
||||
|
||||
unsigned int GetNumPlugins() const; // tolua_export
|
||||
size_t GetNumPlugins() const; // tolua_export
|
||||
|
||||
// Calls for individual hooks. Each returns false if the action is to continue or true if the plugin wants to abort
|
||||
bool CallHookBlockSpread (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, eSpreadSource a_Source);
|
||||
@ -172,7 +172,7 @@ public: // tolua_export
|
||||
bool CallHookChunkUnloading (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
|
||||
bool CallHookCollectingPickup (cPlayer * a_Player, cPickup & a_Pickup);
|
||||
bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
|
||||
bool CallHookDisconnect (cPlayer * a_Player, const AString & a_Reason);
|
||||
bool CallHookDisconnect (cClientHandle & a_Client, const AString & a_Reason);
|
||||
bool CallHookExecuteCommand (cPlayer * a_Player, const AStringVector & a_Split); // If a_Player == NULL, it is a console cmd
|
||||
bool CallHookExploded (cWorld & a_World, double a_ExplosionSize, bool a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
|
||||
bool CallHookExploding (cWorld & a_World, double & a_ExplosionSize, bool & a_CanCauseFire, double a_X, double a_Y, double a_Z, eExplosionSource a_Source, void * a_SourceData);
|
||||
|
@ -707,11 +707,11 @@ void cBlockArea::Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_R
|
||||
|
||||
if (IsDummyMetas)
|
||||
{
|
||||
MergeByStrategy<true>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
|
||||
MergeByStrategy<false>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
|
||||
}
|
||||
else
|
||||
{
|
||||
MergeByStrategy<false>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
|
||||
MergeByStrategy<true>(a_Src, a_RelX, a_RelY, a_RelZ, a_Strategy, SrcMetas, DstMetas);
|
||||
}
|
||||
}
|
||||
|
||||
@ -738,31 +738,31 @@ void cBlockArea::Fill(int a_DataTypes, BLOCKTYPE a_BlockType, NIBBLETYPE a_Block
|
||||
a_DataTypes = a_DataTypes & GetDataTypes();
|
||||
}
|
||||
|
||||
int BlockCount = GetBlockCount();
|
||||
size_t BlockCount = GetBlockCount();
|
||||
if ((a_DataTypes & baTypes) != 0)
|
||||
{
|
||||
for (int i = 0; i < BlockCount; i++)
|
||||
for (size_t i = 0; i < BlockCount; i++)
|
||||
{
|
||||
m_BlockTypes[i] = a_BlockType;
|
||||
}
|
||||
}
|
||||
if ((a_DataTypes & baMetas) != 0)
|
||||
{
|
||||
for (int i = 0; i < BlockCount; i++)
|
||||
for (size_t i = 0; i < BlockCount; i++)
|
||||
{
|
||||
m_BlockMetas[i] = a_BlockMeta;
|
||||
}
|
||||
}
|
||||
if ((a_DataTypes & baLight) != 0)
|
||||
{
|
||||
for (int i = 0; i < BlockCount; i++)
|
||||
for (size_t i = 0; i < BlockCount; i++)
|
||||
{
|
||||
m_BlockLight[i] = a_BlockLight;
|
||||
}
|
||||
}
|
||||
if ((a_DataTypes & baSkyLight) != 0)
|
||||
{
|
||||
for (int i = 0; i < BlockCount; i++)
|
||||
for (size_t i = 0; i < BlockCount; i++)
|
||||
{
|
||||
m_BlockSkyLight[i] = a_BlockSkyLight;
|
||||
}
|
||||
|
@ -110,10 +110,13 @@ void cBlockInfo::Initialize(void)
|
||||
// Transparent blocks
|
||||
ms_Info[E_BLOCK_ACTIVATOR_RAIL ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_AIR ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_ANVIL ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_BIG_FLOWER ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_CAKE ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_CARROTS ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_CHEST ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_COBBLESTONE_WALL ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_COBWEB ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_CROPS ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_DANDELION ].m_Transparent = true;
|
||||
@ -126,6 +129,7 @@ void cBlockInfo::Initialize(void)
|
||||
ms_Info[E_BLOCK_FLOWER_POT ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_GLASS ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_GLASS_PANE ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_HEAD ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_ICE ].m_Transparent = true;
|
||||
ms_Info[E_BLOCK_IRON_DOOR ].m_Transparent = true;
|
||||
@ -196,12 +200,14 @@ void cBlockInfo::Initialize(void)
|
||||
ms_Info[E_BLOCK_BED ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_BIG_FLOWER ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_CAKE ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_COBWEB ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_CROPS ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_DANDELION ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_DEAD_BUSH ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_FIRE ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_FLOWER ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_HEAD ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_INACTIVE_COMPARATOR ].m_PistonBreakable = true;
|
||||
ms_Info[E_BLOCK_IRON_DOOR ].m_PistonBreakable = true;
|
||||
@ -243,6 +249,7 @@ void cBlockInfo::Initialize(void)
|
||||
ms_Info[E_BLOCK_CACTUS ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_CHEST ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_CROPS ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_COBBLESTONE_WALL ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_DANDELION ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_FIRE ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_FLOWER ].m_IsSnowable = false;
|
||||
@ -276,6 +283,7 @@ void cBlockInfo::Initialize(void)
|
||||
ms_Info[E_BLOCK_POWERED_RAIL ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_DETECTOR_RAIL ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_COBWEB ].m_IsSnowable = false;
|
||||
ms_Info[E_BLOCK_HEAD ].m_IsSnowable = false;
|
||||
|
||||
|
||||
// Blocks that don't drop without a special tool:
|
||||
@ -283,6 +291,7 @@ void cBlockInfo::Initialize(void)
|
||||
ms_Info[E_BLOCK_CAULDRON ].m_RequiresSpecialTool = true;
|
||||
ms_Info[E_BLOCK_COAL_ORE ].m_RequiresSpecialTool = true;
|
||||
ms_Info[E_BLOCK_COBBLESTONE ].m_RequiresSpecialTool = true;
|
||||
ms_Info[E_BLOCK_COBBLESTONE_WALL ].m_RequiresSpecialTool = true;
|
||||
ms_Info[E_BLOCK_COBBLESTONE_STAIRS ].m_RequiresSpecialTool = true;
|
||||
ms_Info[E_BLOCK_COBWEB ].m_RequiresSpecialTool = true;
|
||||
ms_Info[E_BLOCK_DIAMOND_BLOCK ].m_RequiresSpecialTool = true;
|
||||
@ -325,6 +334,7 @@ void cBlockInfo::Initialize(void)
|
||||
ms_Info[E_BLOCK_AIR ].m_IsSolid = false;
|
||||
ms_Info[E_BLOCK_BIG_FLOWER ].m_IsSolid = false;
|
||||
ms_Info[E_BLOCK_BROWN_MUSHROOM ].m_IsSolid = false;
|
||||
ms_Info[E_BLOCK_CAKE ].m_IsSolid = false;
|
||||
ms_Info[E_BLOCK_CARROTS ].m_IsSolid = false;
|
||||
ms_Info[E_BLOCK_COBWEB ].m_IsSolid = false;
|
||||
ms_Info[E_BLOCK_CROPS ].m_IsSolid = false;
|
||||
|
@ -23,6 +23,13 @@ public:
|
||||
{
|
||||
a_Pickups.push_back(cItem(E_BLOCK_ANVIL, 1, a_BlockMeta >> 2));
|
||||
}
|
||||
|
||||
|
||||
virtual void OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
|
||||
{
|
||||
cWindow * Window = new cAnvilWindow(a_BlockX, a_BlockY, a_BlockZ);
|
||||
a_Player->OpenWindow(Window);
|
||||
}
|
||||
|
||||
|
||||
virtual bool GetPlacementBlockTypeMeta(
|
||||
|
@ -39,6 +39,13 @@ public:
|
||||
}
|
||||
|
||||
|
||||
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Bed specific helper functions
|
||||
static NIBBLETYPE RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
|
@ -35,8 +35,10 @@ public:
|
||||
// Grass becomes dirt if there is something on top of it:
|
||||
if (a_RelY < cChunkDef::Height - 1)
|
||||
{
|
||||
BLOCKTYPE Above = a_Chunk.GetBlock(a_RelX, a_RelY + 1, a_RelZ);
|
||||
if ((!cBlockInfo::IsTransparent(Above) && !cBlockInfo::IsOneHitDig(Above)) || IsBlockWater(Above))
|
||||
BLOCKTYPE Above;
|
||||
NIBBLETYPE AboveMeta;
|
||||
a_Chunk.GetBlockTypeMeta(a_RelX, a_RelY + 1, a_RelZ, Above, AboveMeta);
|
||||
if (!cBlockInfo::GetHandler(Above)->CanDirtGrowGrass(AboveMeta))
|
||||
{
|
||||
a_Chunk.FastSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_DIRT, E_META_DIRT_NORMAL);
|
||||
return;
|
||||
@ -77,7 +79,7 @@ public:
|
||||
BLOCKTYPE AboveDest;
|
||||
NIBBLETYPE AboveMeta;
|
||||
Chunk->GetBlockTypeMeta(BlockX, BlockY + 1, BlockZ, AboveDest, AboveMeta);
|
||||
if ((cBlockInfo::IsOneHitDig(AboveDest) || cBlockInfo::IsTransparent(AboveDest)) && !IsBlockWater(AboveDest))
|
||||
if (cBlockInfo::GetHandler(AboveDest)->CanDirtGrowGrass(AboveMeta))
|
||||
{
|
||||
if (!cRoot::Get()->GetPluginManager()->CallHookBlockSpread((cWorld*) &a_WorldInterface, BlockX * cChunkDef::Width, BlockY, BlockZ * cChunkDef::Width, ssGrassSpread))
|
||||
{
|
||||
|
@ -52,9 +52,9 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
int NumBlocks = Area.GetBlockCount();
|
||||
size_t NumBlocks = Area.GetBlockCount();
|
||||
BLOCKTYPE * BlockTypes = Area.GetBlockTypes();
|
||||
for (int i = 0; i < NumBlocks; i++)
|
||||
for (size_t i = 0; i < NumBlocks; i++)
|
||||
{
|
||||
if (
|
||||
(BlockTypes[i] == E_BLOCK_WATER) ||
|
||||
|
@ -68,7 +68,6 @@ public:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
for (int newY = Y + 1; newY < cChunkDef::Height; newY++)
|
||||
{
|
||||
@ -84,7 +83,7 @@ public:
|
||||
// This is because the frame is a solid obsidian pillar
|
||||
if ((MaxY != 0) && (newY == Y + 1))
|
||||
{
|
||||
return EvaluatePortalBorder(X, newY, Z, MaxY, a_ChunkInterface);
|
||||
return EvaluatePortalBorder(X, newY, Z, MaxY, a_ChunkInterface) ? -1 /* -1 = found a frame */ : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -99,18 +98,18 @@ public:
|
||||
}
|
||||
|
||||
/// Evaluates if coords have a valid border on top, based on MaxY
|
||||
int EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
|
||||
bool EvaluatePortalBorder(int X, int FoundObsidianY, int Z, int MaxY, cChunkInterface & a_ChunkInterface)
|
||||
{
|
||||
for (int checkBorder = FoundObsidianY + 1; checkBorder <= MaxY - 1; checkBorder++) // FoundObsidianY + 1: FoundObsidianY has already been checked in FindObsidianCeiling; MaxY - 1: portal doesn't need corners
|
||||
{
|
||||
if (a_ChunkInterface.GetBlock(X, checkBorder, Z) != E_BLOCK_OBSIDIAN)
|
||||
{
|
||||
// Base obsidian, base + 1 obsidian, base + x NOT obsidian -> not complete portal
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Everything was obsidian, found a border!
|
||||
return -1; // Return -1 for a frame border
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Finds entire frame in any direction with the coordinates of a base block and fills hole with nether portal (START HERE)
|
||||
@ -169,7 +168,7 @@ public:
|
||||
{
|
||||
return false; // Not valid slice, no portal can be formed
|
||||
}
|
||||
} XZP = X1 - 1; // Set boundary of frame interior, note that for some reason, the loop of X and the loop of Z go to different numbers, hence -1 here and -2 there
|
||||
} XZP = X1 - 1; // Set boundary of frame interior
|
||||
for (; ((a_ChunkInterface.GetBlock(X2, Y, Z) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X2, Y + 1, Z) == E_BLOCK_OBSIDIAN)); X2--) // Go the other direction (XM)
|
||||
{
|
||||
int Value = FindObsidianCeiling(X2, Y, Z, a_ChunkInterface, MaxY);
|
||||
@ -199,13 +198,13 @@ public:
|
||||
if ((Value == -1) || (ValueTwo == -1))
|
||||
{
|
||||
FoundFrameZP = true;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
else if ((Value != MaxY) && (ValueTwo != MaxY))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} XZP = Z1 - 2;
|
||||
} XZP = Z1 - 1;
|
||||
for (; ((a_ChunkInterface.GetBlock(X, Y, Z2) == E_BLOCK_OBSIDIAN) || (a_ChunkInterface.GetBlock(X, Y + 1, Z2) == E_BLOCK_OBSIDIAN)); Z2--)
|
||||
{
|
||||
int Value = FindObsidianCeiling(X, Y, Z2, a_ChunkInterface, MaxY);
|
||||
@ -213,13 +212,13 @@ public:
|
||||
if ((Value == -1) || (ValueTwo == -1))
|
||||
{
|
||||
FoundFrameZM = true;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
else if ((Value != MaxY) && (ValueTwo != MaxY))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} XZM = Z2 + 2;
|
||||
} XZM = Z2 + 1;
|
||||
return (FoundFrameZP && FoundFrameZM);
|
||||
}
|
||||
};
|
||||
|
@ -49,6 +49,12 @@ public:
|
||||
}
|
||||
super::Check(a_ChunkInterface, a_PluginInterface, a_RelX, a_RelY, a_RelZ, a_Chunk);
|
||||
}
|
||||
|
||||
|
||||
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -400,6 +400,15 @@ bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, in
|
||||
|
||||
|
||||
|
||||
bool cBlockHandler::CanDirtGrowGrass(NIBBLETYPE a_Meta)
|
||||
{
|
||||
return ((cBlockInfo::IsTransparent(m_BlockType)) || (cBlockInfo::IsOneHitDig(m_BlockType)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cBlockHandler::IsUseable()
|
||||
{
|
||||
return false;
|
||||
|
@ -85,6 +85,9 @@ public:
|
||||
|
||||
/// Checks if the block can stay at the specified relative coords in the chunk
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk);
|
||||
|
||||
/** Can the dirt under this block grow to grass? */
|
||||
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta);
|
||||
|
||||
/** Checks if the block can be placed at this point.
|
||||
Default: CanBeAt(...)
|
||||
|
@ -138,14 +138,14 @@ bool HasNearLog(cBlockArea & a_Area, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
// Filter the blocks into a {leaves, log, other (air)} set:
|
||||
BLOCKTYPE * Types = a_Area.GetBlockTypes();
|
||||
for (int i = a_Area.GetBlockCount() - 1; i > 0; i--)
|
||||
for (size_t i = a_Area.GetBlockCount() - 1; i > 0; i--)
|
||||
{
|
||||
switch (Types[i])
|
||||
{
|
||||
case E_BLOCK_NEW_LEAVES:
|
||||
case E_BLOCK_NEW_LOG:
|
||||
case E_BLOCK_LEAVES:
|
||||
case E_BLOCK_LOG:
|
||||
case E_BLOCK_NEW_LEAVES:
|
||||
case E_BLOCK_NEW_LOG:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "BlockHandler.h"
|
||||
#include "../Mobs/Monster.h"
|
||||
|
||||
|
||||
|
||||
@ -38,6 +39,19 @@ public:
|
||||
return; // No pickups
|
||||
}
|
||||
|
||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_PluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ) override
|
||||
{
|
||||
cFastRandom Random;
|
||||
if (Random.NextInt(2000) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int PosX = a_Chunk.GetPosX() * 16 + a_RelX;
|
||||
int PosZ = a_Chunk.GetPosZ() * 16 + a_RelZ;
|
||||
|
||||
a_WorldInterface.SpawnMob(PosX, a_RelY, PosZ, cMonster::mtZombiePigman);
|
||||
}
|
||||
|
||||
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
|
||||
{
|
||||
|
@ -97,6 +97,12 @@ public:
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
return ((a_Meta & 0x8) != 0);
|
||||
}
|
||||
|
||||
|
||||
/// Returns true if the specified blocktype is one of the slabs handled by this handler
|
||||
static bool IsAnySlabType(BLOCKTYPE a_BlockType)
|
||||
|
@ -77,6 +77,11 @@ public:
|
||||
// Reset meta to 0
|
||||
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
|
||||
}
|
||||
|
||||
virtual bool CanDirtGrowGrass(NIBBLETYPE a_Meta) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static NIBBLETYPE RotationToMetaData(double a_Rotation)
|
||||
{
|
||||
|
@ -380,12 +380,12 @@ void cChunk::SetLight(
|
||||
|
||||
{ // Compress blocklight
|
||||
m_BlockLight.clear();
|
||||
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[m_BlockTypes.size()]);
|
||||
m_BlockLight.insert(m_BlockLight.end(), &a_BlockLight[0], &a_BlockLight[m_BlockTypes.size() / 2]);
|
||||
}
|
||||
|
||||
{ // Compress skylight
|
||||
m_BlockSkyLight.clear();
|
||||
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[m_BlockTypes.size()]);
|
||||
m_BlockSkyLight.insert(m_BlockSkyLight.end(), &a_SkyLight[0], &a_SkyLight[m_BlockTypes.size() / 2]);
|
||||
}
|
||||
|
||||
m_IsLightValid = true;
|
||||
@ -749,7 +749,7 @@ void cChunk::ProcessQueuedSetBlocks(void)
|
||||
{
|
||||
if (itr->m_Tick <= CurrTick)
|
||||
{
|
||||
if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to -1 if not specified
|
||||
if (itr->m_PreviousType != E_BLOCK_AIR) // PreviousType defaults to 0 if not specified
|
||||
{
|
||||
if (GetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ) == itr->m_PreviousType)
|
||||
{
|
||||
@ -1638,6 +1638,24 @@ void cChunk::FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockT
|
||||
|
||||
|
||||
|
||||
void cChunk::SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta)
|
||||
{
|
||||
if (GetNibble(m_BlockMeta, a_BlockIdx) == a_Meta)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MarkDirty();
|
||||
SetNibble(m_BlockMeta, a_BlockIdx, a_Meta);
|
||||
Vector3i Coords(IndexToCoordinate(a_BlockIdx));
|
||||
|
||||
m_PendingSendBlocks.push_back(sSetBlock(m_PosX, m_PosZ, Coords.x, Coords.y, Coords.z, GetBlock(a_BlockIdx), a_Meta));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cChunk::SendBlockTo(int a_RelX, int a_RelY, int a_RelZ, cClientHandle * a_Client)
|
||||
{
|
||||
// The coords must be valid, because the upper level already does chunk lookup. No need to check them again.
|
||||
|
@ -320,10 +320,10 @@ public:
|
||||
m_BlockTickZ = a_RelZ;
|
||||
}
|
||||
|
||||
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ); }
|
||||
inline NIBBLETYPE GetMeta(int a_BlockIdx) const {return cChunkDef::GetNibble(m_BlockMeta, a_BlockIdx); }
|
||||
inline void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { cChunkDef::SetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ, a_Meta); }
|
||||
inline void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta) { cChunkDef::SetNibble(m_BlockMeta, a_BlockIdx, a_Meta); }
|
||||
inline NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const { return cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ); }
|
||||
inline NIBBLETYPE GetMeta(int a_BlockIdx) const { return cChunkDef::GetNibble(m_BlockMeta, a_BlockIdx); }
|
||||
inline void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta) { SetMeta(MakeIndex(a_RelX, a_RelY, a_RelZ), a_Meta); }
|
||||
void SetMeta(int a_BlockIdx, NIBBLETYPE a_Meta);
|
||||
|
||||
inline NIBBLETYPE GetBlockLight(int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockLight, a_RelX, a_RelY, a_RelZ); }
|
||||
inline NIBBLETYPE GetSkyLight (int a_RelX, int a_RelY, int a_RelZ) const {return cChunkDef::GetNibble(m_BlockSkyLight, a_RelX, a_RelY, a_RelZ, true); }
|
||||
@ -420,7 +420,6 @@ private:
|
||||
cWorld * m_World;
|
||||
cChunkMap * m_ChunkMap;
|
||||
|
||||
// TODO: Make these pointers and don't allocate what isn't needed
|
||||
COMPRESSED_BLOCKTYPE m_BlockTypes;
|
||||
COMPRESSED_NIBBLETYPE m_BlockMeta;
|
||||
COMPRESSED_NIBBLETYPE m_BlockLight;
|
||||
|
@ -1248,8 +1248,6 @@ void cChunkMap::SetBlockMeta(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYP
|
||||
if ((Chunk != NULL) && Chunk->IsValid())
|
||||
{
|
||||
Chunk->SetMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta);
|
||||
Chunk->MarkDirty();
|
||||
Chunk->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessage
|
||||
{
|
||||
switch (a_ChatPrefix)
|
||||
{
|
||||
case mtCustom: return AString();
|
||||
case mtCustom: return "";
|
||||
case mtFailure: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Rose, cChatColor::White);
|
||||
case mtInformation: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Yellow, cChatColor::White);
|
||||
case mtSuccess: return FormatChatPrefix(ShouldAppendChatPrefixes, "INFO", cChatColor::Green, cChatColor::White);
|
||||
@ -224,7 +224,7 @@ AString cClientHandle::FormatMessageType(bool ShouldAppendChatPrefixes, eMessage
|
||||
}
|
||||
}
|
||||
ASSERT(!"Unhandled chat prefix type!");
|
||||
return AString();
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@ -633,6 +633,10 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
|
||||
// Client <-> Server branding exchange
|
||||
SendPluginMessage("MC|Brand", "MCServer");
|
||||
}
|
||||
else if (a_Channel == "MC|ItemName")
|
||||
{
|
||||
HandleAnvilItemName(a_Message.c_str(), a_Message.size());
|
||||
}
|
||||
else if (a_Channel == "REGISTER")
|
||||
{
|
||||
if (HasPluginChannel(a_Channel))
|
||||
@ -774,6 +778,29 @@ void cClientHandle::HandleCommandBlockMessage(const char * a_Data, size_t a_Leng
|
||||
|
||||
|
||||
|
||||
void cClientHandle::HandleAnvilItemName(const char * a_Data, size_t a_Length)
|
||||
{
|
||||
if (a_Length < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_Player->GetWindow() == NULL) || (m_Player->GetWindow()->GetWindowType() != cWindow::wtAnvil))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AString Name(a_Data, a_Length);
|
||||
if (Name.length() <= 30)
|
||||
{
|
||||
((cAnvilWindow *)m_Player->GetWindow())->SetRepairedItemName(Name, m_Player);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, char a_Status)
|
||||
{
|
||||
LOGD("HandleLeftClick: {%i, %i, %i}; Face: %i; Stat: %i",
|
||||
@ -1510,7 +1537,7 @@ void cClientHandle::HandleDisconnect(const AString & a_Reason)
|
||||
{
|
||||
LOGD("Received d/c packet from %s with reason \"%s\"", m_Username.c_str(), a_Reason.c_str());
|
||||
|
||||
cRoot::Get()->GetPluginManager()->CallHookDisconnect(m_Player, a_Reason);
|
||||
cRoot::Get()->GetPluginManager()->CallHookDisconnect(*this, a_Reason);
|
||||
|
||||
m_HasSentDC = true;
|
||||
Destroy();
|
||||
@ -2690,9 +2717,9 @@ void cClientHandle::SocketClosed(void)
|
||||
|
||||
LOGD("Player %s @ %s disconnected", m_Username.c_str(), m_IPString.c_str());
|
||||
|
||||
if (m_Username != "") // Ignore client pings
|
||||
if (!m_Username.empty()) // Ignore client pings
|
||||
{
|
||||
cRoot::Get()->GetPluginManager()->CallHookDisconnect(m_Player, "Player disconnected");
|
||||
cRoot::Get()->GetPluginManager()->CallHookDisconnect(*this, "Player disconnected");
|
||||
}
|
||||
|
||||
Destroy();
|
||||
|
@ -385,6 +385,9 @@ private:
|
||||
|
||||
/** Handles the "MC|AdvCdm" plugin message */
|
||||
void HandleCommandBlockMessage(const char * a_Data, size_t a_Length);
|
||||
|
||||
/** Handles the "MC|ItemName" plugin message */
|
||||
void HandleAnvilItemName(const char * a_Data, size_t a_Length);
|
||||
|
||||
// cSocketThreads::cCallback overrides:
|
||||
virtual bool DataReceived (const char * a_Data, size_t a_Size) override; // Data is received from the client
|
||||
|
@ -802,7 +802,7 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
|
||||
break;
|
||||
}
|
||||
case E_ITEM_PAPER: break;
|
||||
default: LOG("Unexpected item in firework rocket a_Recipe, was the crafting file fireworks section changed?"); break;
|
||||
default: LOG("Unexpected item in firework rocket recipe, was the crafting file's fireworks section changed?"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -837,7 +837,7 @@ void cCraftingRecipes::HandleFireworks(const cItem * a_CraftingGrid, cCraftingRe
|
||||
case E_ITEM_GOLD_NUGGET: a_Recipe->m_Result.m_FireworkItem.m_Type = 2; break;
|
||||
case E_ITEM_FEATHER: a_Recipe->m_Result.m_FireworkItem.m_Type = 4; break;
|
||||
case E_ITEM_HEAD: a_Recipe->m_Result.m_FireworkItem.m_Type = 3; break;
|
||||
default: LOG("Unexpected item in firework star a_Recipe, was the crafting file fireworks section changed?"); break; // ermahgerd BARD ardmins
|
||||
default: LOG("Unexpected item in firework star recipe, was the crafting file's fireworks section changed?"); break; // ermahgerd BARD ardmins
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ void cDeadlockDetect::CheckWorldAge(const AString & a_WorldName, Int64 a_Age)
|
||||
WorldAges::iterator itr = m_WorldAges.find(a_WorldName);
|
||||
if (itr == m_WorldAges.end())
|
||||
{
|
||||
ASSERT(!"Unknown world in cDeadlockDetect");
|
||||
SetWorldAge(a_WorldName, a_Age);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,15 @@ void cEnchantments::AddFromString(const AString & a_StringSpec)
|
||||
|
||||
|
||||
|
||||
size_t cEnchantments::Count(void)
|
||||
{
|
||||
return m_Enchantments.size();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AString cEnchantments::ToString(void) const
|
||||
{
|
||||
// Serialize all the enchantments into a string
|
||||
|
@ -84,6 +84,9 @@ public:
|
||||
/** Adds enchantments in the stringspec; if a specified enchantment already exists, overwrites it */
|
||||
void AddFromString(const AString & a_StringSpec);
|
||||
|
||||
/** Get the count of enchantments */
|
||||
size_t Count(void);
|
||||
|
||||
/** Serializes all the enchantments into a string */
|
||||
AString ToString(void) const;
|
||||
|
||||
|
@ -15,6 +15,7 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a
|
||||
m_IsCritical(false),
|
||||
m_Timer(0),
|
||||
m_HitGroundTimer(0),
|
||||
m_HasTeleported(false),
|
||||
m_bIsCollected(false),
|
||||
m_HitBlockPos(Vector3i(0, 0, 0))
|
||||
{
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "Entity.h"
|
||||
@ -10,7 +11,6 @@
|
||||
#include "../Simulator/FluidSimulator.h"
|
||||
#include "../Bindings/PluginManager.h"
|
||||
#include "../Tracer.h"
|
||||
#include "Minecart.h"
|
||||
#include "Player.h"
|
||||
|
||||
|
||||
@ -32,16 +32,10 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
||||
, m_Attachee(NULL)
|
||||
, m_bDirtyHead(true)
|
||||
, m_bDirtyOrientation(true)
|
||||
, m_bDirtyPosition(true)
|
||||
, m_bDirtySpeed(true)
|
||||
, m_bOnGround( false )
|
||||
, m_Gravity( -9.81f )
|
||||
, m_LastPosX( 0.0 )
|
||||
, m_LastPosY( 0.0 )
|
||||
, m_LastPosZ( 0.0 )
|
||||
, m_TimeLastTeleportPacket(0)
|
||||
, m_TimeLastMoveReltPacket(0)
|
||||
, m_TimeLastSpeedPacket(0)
|
||||
, m_bHasSentNoSpeed(true)
|
||||
, m_bOnGround(false)
|
||||
, m_Gravity(-9.81f)
|
||||
, m_LastPos(a_X, a_Y, a_Z)
|
||||
, m_IsInitialized(false)
|
||||
, m_EntityType(a_EntityType)
|
||||
, m_World(NULL)
|
||||
@ -55,7 +49,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
|
||||
, m_IsSubmerged(false)
|
||||
, m_AirLevel(0)
|
||||
, m_AirTickTimer(0)
|
||||
, m_HeadYaw( 0.0 )
|
||||
, m_HeadYaw(0.0)
|
||||
, m_Rot(0.0, 0.0, 0.0)
|
||||
, m_Pos(a_X, a_Y, a_Z)
|
||||
, m_WaterSpeed(0, 0, 0)
|
||||
@ -794,30 +788,43 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||
|
||||
NextSpeed += m_WaterSpeed;
|
||||
|
||||
if( NextSpeed.SqrLength() > 0.f )
|
||||
if (NextSpeed.SqrLength() > 0.f)
|
||||
{
|
||||
cTracer Tracer( GetWorld() );
|
||||
bool HasHit = Tracer.Trace( NextPos, NextSpeed, 2 );
|
||||
if (HasHit) // Oh noez! we hit something
|
||||
cTracer Tracer(GetWorld());
|
||||
// Distance traced is an integer, so we round up from the distance we should go (Speed * Delta), else we will encounter collision detection failurse
|
||||
int DistanceToTrace = (int)(ceil((NextSpeed * a_Dt).SqrLength()) * 2);
|
||||
bool HasHit = Tracer.Trace(NextPos, NextSpeed, DistanceToTrace);
|
||||
|
||||
if (HasHit)
|
||||
{
|
||||
// Set to hit position
|
||||
// Oh noez! We hit something: verify that the (hit position - current) was smaller or equal to the (position that we should travel without obstacles - current)
|
||||
// This is because previously, we traced with a length that was rounded up (due to integer limitations), and in the case that something was hit, we don't want to overshoot our projected movement
|
||||
if ((Tracer.RealHit - NextPos).SqrLength() <= (NextSpeed * a_Dt).SqrLength())
|
||||
{
|
||||
// Block hit was within our projected path
|
||||
// Begin by stopping movement in the direction that we hit something. The Normal is the line perpendicular to a 2D face and in this case, stores what block face was hit through either -1 or 1.
|
||||
// For example: HitNormal.y = -1 : BLOCK_FACE_YM; HitNormal.y = 1 : BLOCK_FACE_YP
|
||||
if (Tracer.HitNormal.x != 0.f) NextSpeed.x = 0.f;
|
||||
if (Tracer.HitNormal.y != 0.f) NextSpeed.y = 0.f;
|
||||
if (Tracer.HitNormal.z != 0.f) NextSpeed.z = 0.f;
|
||||
|
||||
if (Tracer.HitNormal.y > 0) // means on ground
|
||||
if (Tracer.HitNormal.y == 1) // Hit BLOCK_FACE_YP, we are on the ground
|
||||
{
|
||||
m_bOnGround = true;
|
||||
}
|
||||
NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
|
||||
NextPos.x += Tracer.HitNormal.x * 0.3f;
|
||||
NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
|
||||
NextPos.z += Tracer.HitNormal.z * 0.3f;
|
||||
|
||||
// Now, set our position to the hit block (i.e. move part way along our intended trajectory)
|
||||
NextPos.Set(Tracer.RealHit.x, Tracer.RealHit.y, Tracer.RealHit.z);
|
||||
NextPos.x += Tracer.HitNormal.x * 0.1;
|
||||
NextPos.y += Tracer.HitNormal.y * 0.05;
|
||||
NextPos.z += Tracer.HitNormal.z * 0.1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have hit a block but overshot our intended trajectory, move normally, safe in the warm cocoon of knowledge that we won't appear to teleport forwards on clients,
|
||||
// and that this piece of software will come to be hailed as the epitome of performance and functionality in C++, never before seen, and of such a like that will never
|
||||
// be henceforth seen again in the time of programmers and man alike
|
||||
// </&sensationalist>
|
||||
NextPos += (NextSpeed * a_Dt);
|
||||
}
|
||||
}
|
||||
@ -1010,9 +1017,9 @@ void cEntity::SetSwimState(cChunk & a_Chunk)
|
||||
{
|
||||
// This sometimes happens on Linux machines
|
||||
// Ref.: http://forum.mc-server.org/showthread.php?tid=1244
|
||||
LOGD("SetSwimState failure: RelX = %d, RelZ = %d, LastPos = {%.02f, %.02f}, Pos = %.02f, %.02f}",
|
||||
RelX, RelY, m_LastPosX, m_LastPosZ, GetPosX(), GetPosZ()
|
||||
);
|
||||
LOGD("SetSwimState failure: RelX = %d, RelZ = %d, Pos = %.02f, %.02f}",
|
||||
RelX, RelY, GetPosX(), GetPosZ()
|
||||
);
|
||||
m_IsSwimming = false;
|
||||
m_IsSubmerged = false;
|
||||
return;
|
||||
@ -1178,72 +1185,70 @@ void cEntity::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
||||
|
||||
void cEntity::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
|
||||
{
|
||||
// Send velocity packet every two ticks if: speed is not negligible or speed was set (as indicated by the DirtySpeed flag)
|
||||
if (((m_Speed.SqrLength() > 0.0004f) || m_bDirtySpeed) && ((m_World->GetWorldAge() - m_TimeLastSpeedPacket) >= 2))
|
||||
// Process packet sending every two ticks
|
||||
if (GetWorld()->GetWorldAge() % 2 == 0)
|
||||
{
|
||||
m_World->BroadcastEntityVelocity(*this,a_Exclude);
|
||||
m_bDirtySpeed = false;
|
||||
m_TimeLastSpeedPacket = m_World->GetWorldAge();
|
||||
}
|
||||
|
||||
// Have to process position related packets this every two ticks
|
||||
if (m_World->GetWorldAge() % 2 == 0)
|
||||
{
|
||||
int DiffX = (int) (floor(GetPosX() * 32.0) - floor(m_LastPosX * 32.0));
|
||||
int DiffY = (int) (floor(GetPosY() * 32.0) - floor(m_LastPosY * 32.0));
|
||||
int DiffZ = (int) (floor(GetPosZ() * 32.0) - floor(m_LastPosZ * 32.0));
|
||||
Int64 DiffTeleportPacket = m_World->GetWorldAge() - m_TimeLastTeleportPacket;
|
||||
// 4 blocks is max Relative So if the Diff is greater than 127 or. Send an absolute position every 20 seconds
|
||||
if (DiffTeleportPacket >= 400 ||
|
||||
((DiffX > 127) || (DiffX < -128) ||
|
||||
(DiffY > 127) || (DiffY < -128) ||
|
||||
(DiffZ > 127) || (DiffZ < -128)))
|
||||
double SpeedSqr = GetSpeed().SqrLength();
|
||||
if (SpeedSqr == 0.0)
|
||||
{
|
||||
//
|
||||
m_World->BroadcastTeleportEntity(*this,a_Exclude);
|
||||
m_TimeLastTeleportPacket = m_World->GetWorldAge();
|
||||
m_TimeLastMoveReltPacket = m_TimeLastTeleportPacket; //Must synchronize.
|
||||
m_LastPosX = GetPosX();
|
||||
m_LastPosY = GetPosY();
|
||||
m_LastPosZ = GetPosZ();
|
||||
m_bDirtyPosition = false;
|
||||
m_bDirtyOrientation = false;
|
||||
// Speed is zero, send this to clients once only as well as an absolute position
|
||||
if (!m_bHasSentNoSpeed)
|
||||
{
|
||||
m_World->BroadcastEntityVelocity(*this, a_Exclude);
|
||||
m_World->BroadcastTeleportEntity(*this, a_Exclude);
|
||||
m_bHasSentNoSpeed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Int64 DiffMoveRelPacket = m_World->GetWorldAge() - m_TimeLastMoveReltPacket;
|
||||
//if the change is big enough.
|
||||
if ((abs(DiffX) >= 4 || abs(DiffY) >= 4 || abs(DiffZ) >= 4 || DiffMoveRelPacket >= 60) && m_bDirtyPosition)
|
||||
// Movin'
|
||||
m_World->BroadcastEntityVelocity(*this, a_Exclude);
|
||||
m_bHasSentNoSpeed = false;
|
||||
}
|
||||
|
||||
// TODO: Pickups move disgracefully if relative move packets are sent as opposed to just velocity. Have a system to send relmove only when SetPosXXX() is called with a large difference in position
|
||||
int DiffX = (int)(floor(GetPosX() * 32.0) - floor(m_LastPos.x * 32.0));
|
||||
int DiffY = (int)(floor(GetPosY() * 32.0) - floor(m_LastPos.y * 32.0));
|
||||
int DiffZ = (int)(floor(GetPosZ() * 32.0) - floor(m_LastPos.z * 32.0));
|
||||
|
||||
if ((DiffX != 0) || (DiffY != 0) || (DiffZ != 0)) // Have we moved?
|
||||
{
|
||||
if ((abs(DiffX) <= 127) && (abs(DiffY) <= 127) && (abs(DiffZ) <= 127)) // Limitations of a Byte
|
||||
{
|
||||
// Difference within Byte limitations, use a relative move packet
|
||||
if (m_bDirtyOrientation)
|
||||
{
|
||||
m_World->BroadcastEntityRelMoveLook(*this, (char)DiffX, (char)DiffY, (char)DiffZ,a_Exclude);
|
||||
m_World->BroadcastEntityRelMoveLook(*this, (char)DiffX, (char)DiffY, (char)DiffZ, a_Exclude);
|
||||
m_bDirtyOrientation = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_World->BroadcastEntityRelMove(*this, (char)DiffX, (char)DiffY, (char)DiffZ,a_Exclude);
|
||||
m_World->BroadcastEntityRelMove(*this, (char)DiffX, (char)DiffY, (char)DiffZ, a_Exclude);
|
||||
}
|
||||
m_LastPosX = GetPosX();
|
||||
m_LastPosY = GetPosY();
|
||||
m_LastPosZ = GetPosZ();
|
||||
m_bDirtyPosition = false;
|
||||
m_TimeLastMoveReltPacket = m_World->GetWorldAge();
|
||||
// Clients seem to store two positions, one for the velocity packet and one for the teleport/relmove packet
|
||||
// The latter is only changed with a relmove/teleport, and m_LastPos stores this position
|
||||
m_LastPos = GetPosition();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_bDirtyOrientation)
|
||||
{
|
||||
m_World->BroadcastEntityLook(*this,a_Exclude);
|
||||
m_bDirtyOrientation = false;
|
||||
}
|
||||
}
|
||||
// Too big a movement, do a teleport
|
||||
m_World->BroadcastTeleportEntity(*this, a_Exclude);
|
||||
m_LastPos = GetPosition(); // See above
|
||||
m_bDirtyOrientation = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bDirtyHead)
|
||||
{
|
||||
m_World->BroadcastEntityHeadLook(*this,a_Exclude);
|
||||
m_World->BroadcastEntityHeadLook(*this, a_Exclude);
|
||||
m_bDirtyHead = false;
|
||||
}
|
||||
if (m_bDirtyOrientation)
|
||||
{
|
||||
// Send individual update in case above (sending with rel-move packet) wasn't done
|
||||
GetWorld()->BroadcastEntityLook(*this, a_Exclude);
|
||||
m_bDirtyOrientation = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1383,7 +1388,7 @@ void cEntity::SetRoll(double a_Roll)
|
||||
void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
||||
{
|
||||
m_Speed.Set(a_SpeedX, a_SpeedY, a_SpeedZ);
|
||||
m_bDirtySpeed = true;
|
||||
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1393,7 +1398,7 @@ void cEntity::SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
|
||||
void cEntity::SetSpeedX(double a_SpeedX)
|
||||
{
|
||||
m_Speed.x = a_SpeedX;
|
||||
m_bDirtySpeed = true;
|
||||
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1403,7 +1408,7 @@ void cEntity::SetSpeedX(double a_SpeedX)
|
||||
void cEntity::SetSpeedY(double a_SpeedY)
|
||||
{
|
||||
m_Speed.y = a_SpeedY;
|
||||
m_bDirtySpeed = true;
|
||||
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1413,7 +1418,7 @@ void cEntity::SetSpeedY(double a_SpeedY)
|
||||
void cEntity::SetSpeedZ(double a_SpeedZ)
|
||||
{
|
||||
m_Speed.z = a_SpeedZ;
|
||||
m_bDirtySpeed = true;
|
||||
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1433,7 +1438,7 @@ void cEntity::SetWidth(double a_Width)
|
||||
void cEntity::AddPosX(double a_AddPosX)
|
||||
{
|
||||
m_Pos.x += a_AddPosX;
|
||||
m_bDirtyPosition = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1442,7 +1447,7 @@ void cEntity::AddPosX(double a_AddPosX)
|
||||
void cEntity::AddPosY(double a_AddPosY)
|
||||
{
|
||||
m_Pos.y += a_AddPosY;
|
||||
m_bDirtyPosition = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1451,7 +1456,7 @@ void cEntity::AddPosY(double a_AddPosY)
|
||||
void cEntity::AddPosZ(double a_AddPosZ)
|
||||
{
|
||||
m_Pos.z += a_AddPosZ;
|
||||
m_bDirtyPosition = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1462,7 +1467,7 @@ void cEntity::AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ)
|
||||
m_Pos.x += a_AddPosX;
|
||||
m_Pos.y += a_AddPosY;
|
||||
m_Pos.z += a_AddPosZ;
|
||||
m_bDirtyPosition = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1472,8 +1477,7 @@ void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeed
|
||||
{
|
||||
m_Speed.x += a_AddSpeedX;
|
||||
m_Speed.y += a_AddSpeedY;
|
||||
m_Speed.z += a_AddSpeedZ;
|
||||
m_bDirtySpeed = true;
|
||||
m_Speed.z += a_AddSpeedZ;
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1483,8 +1487,7 @@ void cEntity::AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeed
|
||||
|
||||
void cEntity::AddSpeedX(double a_AddSpeedX)
|
||||
{
|
||||
m_Speed.x += a_AddSpeedX;
|
||||
m_bDirtySpeed = true;
|
||||
m_Speed.x += a_AddSpeedX;
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1494,8 +1497,7 @@ void cEntity::AddSpeedX(double a_AddSpeedX)
|
||||
|
||||
void cEntity::AddSpeedY(double a_AddSpeedY)
|
||||
{
|
||||
m_Speed.y += a_AddSpeedY;
|
||||
m_bDirtySpeed = true;
|
||||
m_Speed.y += a_AddSpeedY;
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1505,8 +1507,7 @@ void cEntity::AddSpeedY(double a_AddSpeedY)
|
||||
|
||||
void cEntity::AddSpeedZ(double a_AddSpeedZ)
|
||||
{
|
||||
m_Speed.z += a_AddSpeedZ;
|
||||
m_bDirtySpeed = true;
|
||||
m_Speed.z += a_AddSpeedZ;
|
||||
WrapSpeed();
|
||||
}
|
||||
|
||||
@ -1561,8 +1562,7 @@ Vector3d cEntity::GetLookVector(void) const
|
||||
// Set position
|
||||
void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
||||
{
|
||||
m_Pos.Set(a_PosX, a_PosY, a_PosZ);
|
||||
m_bDirtyPosition = true;
|
||||
m_Pos.Set(a_PosX, a_PosY, a_PosZ);
|
||||
}
|
||||
|
||||
|
||||
@ -1571,8 +1571,7 @@ void cEntity::SetPosition(double a_PosX, double a_PosY, double a_PosZ)
|
||||
|
||||
void cEntity::SetPosX(double a_PosX)
|
||||
{
|
||||
m_Pos.x = a_PosX;
|
||||
m_bDirtyPosition = true;
|
||||
m_Pos.x = a_PosX;
|
||||
}
|
||||
|
||||
|
||||
@ -1581,8 +1580,7 @@ void cEntity::SetPosX(double a_PosX)
|
||||
|
||||
void cEntity::SetPosY(double a_PosY)
|
||||
{
|
||||
m_Pos.y = a_PosY;
|
||||
m_bDirtyPosition = true;
|
||||
m_Pos.y = a_PosY;
|
||||
}
|
||||
|
||||
|
||||
@ -1592,7 +1590,6 @@ void cEntity::SetPosY(double a_PosY)
|
||||
void cEntity::SetPosZ(double a_PosZ)
|
||||
{
|
||||
m_Pos.z = a_PosZ;
|
||||
m_bDirtyPosition = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -430,22 +430,29 @@ protected:
|
||||
/// The entity which is attached to this entity (rider), NULL if none
|
||||
cEntity * m_Attachee;
|
||||
|
||||
// Flags that signal that we haven't updated the clients with the latest.
|
||||
bool m_bDirtyHead;
|
||||
bool m_bDirtyOrientation;
|
||||
bool m_bDirtyPosition;
|
||||
bool m_bDirtySpeed;
|
||||
|
||||
bool m_bOnGround;
|
||||
float m_Gravity;
|
||||
/** Stores whether head yaw has been set manually */
|
||||
bool m_bDirtyHead;
|
||||
|
||||
// Last Position.
|
||||
double m_LastPosX, m_LastPosY, m_LastPosZ;
|
||||
/** Stores whether our yaw/pitch/roll (body orientation) has been set manually */
|
||||
bool m_bDirtyOrientation;
|
||||
|
||||
/** Stores whether we have sent a Velocity packet with a speed of zero (no speed) to the client
|
||||
Ensures that said packet is sent only once */
|
||||
bool m_bHasSentNoSpeed;
|
||||
|
||||
// This variables keep track of the last time a packet was sent
|
||||
Int64 m_TimeLastTeleportPacket, m_TimeLastMoveReltPacket, m_TimeLastSpeedPacket; // In ticks
|
||||
/** Stores if the entity is on the ground */
|
||||
bool m_bOnGround;
|
||||
|
||||
/** Stores gravity that is applied to an entity every tick
|
||||
For realistic effects, this should be negative. For spaaaaaaace, this can be zero or even positive */
|
||||
float m_Gravity;
|
||||
|
||||
/** Last position sent to client via the Relative Move or Teleport packets (not Velocity)
|
||||
Only updated if cEntity::BroadcastMovementUpdate() is called! */
|
||||
Vector3d m_LastPos;
|
||||
|
||||
bool m_IsInitialized; // Is set to true when it's initialized, until it's destroyed (Initialize() till Destroy() )
|
||||
/** True when entity is initialised (Initialize()) and false when destroyed pending deletion (Destroy()) */
|
||||
bool m_IsInitialized;
|
||||
|
||||
eEntityType m_EntityType;
|
||||
|
||||
@ -469,12 +476,14 @@ protected:
|
||||
/// Time, in ticks, since the last damage dealt by the void. Reset to zero when moving out of the void.
|
||||
int m_TicksSinceLastVoidDamage;
|
||||
|
||||
|
||||
virtual void Destroyed(void) {} // Called after the entity has been destroyed
|
||||
|
||||
void SetWorld(cWorld * a_World) { m_World = a_World; }
|
||||
|
||||
/** Called in each tick to handle air-related processing i.e. drowning */
|
||||
virtual void HandleAir();
|
||||
|
||||
/** Called once per tick to set IsSwimming and IsSubmerged */
|
||||
virtual void SetSwimState(cChunk & a_Chunk);
|
||||
|
||||
|
@ -34,8 +34,6 @@ cExpOrb::cExpOrb(const Vector3d & a_Pos, int a_Reward)
|
||||
void cExpOrb::SpawnOn(cClientHandle & a_Client)
|
||||
{
|
||||
a_Client.SendExperienceOrb(*this);
|
||||
m_bDirtyPosition = false;
|
||||
m_bDirtySpeed = false;
|
||||
m_bDirtyOrientation = false;
|
||||
m_bDirtyHead = false;
|
||||
}
|
||||
|
@ -87,9 +87,8 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
AddSpeedY(MilliDt * -9.8f);
|
||||
AddPosition(GetSpeed() * MilliDt);
|
||||
|
||||
// If not static (One billionth precision) broadcast movement.
|
||||
static const float epsilon = 0.000000001f;
|
||||
if ((fabs(GetSpeedX()) > epsilon) || (fabs(GetSpeedZ()) > epsilon))
|
||||
// If not static (one billionth precision) broadcast movement
|
||||
if ((fabs(GetSpeedX()) > std::numeric_limits<double>::epsilon()) || (fabs(GetSpeedZ()) > std::numeric_limits<double>::epsilon()))
|
||||
{
|
||||
BroadcastMovementUpdate();
|
||||
}
|
||||
|
@ -76,11 +76,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
||||
|
||||
cTimer t1;
|
||||
m_LastPlayerListTime = t1.GetNowTime();
|
||||
|
||||
m_TimeLastTeleportPacket = 0;
|
||||
|
||||
m_PlayerName = a_PlayerName;
|
||||
m_bDirtyPosition = true; // So chunks are streamed to player at spawn
|
||||
|
||||
if (!LoadFromDisk())
|
||||
{
|
||||
@ -209,25 +206,22 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
m_BowCharge += 1;
|
||||
}
|
||||
|
||||
//handle updating experience
|
||||
// Handle updating experience
|
||||
if (m_bDirtyExperience)
|
||||
{
|
||||
SendExperience();
|
||||
}
|
||||
|
||||
if (m_bDirtyPosition)
|
||||
if (GetPosition() != m_LastPos) // Change in position from last tick?
|
||||
{
|
||||
// Apply food exhaustion from movement:
|
||||
ApplyFoodExhaustionFromMovement();
|
||||
|
||||
cRoot::Get()->GetPluginManager()->CallHookPlayerMoving(*this);
|
||||
BroadcastMovementUpdate(m_ClientHandle);
|
||||
m_ClientHandle->StreamChunks();
|
||||
}
|
||||
else
|
||||
{
|
||||
BroadcastMovementUpdate(m_ClientHandle);
|
||||
}
|
||||
|
||||
BroadcastMovementUpdate(m_ClientHandle);
|
||||
|
||||
if (m_Health > 0) // make sure player is alive
|
||||
{
|
||||
@ -1596,10 +1590,7 @@ bool cPlayer::LoadFromDisk()
|
||||
SetPosX(JSON_PlayerPosition[(unsigned int)0].asDouble());
|
||||
SetPosY(JSON_PlayerPosition[(unsigned int)1].asDouble());
|
||||
SetPosZ(JSON_PlayerPosition[(unsigned int)2].asDouble());
|
||||
m_LastPosX = GetPosX();
|
||||
m_LastPosY = GetPosY();
|
||||
m_LastPosZ = GetPosZ();
|
||||
m_LastFoodPos = GetPosition();
|
||||
m_LastPos = GetPosition();
|
||||
}
|
||||
|
||||
Json::Value & JSON_PlayerRotation = root["rotation"];
|
||||
@ -1860,17 +1851,16 @@ void cPlayer::ApplyFoodExhaustionFromMovement()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the distance travelled, update the last pos:
|
||||
Vector3d Movement(GetPosition() - m_LastFoodPos);
|
||||
Movement.y = 0; // Only take XZ movement into account
|
||||
m_LastFoodPos = GetPosition();
|
||||
|
||||
|
||||
// If riding anything, apply no food exhaustion
|
||||
if (m_AttachedTo != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the distance travelled, update the last pos:
|
||||
Vector3d Movement(GetPosition() - m_LastPos);
|
||||
Movement.y = 0; // Only take XZ movement into account
|
||||
|
||||
// Apply the exhaustion based on distance travelled:
|
||||
double BaseExhaustion = Movement.Length();
|
||||
|
@ -423,9 +423,6 @@ protected:
|
||||
/** Number of ticks remaining for the foodpoisoning effect; zero if not foodpoisoned */
|
||||
int m_FoodPoisonedTicksRemaining;
|
||||
|
||||
/** Last position that has been recorded for food-related processing: */
|
||||
Vector3d m_LastFoodPos;
|
||||
|
||||
float m_LastJumpHeight;
|
||||
float m_LastGroundHeight;
|
||||
bool m_bTouchGround;
|
||||
|
@ -30,8 +30,6 @@ cTNTEntity::cTNTEntity(const Vector3d & a_Pos, int a_FuseTicks) :
|
||||
void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle)
|
||||
{
|
||||
a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT
|
||||
m_bDirtyPosition = false;
|
||||
m_bDirtySpeed = false;
|
||||
m_bDirtyOrientation = false;
|
||||
m_bDirtyHead = false;
|
||||
}
|
||||
|
@ -35,13 +35,6 @@ reduced in complexity in order for this generator to be useful, so the caves' sh
|
||||
|
||||
|
||||
|
||||
/// How many nests in each direction are generated for a given chunk. Must be an even number
|
||||
#define NEIGHBORHOOD_SIZE 8
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const int MIN_RADIUS = 3;
|
||||
const int MAX_RADIUS = 8;
|
||||
|
||||
@ -122,27 +115,19 @@ typedef std::vector<cCaveTunnel *> cCaveTunnels;
|
||||
|
||||
|
||||
/// A collection of connected tunnels, possibly branching.
|
||||
class cStructGenWormNestCaves::cCaveSystem
|
||||
class cStructGenWormNestCaves::cCaveSystem :
|
||||
public cGridStructGen::cStructure
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
public:
|
||||
// The generating block position; is read directly in cStructGenWormNestCaves::GetCavesForChunk()
|
||||
int m_BlockX;
|
||||
int m_BlockZ;
|
||||
|
||||
cCaveSystem(int a_BlockX, int a_BlockZ, int a_MaxOffset, int a_Size, cNoise & a_Noise);
|
||||
cCaveSystem(int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise);
|
||||
~cCaveSystem();
|
||||
|
||||
/// Carves the cave system into the chunk specified
|
||||
void ProcessChunk(
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
cChunkDef::BlockTypes & a_BlockTypes,
|
||||
cChunkDef::HeightMap & a_HeightMap
|
||||
);
|
||||
|
||||
#ifdef _DEBUG
|
||||
AString ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const;
|
||||
#endif // _DEBUG
|
||||
|
||||
protected:
|
||||
int m_Size;
|
||||
cCaveTunnels m_Tunnels;
|
||||
@ -157,6 +142,9 @@ protected:
|
||||
|
||||
/// Returns a radius based on the location provided.
|
||||
int GetRadius(cNoise & a_Noise, int a_OriginX, int a_OriginY, int a_OriginZ);
|
||||
|
||||
// cGridStructGen::cStructure overrides:
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override;
|
||||
} ;
|
||||
|
||||
|
||||
@ -239,9 +227,15 @@ void cCaveTunnel::Randomize(cNoise & a_Noise)
|
||||
|
||||
bool cCaveTunnel::RefineDefPoints(const cCaveDefPoints & a_Src, cCaveDefPoints & a_Dst)
|
||||
{
|
||||
if (a_Src.size() < 2)
|
||||
{
|
||||
// There are no midpoints, nothing to smooth
|
||||
return true;
|
||||
}
|
||||
|
||||
// Smoothing: for each line segment, add points on its 1/4 lengths
|
||||
bool res = false;
|
||||
int Num = a_Src.size() - 2; // this many intermediary points
|
||||
size_t Num = a_Src.size() - 2; // this many intermediary points
|
||||
a_Dst.clear();
|
||||
a_Dst.reserve(Num * 2 + 2);
|
||||
cCaveDefPoints::const_iterator itr = a_Src.begin() + 1;
|
||||
@ -251,7 +245,7 @@ bool cCaveTunnel::RefineDefPoints(const cCaveDefPoints & a_Src, cCaveDefPoints &
|
||||
int PrevY = Source.m_BlockY;
|
||||
int PrevZ = Source.m_BlockZ;
|
||||
int PrevR = Source.m_Radius;
|
||||
for (int i = 0; i <= Num; ++i, ++itr)
|
||||
for (size_t i = 0; i <= Num; ++i, ++itr)
|
||||
{
|
||||
int dx = itr->m_BlockX - PrevX;
|
||||
int dy = itr->m_BlockY - PrevY;
|
||||
@ -580,17 +574,16 @@ AString cCaveTunnel::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) cons
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cStructGenWormNestCaves::cCaveSystem:
|
||||
|
||||
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_BlockX, int a_BlockZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) :
|
||||
m_BlockX(a_BlockX),
|
||||
m_BlockZ(a_BlockZ),
|
||||
cStructGenWormNestCaves::cCaveSystem::cCaveSystem(int a_OriginX, int a_OriginZ, int a_MaxOffset, int a_Size, cNoise & a_Noise) :
|
||||
super(a_OriginX, a_OriginZ),
|
||||
m_Size(a_Size)
|
||||
{
|
||||
int Num = 1 + a_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) % 3;
|
||||
int Num = 1 + a_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) % 3;
|
||||
for (int i = 0; i < Num; i++)
|
||||
{
|
||||
int OriginX = a_BlockX + (a_Noise.IntNoise3DInt(13 * a_BlockX, 17 * a_BlockZ, 11 * i) / 19) % a_MaxOffset;
|
||||
int OriginZ = a_BlockZ + (a_Noise.IntNoise3DInt(17 * a_BlockX, 13 * a_BlockZ, 11 * i) / 23) % a_MaxOffset;
|
||||
int OriginY = 20 + (a_Noise.IntNoise3DInt(19 * a_BlockX, 13 * a_BlockZ, 11 * i) / 17) % 20;
|
||||
int OriginX = a_OriginX + (a_Noise.IntNoise3DInt(13 * a_OriginX, 17 * a_OriginZ, 11 * i) / 19) % a_MaxOffset;
|
||||
int OriginZ = a_OriginZ + (a_Noise.IntNoise3DInt(17 * a_OriginX, 13 * a_OriginZ, 11 * i) / 23) % a_MaxOffset;
|
||||
int OriginY = 20 + (a_Noise.IntNoise3DInt(19 * a_OriginX, 13 * a_OriginZ, 11 * i) / 17) % 20;
|
||||
|
||||
// Generate three branches from the origin point:
|
||||
// The tunnels generated depend on X, Y, Z and Branches,
|
||||
@ -616,15 +609,15 @@ cStructGenWormNestCaves::cCaveSystem::~cCaveSystem()
|
||||
|
||||
|
||||
|
||||
void cStructGenWormNestCaves::cCaveSystem::ProcessChunk(
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
cChunkDef::BlockTypes & a_BlockTypes,
|
||||
cChunkDef::HeightMap & a_HeightMap
|
||||
)
|
||||
void cStructGenWormNestCaves::cCaveSystem::DrawIntoChunk(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes();
|
||||
cChunkDef::HeightMap & HeightMap = a_ChunkDesc.GetHeightMap();
|
||||
for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
|
||||
{
|
||||
(*itr)->ProcessChunk(a_ChunkX, a_ChunkZ, a_BlockTypes, a_HeightMap);
|
||||
(*itr)->ProcessChunk(ChunkX, ChunkZ, BlockTypes, HeightMap);
|
||||
} // for itr - m_Tunnels[]
|
||||
}
|
||||
|
||||
@ -632,53 +625,6 @@ void cStructGenWormNestCaves::cCaveSystem::ProcessChunk(
|
||||
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
AString cStructGenWormNestCaves::cCaveSystem::ExportAsSVG(int a_Color, int a_OffsetX, int a_OffsetZ) const
|
||||
{
|
||||
AString SVG;
|
||||
SVG.reserve(512 * 1024);
|
||||
for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
|
||||
{
|
||||
SVG.append((*itr)->ExportAsSVG(a_Color, a_OffsetX, a_OffsetZ));
|
||||
} // for itr - m_Tunnels[]
|
||||
|
||||
// Base point highlight:
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
||||
a_OffsetX + m_BlockX - 5, a_OffsetZ + m_BlockZ, a_OffsetX + m_BlockX + 5, a_OffsetZ + m_BlockZ
|
||||
);
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
||||
a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ - 5, a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ + 5
|
||||
);
|
||||
|
||||
// A gray line from the base point to the first point of the ravine, for identification:
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#cfcfcf;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
||||
a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ,
|
||||
a_OffsetX + m_Tunnels.front()->m_Points.front().m_BlockX,
|
||||
a_OffsetZ + m_Tunnels.front()->m_Points.front().m_BlockZ
|
||||
);
|
||||
|
||||
// Offset guides:
|
||||
if (a_OffsetX > 0)
|
||||
{
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M %d,0 L %d,1024\"/>\n",
|
||||
a_OffsetX, a_OffsetX
|
||||
);
|
||||
}
|
||||
if (a_OffsetZ > 0)
|
||||
{
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#0000ff;stroke-width:1px;\"\nd=\"M 0,%d L 1024,%d\"/>\n",
|
||||
a_OffsetZ, a_OffsetZ
|
||||
);
|
||||
}
|
||||
|
||||
return SVG;
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenWormNestCaves::cCaveSystem::Clear(void)
|
||||
{
|
||||
for (cCaveTunnels::const_iterator itr = m_Tunnels.begin(), end = m_Tunnels.end(); itr != end; ++itr)
|
||||
@ -744,142 +690,9 @@ int cStructGenWormNestCaves::cCaveSystem::GetRadius(cNoise & a_Noise, int a_Orig
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cStructGenWormNestCaves:
|
||||
|
||||
cStructGenWormNestCaves::~cStructGenWormNestCaves()
|
||||
cGridStructGen::cStructurePtr cStructGenWormNestCaves::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||
{
|
||||
ClearCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenWormNestCaves::ClearCache(void)
|
||||
{
|
||||
for (cCaveSystems::const_iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
} // for itr - m_Cache[]
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenWormNestCaves::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
cCaveSystems Caves;
|
||||
GetCavesForChunk(ChunkX, ChunkZ, Caves);
|
||||
for (cCaveSystems::const_iterator itr = Caves.begin(); itr != Caves.end(); ++itr)
|
||||
{
|
||||
(*itr)->ProcessChunk(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
|
||||
} // for itr - Caves[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenWormNestCaves::GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cStructGenWormNestCaves::cCaveSystems & a_Caves)
|
||||
{
|
||||
int BaseX = a_ChunkX * cChunkDef::Width / m_Grid;
|
||||
int BaseZ = a_ChunkZ * cChunkDef::Width / m_Grid;
|
||||
if (BaseX < 0)
|
||||
{
|
||||
--BaseX;
|
||||
}
|
||||
if (BaseZ < 0)
|
||||
{
|
||||
--BaseZ;
|
||||
}
|
||||
BaseX -= NEIGHBORHOOD_SIZE / 2;
|
||||
BaseZ -= NEIGHBORHOOD_SIZE / 2;
|
||||
|
||||
// Walk the cache, move each cave system that we want into a_Caves:
|
||||
int StartX = BaseX * m_Grid;
|
||||
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_Grid;
|
||||
int StartZ = BaseZ * m_Grid;
|
||||
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_Grid;
|
||||
for (cCaveSystems::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
|
||||
{
|
||||
if (
|
||||
((*itr)->m_BlockX >= StartX) && ((*itr)->m_BlockX < EndX) &&
|
||||
((*itr)->m_BlockZ >= StartZ) && ((*itr)->m_BlockZ < EndZ)
|
||||
)
|
||||
{
|
||||
// want
|
||||
a_Caves.push_back(*itr);
|
||||
itr = m_Cache.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't want
|
||||
++itr;
|
||||
}
|
||||
} // for itr - m_Cache[]
|
||||
|
||||
for (int x = 0; x < NEIGHBORHOOD_SIZE; x++)
|
||||
{
|
||||
int RealX = (BaseX + x) * m_Grid;
|
||||
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
|
||||
{
|
||||
int RealZ = (BaseZ + z) * m_Grid;
|
||||
bool Found = false;
|
||||
for (cCaveSystems::const_iterator itr = a_Caves.begin(), end = a_Caves.end(); itr != end; ++itr)
|
||||
{
|
||||
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!Found)
|
||||
{
|
||||
a_Caves.push_back(new cCaveSystem(RealX, RealZ, m_MaxOffset, m_Size, m_Noise));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy a_Caves into m_Cache to the beginning:
|
||||
cCaveSystems CavesCopy(a_Caves);
|
||||
m_Cache.splice(m_Cache.begin(), CavesCopy, CavesCopy.begin(), CavesCopy.end());
|
||||
|
||||
// Trim the cache if it's too long:
|
||||
if (m_Cache.size() > 100)
|
||||
{
|
||||
cCaveSystems::iterator itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
for (cCaveSystems::iterator end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
}
|
||||
itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
m_Cache.erase(itr, m_Cache.end());
|
||||
}
|
||||
|
||||
/*
|
||||
// Uncomment this block for debugging the caves' shapes in 2D using an SVG export
|
||||
#ifdef _DEBUG
|
||||
AString SVG;
|
||||
SVG.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1024\" height = \"1024\">\n");
|
||||
SVG.reserve(2 * 1024 * 1024);
|
||||
for (cCaveSystems::const_iterator itr = a_Caves.begin(), end = a_Caves.end(); itr != end; ++itr)
|
||||
{
|
||||
int Color = 0x10 * abs((*itr)->m_BlockX / m_Grid);
|
||||
Color |= 0x1000 * abs((*itr)->m_BlockZ / m_Grid);
|
||||
SVG.append((*itr)->ExportAsSVG(Color, 512, 512));
|
||||
}
|
||||
SVG.append("</svg>\n");
|
||||
|
||||
AString fnam;
|
||||
Printf(fnam, "wnc\\%03d_%03d.svg", a_ChunkX, a_ChunkZ);
|
||||
cFile File(fnam, cFile::fmWrite);
|
||||
File.Write(SVG.c_str(), SVG.size());
|
||||
#endif // _DEBUG
|
||||
//*/
|
||||
return cStructurePtr(new cCaveSystem(a_OriginX, a_OriginZ, m_MaxOffset, m_Size, m_Noise));
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ComposableGenerator.h"
|
||||
#include "GridStructGen.h"
|
||||
#include "../Noise.h"
|
||||
|
||||
|
||||
@ -64,10 +64,12 @@ protected:
|
||||
|
||||
|
||||
class cStructGenWormNestCaves :
|
||||
public cFinishGen
|
||||
public cGridStructGen
|
||||
{
|
||||
typedef cGridStructGen super;
|
||||
public:
|
||||
cStructGenWormNestCaves(int a_Seed, int a_Size = 64, int a_Grid = 96, int a_MaxOffset = 128) :
|
||||
super(a_Seed, a_Grid, a_Grid, a_Size + a_MaxOffset, a_Size + a_MaxOffset, 100),
|
||||
m_Noise(a_Seed),
|
||||
m_Size(a_Size),
|
||||
m_MaxOffset(a_MaxOffset),
|
||||
@ -75,26 +77,16 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
~cStructGenWormNestCaves();
|
||||
|
||||
protected:
|
||||
class cCaveSystem; // fwd: Caves.cpp
|
||||
typedef std::list<cCaveSystem *> cCaveSystems;
|
||||
|
||||
cNoise m_Noise;
|
||||
int m_Size; // relative size of the cave systems' caves. Average number of blocks of each initial tunnel
|
||||
int m_MaxOffset; // maximum offset of the cave nest origin from the grid cell the nest belongs to
|
||||
int m_Grid; // average spacing of the nests
|
||||
cCaveSystems m_Cache;
|
||||
|
||||
/// Clears everything from the cache
|
||||
void ClearCache(void);
|
||||
|
||||
/// Returns all caves that *may* intersect the given chunk. All the caves are valid until the next call to this function.
|
||||
void GetCavesForChunk(int a_ChunkX, int a_ChunkZ, cCaveSystems & a_Caves);
|
||||
|
||||
// cStructGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
// cGridStructGen override:
|
||||
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
126
src/Generating/GridStructGen.cpp
Normal file
126
src/Generating/GridStructGen.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
|
||||
// GridStructGen.cpp
|
||||
|
||||
// Implements the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid
|
||||
|
||||
#include "Globals.h"
|
||||
#include "GridStructGen.h"
|
||||
|
||||
|
||||
|
||||
|
||||
cGridStructGen::cGridStructGen(
|
||||
int a_Seed,
|
||||
int a_GridSizeX, int a_GridSizeZ,
|
||||
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
|
||||
size_t a_MaxCacheSize
|
||||
) :
|
||||
m_Seed(a_Seed),
|
||||
m_GridSizeX(a_GridSizeX),
|
||||
m_GridSizeZ(a_GridSizeZ),
|
||||
m_MaxStructureSizeX(a_MaxStructureSizeX),
|
||||
m_MaxStructureSizeZ(a_MaxStructureSizeZ),
|
||||
m_MaxCacheSize(a_MaxCacheSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cGridStructGen::GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures)
|
||||
{
|
||||
// Calculate the min and max grid coords of the structures to be returned:
|
||||
int MinBlockX = a_ChunkX * cChunkDef::Width - m_MaxStructureSizeX;
|
||||
int MinBlockZ = a_ChunkZ * cChunkDef::Width - m_MaxStructureSizeZ;
|
||||
int MaxBlockX = a_ChunkX * cChunkDef::Width + m_MaxStructureSizeX + cChunkDef::Width - 1;
|
||||
int MaxBlockZ = a_ChunkZ * cChunkDef::Width + m_MaxStructureSizeZ + cChunkDef::Width - 1;
|
||||
int MinGridX = MinBlockX / m_GridSizeX;
|
||||
int MinGridZ = MinBlockZ / m_GridSizeZ;
|
||||
int MaxGridX = (MaxBlockX + m_GridSizeX - 1) / m_GridSizeX;
|
||||
int MaxGridZ = (MaxBlockZ + m_GridSizeZ - 1) / m_GridSizeZ;
|
||||
int MinX = MinGridX * m_GridSizeX;
|
||||
int MaxX = MaxGridX * m_GridSizeX;
|
||||
int MinZ = MinGridZ * m_GridSizeZ;
|
||||
int MaxZ = MaxGridZ * m_GridSizeZ;
|
||||
|
||||
// Walk the cache, move each structure that we want into a_Structures:
|
||||
for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
|
||||
{
|
||||
if (
|
||||
((*itr)->m_OriginX >= MinX) && ((*itr)->m_OriginX < MaxX) &&
|
||||
((*itr)->m_OriginZ >= MinZ) && ((*itr)->m_OriginZ < MaxZ)
|
||||
)
|
||||
{
|
||||
// want
|
||||
a_Structures.push_back(*itr);
|
||||
itr = m_Cache.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't want
|
||||
++itr;
|
||||
}
|
||||
} // for itr - m_Cache[]
|
||||
|
||||
// Create those structures that haven't been in the cache:
|
||||
for (int x = MinGridX; x < MaxGridX; x++)
|
||||
{
|
||||
int OriginX = x * m_GridSizeX;
|
||||
for (int z = MinGridZ; z < MaxGridZ; z++)
|
||||
{
|
||||
int OriginZ = z * m_GridSizeZ;
|
||||
bool Found = false;
|
||||
for (cStructurePtrs::const_iterator itr = a_Structures.begin(), end = a_Structures.end(); itr != end; ++itr)
|
||||
{
|
||||
if (((*itr)->m_OriginX == OriginX) && ((*itr)->m_OriginZ == OriginZ))
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
} // for itr - a_Structures[]
|
||||
if (!Found)
|
||||
{
|
||||
a_Structures.push_back(CreateStructure(OriginX, OriginZ));
|
||||
}
|
||||
} // for z
|
||||
} // for x
|
||||
|
||||
// Copy a_Forts into m_Cache to the beginning:
|
||||
cStructurePtrs StructuresCopy (a_Structures);
|
||||
m_Cache.splice(m_Cache.begin(), StructuresCopy, StructuresCopy.begin(), StructuresCopy.end());
|
||||
|
||||
// Trim the cache if it's too long:
|
||||
size_t CacheSize = 0;
|
||||
for (cStructurePtrs::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
CacheSize += (*itr)->GetCacheCost();
|
||||
if (CacheSize > m_MaxCacheSize)
|
||||
{
|
||||
// Erase all items from this one till the cache end
|
||||
m_Cache.erase(itr, m_Cache.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cGridStructGen::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
cStructurePtrs Structures;
|
||||
GetStructuresForChunk(ChunkX, ChunkZ, Structures);
|
||||
for (cStructurePtrs::const_iterator itr = Structures.begin(); itr != Structures.end(); ++itr)
|
||||
{
|
||||
(*itr)->DrawIntoChunk(a_ChunkDesc);
|
||||
} // for itr - Structures[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
124
src/Generating/GridStructGen.h
Normal file
124
src/Generating/GridStructGen.h
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
// GridStructGen.h
|
||||
|
||||
// Declares the cGridStructGen class representing a common base class for structure generators that place structures in a semi-random grid
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ComposableGenerator.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Generates structures in a semi-random grid.
|
||||
Defines a grid in the XZ space with predefined cell size in each direction. Each cell then receives exactly
|
||||
one structure (provided by the descendant class). The structure is placed within the cell, but doesn't need
|
||||
to be bounded by the cell, it can be well outside the cell; the generator uses the MaxStructureSize parameter
|
||||
to determine how far away from the cell the structure can be at most.
|
||||
This class provides a cache for the structures generated for successive chunks and manages that cache. It
|
||||
also provides the cFinishGen override that uses the cache to actually generate the structure into chunk data.
|
||||
|
||||
After generating each chunk the cache is checked for size, each item in the cache has a cost associated with
|
||||
it and the cache is trimmed (from its least-recently-used end) so that the sum of the cost in the cache is
|
||||
less than m_MaxCacheSize
|
||||
|
||||
To use this class, declare a descendant class that implements the overridable methods, then create an
|
||||
instance of that class. The descendant must provide the CreateStructure() function that is called to generate
|
||||
a structure at the specific grid cell.
|
||||
|
||||
The descendant must use a specific cStructure descendant to provide the actual structure that gets generated.
|
||||
The structure must provide the DrawIntoChunk() function that generates the structure into the chunk data, and
|
||||
can override the GetCacheCost() function that returns the cost of that structure in the cache.
|
||||
*/
|
||||
class cGridStructGen :
|
||||
public cFinishGen
|
||||
{
|
||||
public:
|
||||
cGridStructGen(
|
||||
int a_Seed,
|
||||
int a_GridSizeX, int a_GridSizeZ,
|
||||
int a_MaxStructureSizeX, int a_MaxStructureSizeZ,
|
||||
size_t a_MaxCacheSize
|
||||
);
|
||||
|
||||
protected:
|
||||
/** Represents a single structure that occupies the grid point. Knows how to draw itself into a chunk. */
|
||||
class cStructure
|
||||
{
|
||||
public:
|
||||
/** The origin (the coords of the gridpoint for which the structure is generated) */
|
||||
int m_OriginX, m_OriginZ;
|
||||
|
||||
|
||||
/** Creates a structure that has its originset at the specified coords. */
|
||||
cStructure (int a_OriginX, int a_OriginZ) :
|
||||
m_OriginX(a_OriginX),
|
||||
m_OriginZ(a_OriginZ)
|
||||
{
|
||||
}
|
||||
|
||||
// Force a virtual destructor in descendants:
|
||||
virtual ~cStructure() {}
|
||||
|
||||
/** Draws self into the specified chunk */
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) = 0;
|
||||
|
||||
/** Returns the cost of keeping this structure in the cache */
|
||||
virtual size_t GetCacheCost(void) const { return 1; }
|
||||
} ;
|
||||
typedef SharedPtr<cStructure> cStructurePtr;
|
||||
typedef std::list<cStructurePtr> cStructurePtrs;
|
||||
|
||||
|
||||
/** Seed for generating the semi-random grid. */
|
||||
int m_Seed;
|
||||
|
||||
/** The size of each grid's cell in the X axis */
|
||||
int m_GridSizeX;
|
||||
|
||||
/** The size of each grid's cell in the Z axis */
|
||||
int m_GridSizeZ;
|
||||
|
||||
/** Maximum theoretical size of the structure in the X axis.
|
||||
This limits the structures considered for a single chunk, so the lesser the number, the better performance.
|
||||
Structures large than this may get cropped. */
|
||||
int m_MaxStructureSizeX;
|
||||
|
||||
/** Maximum theoretical size of the structure in the Z axis.
|
||||
This limits the structures considered for a single chunk, so the lesser the number, the better performance.
|
||||
Structures large than this may get cropped. */
|
||||
int m_MaxStructureSizeZ;
|
||||
|
||||
/** Maximum allowed sum of costs for items in the cache. Items that are over this cost are removed from the
|
||||
cache, oldest-first */
|
||||
size_t m_MaxCacheSize;
|
||||
|
||||
/** Cache for the most recently generated structures, ordered by the recentness. */
|
||||
cStructurePtrs m_Cache;
|
||||
|
||||
|
||||
/** Clears everything from the cache */
|
||||
void ClearCache(void);
|
||||
|
||||
/** Returns all structures that may intersect the given chunk.
|
||||
The structures are considered as intersecting iff their bounding box (defined by m_MaxStructureSize)
|
||||
around their gridpoint intersects the chunk. */
|
||||
void GetStructuresForChunk(int a_ChunkX, int a_ChunkZ, cStructurePtrs & a_Structures);
|
||||
|
||||
// cFinishGen overrides:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
// Functions for the descendants to override:
|
||||
/** Create a new structure at the specified gridpoint */
|
||||
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) = 0;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -25,12 +25,6 @@ in a depth-first processing. Each of the descendants will branch randomly, if no
|
||||
|
||||
|
||||
|
||||
static const int NEIGHBORHOOD_SIZE = 3;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cMineShaft abstract
|
||||
{
|
||||
public:
|
||||
@ -234,10 +228,12 @@ protected:
|
||||
|
||||
|
||||
|
||||
class cStructGenMineShafts::cMineShaftSystem
|
||||
class cStructGenMineShafts::cMineShaftSystem :
|
||||
public cGridStructGen::cStructure
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
public:
|
||||
int m_BlockX, m_BlockZ; ///< The pivot point on which the system is generated
|
||||
int m_GridSize; ///< Maximum offset of the dirtroom from grid center, * 2, in each direction
|
||||
int m_MaxRecursion; ///< Maximum recursion level (initialized from cStructGenMineShafts::m_MaxRecursion)
|
||||
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
||||
@ -249,17 +245,15 @@ public:
|
||||
cMineShafts m_MineShafts; ///< List of cMineShaft descendants that comprise this system
|
||||
cCuboid m_BoundingBox; ///< Bounding box into which all of the components need to fit
|
||||
|
||||
/// Creates and generates the entire system
|
||||
|
||||
/** Creates and generates the entire system */
|
||||
cMineShaftSystem(
|
||||
int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
||||
int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
||||
int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase
|
||||
);
|
||||
|
||||
~cMineShaftSystem();
|
||||
|
||||
/// Carves the system into the chunk data
|
||||
void ProcessChunk(cChunkDesc & a_Chunk);
|
||||
|
||||
/** Creates new cMineShaft descendant connected at the specified point, heading the specified direction,
|
||||
if it fits, appends it to the list and calls its AppendBranches()
|
||||
*/
|
||||
@ -269,8 +263,11 @@ public:
|
||||
int a_RecursionLevel
|
||||
);
|
||||
|
||||
/// Returns true if none of the objects in m_MineShafts intersect with the specified bounding box and the bounding box is valid
|
||||
/** Returns true if none of the objects in m_MineShafts intersect with the specified bounding box and the bounding box is valid */
|
||||
bool CanAppend(const cCuboid & a_BoundingBox);
|
||||
|
||||
// cGridStructGen::cStructure overrides:
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_Chunk);
|
||||
} ;
|
||||
|
||||
|
||||
@ -281,11 +278,10 @@ public:
|
||||
// cStructGenMineShafts::cMineShaftSystem:
|
||||
|
||||
cStructGenMineShafts::cMineShaftSystem::cMineShaftSystem(
|
||||
int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
||||
int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxSystemSize, cNoise & a_Noise,
|
||||
int a_ProbLevelCorridor, int a_ProbLevelCrossing, int a_ProbLevelStaircase
|
||||
) :
|
||||
m_BlockX(a_BlockX),
|
||||
m_BlockZ(a_BlockZ),
|
||||
super(a_OriginX, a_OriginZ),
|
||||
m_GridSize(a_GridSize),
|
||||
m_MaxRecursion(8), // TODO: settable
|
||||
m_ProbLevelCorridor(a_ProbLevelCorridor),
|
||||
@ -330,7 +326,7 @@ cStructGenMineShafts::cMineShaftSystem::~cMineShaftSystem()
|
||||
|
||||
|
||||
|
||||
void cStructGenMineShafts::cMineShaftSystem::ProcessChunk(cChunkDesc & a_Chunk)
|
||||
void cStructGenMineShafts::cMineShaftSystem::DrawIntoChunk(cChunkDesc & a_Chunk)
|
||||
{
|
||||
for (cMineShafts::const_iterator itr = m_MineShafts.begin(), end = m_MineShafts.end(); itr != end; ++itr)
|
||||
{
|
||||
@ -409,15 +405,15 @@ cMineShaftDirtRoom::cMineShaftDirtRoom(cStructGenMineShafts::cMineShaftSystem &
|
||||
super(a_Parent, mskDirtRoom)
|
||||
{
|
||||
// Make the room of random size, min 10 x 4 x 10; max 18 x 12 x 18:
|
||||
int rnd = a_Noise.IntNoise3DInt(a_Parent.m_BlockX, 0, a_Parent.m_BlockZ) / 7;
|
||||
int rnd = a_Noise.IntNoise3DInt(a_Parent.m_OriginX, 0, a_Parent.m_OriginZ) / 7;
|
||||
int OfsX = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2;
|
||||
rnd >>= 12;
|
||||
int OfsZ = (rnd % a_Parent.m_GridSize) - a_Parent.m_GridSize / 2;
|
||||
rnd = a_Noise.IntNoise3DInt(a_Parent.m_BlockX, 1000, a_Parent.m_BlockZ) / 11;
|
||||
m_BoundingBox.p1.x = a_Parent.m_BlockX + OfsX;
|
||||
rnd = a_Noise.IntNoise3DInt(a_Parent.m_OriginX, 1000, a_Parent.m_OriginZ) / 11;
|
||||
m_BoundingBox.p1.x = a_Parent.m_OriginX + OfsX;
|
||||
m_BoundingBox.p2.x = m_BoundingBox.p1.x + 10 + (rnd % 8);
|
||||
rnd >>= 4;
|
||||
m_BoundingBox.p1.z = a_Parent.m_BlockZ + OfsZ;
|
||||
m_BoundingBox.p1.z = a_Parent.m_OriginZ + OfsZ;
|
||||
m_BoundingBox.p2.z = m_BoundingBox.p1.z + 10 + (rnd % 8);
|
||||
rnd >>= 4;
|
||||
m_BoundingBox.p1.y = 20;
|
||||
@ -543,7 +539,7 @@ cMineShaft * cMineShaftCorridor::CreateAndFit(
|
||||
{
|
||||
cCuboid BoundingBox(a_PivotX, a_PivotY - 1, a_PivotZ);
|
||||
BoundingBox.p2.y += 3;
|
||||
int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + a_ParentSystem.m_MineShafts.size(), a_PivotZ) / 7;
|
||||
int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + (int)a_ParentSystem.m_MineShafts.size(), a_PivotZ) / 7;
|
||||
int NumSegments = 2 + (rnd) % (MAX_SEGMENTS - 1); // 2 .. MAX_SEGMENTS
|
||||
switch (a_Direction)
|
||||
{
|
||||
@ -985,7 +981,7 @@ cMineShaft * cMineShaftCrossing::CreateAndFit(
|
||||
)
|
||||
{
|
||||
cCuboid BoundingBox(a_PivotX, a_PivotY - 1, a_PivotZ);
|
||||
int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + a_ParentSystem.m_MineShafts.size(), a_PivotZ) / 7;
|
||||
int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + (int)a_ParentSystem.m_MineShafts.size(), a_PivotZ) / 7;
|
||||
BoundingBox.p2.y += 3;
|
||||
if ((rnd % 4) < 2)
|
||||
{
|
||||
@ -1127,7 +1123,7 @@ cMineShaft * cMineShaftStaircase::CreateAndFit(
|
||||
cNoise & a_Noise
|
||||
)
|
||||
{
|
||||
int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + a_ParentSystem.m_MineShafts.size(), a_PivotZ) / 7;
|
||||
int rnd = a_Noise.IntNoise3DInt(a_PivotX, a_PivotY + (int)a_ParentSystem.m_MineShafts.size(), a_PivotZ) / 7;
|
||||
cCuboid Box;
|
||||
switch (a_Direction)
|
||||
{
|
||||
@ -1287,6 +1283,7 @@ cStructGenMineShafts::cStructGenMineShafts(
|
||||
int a_Seed, int a_GridSize, int a_MaxSystemSize,
|
||||
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
|
||||
) :
|
||||
super(a_Seed, a_GridSize, a_GridSize, 120 + a_MaxSystemSize * 10, 120 + a_MaxSystemSize * 10, 100),
|
||||
m_Noise(a_Seed),
|
||||
m_GridSize(a_GridSize),
|
||||
m_MaxSystemSize(a_MaxSystemSize),
|
||||
@ -1300,125 +1297,9 @@ cStructGenMineShafts::cStructGenMineShafts(
|
||||
|
||||
|
||||
|
||||
cStructGenMineShafts::~cStructGenMineShafts()
|
||||
cGridStructGen::cStructurePtr cStructGenMineShafts::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||
{
|
||||
ClearCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenMineShafts::ClearCache(void)
|
||||
{
|
||||
for (cMineShaftSystems::const_iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
} // for itr - m_Cache[]
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenMineShafts::GetMineShaftSystemsForChunk(
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
cStructGenMineShafts::cMineShaftSystems & a_MineShafts
|
||||
)
|
||||
{
|
||||
int BaseX = a_ChunkX * cChunkDef::Width / m_GridSize;
|
||||
int BaseZ = a_ChunkZ * cChunkDef::Width / m_GridSize;
|
||||
if (BaseX < 0)
|
||||
{
|
||||
--BaseX;
|
||||
}
|
||||
if (BaseZ < 0)
|
||||
{
|
||||
--BaseZ;
|
||||
}
|
||||
BaseX -= NEIGHBORHOOD_SIZE / 2;
|
||||
BaseZ -= NEIGHBORHOOD_SIZE / 2;
|
||||
|
||||
// Walk the cache, move each cave system that we want into a_Mineshafts:
|
||||
int StartX = BaseX * m_GridSize;
|
||||
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
||||
int StartZ = BaseZ * m_GridSize;
|
||||
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
||||
for (cMineShaftSystems::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
|
||||
{
|
||||
if (
|
||||
((*itr)->m_BlockX >= StartX) && ((*itr)->m_BlockX < EndX) &&
|
||||
((*itr)->m_BlockZ >= StartZ) && ((*itr)->m_BlockZ < EndZ)
|
||||
)
|
||||
{
|
||||
// want
|
||||
a_MineShafts.push_back(*itr);
|
||||
itr = m_Cache.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't want
|
||||
++itr;
|
||||
}
|
||||
} // for itr - m_Cache[]
|
||||
|
||||
for (int x = 0; x < NEIGHBORHOOD_SIZE; x++)
|
||||
{
|
||||
int RealX = (BaseX + x) * m_GridSize;
|
||||
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
|
||||
{
|
||||
int RealZ = (BaseZ + z) * m_GridSize;
|
||||
bool Found = false;
|
||||
for (cMineShaftSystems::const_iterator itr = a_MineShafts.begin(), end = a_MineShafts.end(); itr != end; ++itr)
|
||||
{
|
||||
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
} // for itr - a_Mineshafts
|
||||
if (!Found)
|
||||
{
|
||||
a_MineShafts.push_back(new cMineShaftSystem(RealX, RealZ, m_GridSize, m_MaxSystemSize, m_Noise, m_ProbLevelCorridor, m_ProbLevelCrossing, m_ProbLevelStaircase));
|
||||
}
|
||||
} // for z
|
||||
} // for x
|
||||
|
||||
// Copy a_MineShafts into m_Cache to the beginning:
|
||||
cMineShaftSystems MineShaftsCopy(a_MineShafts);
|
||||
m_Cache.splice(m_Cache.begin(), MineShaftsCopy, MineShaftsCopy.begin(), MineShaftsCopy.end());
|
||||
|
||||
// Trim the cache if it's too long:
|
||||
if (m_Cache.size() > 100)
|
||||
{
|
||||
cMineShaftSystems::iterator itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
for (cMineShaftSystems::iterator end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
}
|
||||
itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
m_Cache.erase(itr, m_Cache.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenMineShafts::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
cMineShaftSystems MineShafts;
|
||||
GetMineShaftSystemsForChunk(ChunkX, ChunkZ, MineShafts);
|
||||
for (cMineShaftSystems::const_iterator itr = MineShafts.begin(); itr != MineShafts.end(); ++itr)
|
||||
{
|
||||
(*itr)->ProcessChunk(a_ChunkDesc);
|
||||
} // for itr - MineShafts[]
|
||||
return cStructurePtr(new cMineShaftSystem(a_OriginX, a_OriginZ, m_GridSize, m_MaxSystemSize, m_Noise, m_ProbLevelCorridor, m_ProbLevelCrossing, m_ProbLevelStaircase));
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ComposableGenerator.h"
|
||||
#include "GridStructGen.h"
|
||||
#include "../Noise.h"
|
||||
|
||||
|
||||
@ -17,16 +17,16 @@
|
||||
|
||||
|
||||
class cStructGenMineShafts :
|
||||
public cFinishGen
|
||||
public cGridStructGen
|
||||
{
|
||||
typedef cGridStructGen super;
|
||||
|
||||
public:
|
||||
cStructGenMineShafts(
|
||||
int a_Seed, int a_GridSize, int a_MaxSystemSize,
|
||||
int a_ChanceCorridor, int a_ChanceCrossing, int a_ChanceStaircase
|
||||
);
|
||||
|
||||
virtual ~cStructGenMineShafts();
|
||||
|
||||
protected:
|
||||
friend class cMineShaft;
|
||||
friend class cMineShaftDirtRoom;
|
||||
@ -34,26 +34,16 @@ protected:
|
||||
friend class cMineShaftCrossing;
|
||||
friend class cMineShaftStaircase;
|
||||
class cMineShaftSystem; // fwd: MineShafts.cpp
|
||||
typedef std::list<cMineShaftSystem *> cMineShaftSystems;
|
||||
|
||||
cNoise m_Noise;
|
||||
int m_GridSize; ///< Average spacing of the systems
|
||||
int m_MaxSystemSize; ///< Maximum blcok size of a mineshaft system
|
||||
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
||||
int m_ProbLevelCrossing; ///< Probability level of a branch object being the crossing, minus Corridor
|
||||
int m_ProbLevelStaircase; ///< Probability level of a branch object being the staircase, minus Crossing
|
||||
cMineShaftSystems m_Cache; ///< Cache of the most recently used systems. MoveToFront used.
|
||||
cNoise m_Noise;
|
||||
int m_GridSize; ///< Average spacing of the systems
|
||||
int m_MaxSystemSize; ///< Maximum blcok size of a mineshaft system
|
||||
int m_ProbLevelCorridor; ///< Probability level of a branch object being the corridor
|
||||
int m_ProbLevelCrossing; ///< Probability level of a branch object being the crossing, minus Corridor
|
||||
int m_ProbLevelStaircase; ///< Probability level of a branch object being the staircase, minus Crossing
|
||||
|
||||
/// Clears everything from the cache
|
||||
void ClearCache(void);
|
||||
|
||||
/** Returns all systems that *may* intersect the given chunk.
|
||||
All the systems are valid until the next call to this function (which may delete some of the pointers).
|
||||
*/
|
||||
void GetMineShaftSystemsForChunk(int a_ChunkX, int a_ChunkZ, cMineShaftSystems & a_MineShaftSystems);
|
||||
|
||||
// cFinishGen overrides:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
// cGridStructGen overrides:
|
||||
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -11,29 +11,24 @@
|
||||
|
||||
|
||||
|
||||
static const int NEIGHBORHOOD_SIZE = 3;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cNetherFortGen::cNetherFort:
|
||||
|
||||
class cNetherFortGen::cNetherFort
|
||||
class cNetherFortGen::cNetherFort :
|
||||
public cGridStructGen::cStructure
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
public:
|
||||
cNetherFortGen & m_ParentGen;
|
||||
int m_BlockX, m_BlockZ;
|
||||
int m_GridSize;
|
||||
int m_Seed;
|
||||
cPlacedPieces m_Pieces;
|
||||
|
||||
|
||||
cNetherFort(cNetherFortGen & a_ParentGen, int a_BlockX, int a_BlockZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
|
||||
cNetherFort(cNetherFortGen & a_ParentGen, int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
|
||||
super(a_OriginX, a_OriginZ),
|
||||
m_ParentGen(a_ParentGen),
|
||||
m_BlockX(a_BlockX),
|
||||
m_BlockZ(a_BlockZ),
|
||||
m_GridSize(a_GridSize),
|
||||
m_Seed(a_Seed)
|
||||
{
|
||||
@ -43,8 +38,8 @@ public:
|
||||
// Generate pieces:
|
||||
for (int i = 0; m_Pieces.size() < (size_t)(a_MaxDepth * a_MaxDepth / 8 + a_MaxDepth); i++)
|
||||
{
|
||||
cBFSPieceGenerator pg(m_ParentGen, a_Seed + i);
|
||||
pg.PlacePieces(a_BlockX, BlockY, a_BlockZ, a_MaxDepth, m_Pieces);
|
||||
cBFSPieceGenerator pg(cNetherFortGen::m_PiecePool, a_Seed + i);
|
||||
pg.PlacePieces(a_OriginX, BlockY, a_OriginZ, a_MaxDepth, m_Pieces);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +51,7 @@ public:
|
||||
|
||||
|
||||
/** Carves the system into the chunk data */
|
||||
void ProcessChunk(cChunkDesc & a_Chunk)
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_Chunk)
|
||||
{
|
||||
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
|
||||
{
|
||||
@ -107,214 +102,30 @@ public:
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cNetherFortGen:
|
||||
|
||||
cPrefabPiecePool cNetherFortGen::m_PiecePool(g_NetherFortPrefabs, g_NetherFortPrefabsCount, g_NetherFortStartingPrefabs, g_NetherFortStartingPrefabsCount);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cNetherFortGen::cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth) :
|
||||
m_Seed(a_Seed),
|
||||
m_Noise(a_Seed),
|
||||
m_GridSize(a_GridSize),
|
||||
super(a_Seed, a_GridSize, a_GridSize, a_MaxDepth * 10, a_MaxDepth * 10, 200),
|
||||
m_MaxDepth(a_MaxDepth)
|
||||
{
|
||||
// Initialize the prefabs:
|
||||
for (size_t i = 0; i < g_NetherFortPrefabsCount; i++)
|
||||
{
|
||||
cPrefab * Prefab = new cPrefab(g_NetherFortPrefabs[i]);
|
||||
m_AllPieces.push_back(Prefab);
|
||||
if (Prefab->HasConnectorType(0))
|
||||
{
|
||||
m_OuterPieces.push_back(Prefab);
|
||||
}
|
||||
if (Prefab->HasConnectorType(1))
|
||||
{
|
||||
m_InnerPieces.push_back(Prefab);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the starting piece prefabs:
|
||||
for (size_t i = 0; i < g_NetherFortStartingPrefabsCount; i++)
|
||||
{
|
||||
m_StartingPieces.push_back(new cPrefab(g_NetherFortStartingPrefabs[i]));
|
||||
}
|
||||
|
||||
/*
|
||||
// DEBUG: Try one round of placement:
|
||||
cPlacedPieces Pieces;
|
||||
cBFSPieceGenerator pg(*this, a_Seed);
|
||||
cBFSPieceGenerator pg(m_PiecePool, a_Seed);
|
||||
pg.PlacePieces(0, 64, 0, a_MaxDepth, Pieces);
|
||||
*/
|
||||
//*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cNetherFortGen::~cNetherFortGen()
|
||||
cGridStructGen::cStructurePtr cNetherFortGen::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||
{
|
||||
ClearCache();
|
||||
for (cPieces::iterator itr = m_AllPieces.begin(), end = m_AllPieces.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
} // for itr - m_AllPieces[]
|
||||
m_AllPieces.clear();
|
||||
return cStructurePtr(new cNetherFort(*this, a_OriginX, a_OriginZ, m_GridSizeX, m_MaxDepth, m_Seed));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNetherFortGen::ClearCache(void)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNetherFortGen::GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts)
|
||||
{
|
||||
int BaseX = a_ChunkX * cChunkDef::Width / m_GridSize;
|
||||
int BaseZ = a_ChunkZ * cChunkDef::Width / m_GridSize;
|
||||
if (BaseX < 0)
|
||||
{
|
||||
--BaseX;
|
||||
}
|
||||
if (BaseZ < 0)
|
||||
{
|
||||
--BaseZ;
|
||||
}
|
||||
BaseX -= NEIGHBORHOOD_SIZE / 2;
|
||||
BaseZ -= NEIGHBORHOOD_SIZE / 2;
|
||||
|
||||
// Walk the cache, move each cave system that we want into a_Forts:
|
||||
int StartX = BaseX * m_GridSize;
|
||||
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
||||
int StartZ = BaseZ * m_GridSize;
|
||||
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_GridSize;
|
||||
for (cNetherForts::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
|
||||
{
|
||||
if (
|
||||
((*itr)->m_BlockX >= StartX) && ((*itr)->m_BlockX < EndX) &&
|
||||
((*itr)->m_BlockZ >= StartZ) && ((*itr)->m_BlockZ < EndZ)
|
||||
)
|
||||
{
|
||||
// want
|
||||
a_Forts.push_back(*itr);
|
||||
itr = m_Cache.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't want
|
||||
++itr;
|
||||
}
|
||||
} // for itr - m_Cache[]
|
||||
|
||||
// Create those forts that haven't been in the cache:
|
||||
for (int x = 0; x < NEIGHBORHOOD_SIZE; x++)
|
||||
{
|
||||
int RealX = (BaseX + x) * m_GridSize;
|
||||
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
|
||||
{
|
||||
int RealZ = (BaseZ + z) * m_GridSize;
|
||||
bool Found = false;
|
||||
for (cNetherForts::const_iterator itr = a_Forts.begin(), end = a_Forts.end(); itr != end; ++itr)
|
||||
{
|
||||
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
} // for itr - a_Mineshafts
|
||||
if (!Found)
|
||||
{
|
||||
a_Forts.push_back(new cNetherFort(*this, RealX, RealZ, m_GridSize, m_MaxDepth, m_Seed));
|
||||
}
|
||||
} // for z
|
||||
} // for x
|
||||
|
||||
// Copy a_Forts into m_Cache to the beginning:
|
||||
cNetherForts FortsCopy (a_Forts);
|
||||
m_Cache.splice(m_Cache.begin(), FortsCopy, FortsCopy.begin(), FortsCopy.end());
|
||||
|
||||
// Trim the cache if it's too long:
|
||||
if (m_Cache.size() > 100)
|
||||
{
|
||||
cNetherForts::iterator itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
for (cNetherForts::iterator end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
}
|
||||
itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
m_Cache.erase(itr, m_Cache.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNetherFortGen::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
cNetherForts Forts;
|
||||
GetFortsForChunk(ChunkX, ChunkZ, Forts);
|
||||
for (cNetherForts::const_iterator itr = Forts.begin(); itr != Forts.end(); ++itr)
|
||||
{
|
||||
(*itr)->ProcessChunk(a_ChunkDesc);
|
||||
} // for itr - Forts[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPieces cNetherFortGen::GetPiecesWithConnector(int a_ConnectorType)
|
||||
{
|
||||
switch (a_ConnectorType)
|
||||
{
|
||||
case 0: return m_OuterPieces;
|
||||
case 1: return m_InnerPieces;
|
||||
default: return cPieces();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPieces cNetherFortGen::GetStartingPieces(void)
|
||||
{
|
||||
return m_StartingPieces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cNetherFortGen::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
|
||||
{
|
||||
return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNetherFortGen::PiecePlaced(const cPiece & a_Piece)
|
||||
{
|
||||
UNUSED(a_Piece);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNetherFortGen::Reset(void)
|
||||
{
|
||||
// Nothing needed
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -10,77 +10,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "ComposableGenerator.h"
|
||||
#include "PieceGenerator.h"
|
||||
#include "PrefabPiecePool.h"
|
||||
#include "GridStructGen.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cNetherFortGen :
|
||||
public cFinishGen,
|
||||
public cPiecePool
|
||||
public cGridStructGen
|
||||
{
|
||||
typedef cGridStructGen super;
|
||||
|
||||
public:
|
||||
cNetherFortGen(int a_Seed, int a_GridSize, int a_MaxDepth);
|
||||
|
||||
virtual ~cNetherFortGen();
|
||||
|
||||
protected:
|
||||
friend class cNetherFortPerfTest; // fwd: NetherFortGen.cpp
|
||||
class cNetherFort; // fwd: NetherFortGen.cpp
|
||||
typedef std::list<cNetherFort *> cNetherForts;
|
||||
|
||||
|
||||
/** The seed used for generating*/
|
||||
int m_Seed;
|
||||
|
||||
/** The noise used for generating */
|
||||
cNoise m_Noise;
|
||||
|
||||
/** Average spacing between the fortresses*/
|
||||
int m_GridSize;
|
||||
|
||||
/** Maximum depth of the piece-generator tree */
|
||||
int m_MaxDepth;
|
||||
|
||||
/** Cache of the most recently used systems. MoveToFront used. */
|
||||
cNetherForts m_Cache;
|
||||
|
||||
/** All the pieces that are allowed for building.
|
||||
This is the list that's used for memory allocation and deallocation for the pieces. */
|
||||
cPieces m_AllPieces;
|
||||
/** The pool of pieces to use for generating. Static, so that it's shared by multiple generators. */
|
||||
static cPrefabPiecePool m_PiecePool;
|
||||
|
||||
/** The pieces that are used as starting pieces.
|
||||
This list is not shared and the pieces need deallocation. */
|
||||
cPieces m_StartingPieces;
|
||||
|
||||
/** The pieces that have an "outer" connector.
|
||||
The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
|
||||
cPieces m_OuterPieces;
|
||||
|
||||
/** The pieces that have an "inner" connector.
|
||||
The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
|
||||
cPieces m_InnerPieces;
|
||||
|
||||
|
||||
/** Clears everything from the cache.
|
||||
Also invalidates the forst returned by GetFortsForChunk(). */
|
||||
void ClearCache(void);
|
||||
|
||||
/** Returns all forts that *may* intersect the given chunk.
|
||||
The returned forts live within m_Cache.They are valid until the next call
|
||||
to this function (which may delete some of the pointers). */
|
||||
void GetFortsForChunk(int a_ChunkX, int a_ChunkZ, cNetherForts & a_Forts);
|
||||
|
||||
// cFinishGen overrides:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
// cPiecePool overrides:
|
||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
|
||||
virtual cPieces GetStartingPieces(void) override;
|
||||
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) override;
|
||||
virtual void Reset(void) override;
|
||||
// cGridStructGen overrides:
|
||||
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -339,9 +339,9 @@ cPlacedPiece * cPieceGenerator::PlaceStartingPiece(int a_BlockX, int a_BlockY, i
|
||||
int NumRotations = 1;
|
||||
for (size_t i = 1; i < ARRAYCOUNT(Rotations); i++)
|
||||
{
|
||||
if (StartingPiece->CanRotateCCW(i))
|
||||
if (StartingPiece->CanRotateCCW((int)i))
|
||||
{
|
||||
Rotations[NumRotations] = i;
|
||||
Rotations[NumRotations] = (int)i;
|
||||
NumRotations += 1;
|
||||
}
|
||||
}
|
||||
@ -388,7 +388,8 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
||||
// Get a list of available connections:
|
||||
const int * RotTable = DirectionRotationTable[a_Connector.m_Direction];
|
||||
cConnections Connections;
|
||||
cPieces AvailablePieces = m_PiecePool.GetPiecesWithConnector(a_Connector.m_Type);
|
||||
int WantedConnectorType = -a_Connector.m_Type;
|
||||
cPieces AvailablePieces = m_PiecePool.GetPiecesWithConnector(WantedConnectorType);
|
||||
Connections.reserve(AvailablePieces.size());
|
||||
Vector3i ConnPos = a_Connector.m_Pos; // The position at which the new connector should be placed - 1 block away from the connector
|
||||
AddFaceDirection(ConnPos.x, ConnPos.y, ConnPos.z, a_Connector.m_Direction);
|
||||
@ -406,7 +407,7 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
||||
cPiece::cConnectors Connectors = (*itrP)->GetConnectors();
|
||||
for (cPiece::cConnectors::iterator itrC = Connectors.begin(), endC = Connectors.end(); itrC != endC; ++itrC)
|
||||
{
|
||||
if (itrC->m_Type != a_Connector.m_Type)
|
||||
if (itrC->m_Type != WantedConnectorType)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -38,7 +38,8 @@ public:
|
||||
/** Position relative to the piece */
|
||||
Vector3i m_Pos;
|
||||
|
||||
/** Type of the connector. Any arbitrary number; the generator connects only connectors of the same type. */
|
||||
/** Type of the connector. Any arbitrary number; the generator connects only connectors of opposite
|
||||
(negative) types. */
|
||||
int m_Type;
|
||||
|
||||
/** Direction in which the connector is facing.
|
||||
|
@ -174,44 +174,47 @@ void cPrefab::Draw(cChunkDesc & a_Dest, const cPlacedPiece * a_Placement) const
|
||||
a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
|
||||
|
||||
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)
|
||||
int MaxX = Image.GetSizeX();
|
||||
int MaxZ = Image.GetSizeZ();
|
||||
for (int z = 0; z < MaxZ; z++)
|
||||
if (m_ShouldExtendFloor)
|
||||
{
|
||||
int RelZ = Placement.z + z;
|
||||
if ((RelZ < 0) || (RelZ >= cChunkDef::Width))
|
||||
int MaxX = Image.GetSizeX();
|
||||
int MaxZ = Image.GetSizeZ();
|
||||
for (int z = 0; z < MaxZ; z++)
|
||||
{
|
||||
// Z coord outside the chunk
|
||||
continue;
|
||||
}
|
||||
for (int x = 0; x < MaxX; x++)
|
||||
{
|
||||
int RelX = Placement.x + x;
|
||||
if ((RelX < 0) || (RelX >= cChunkDef::Width))
|
||||
int RelZ = Placement.z + z;
|
||||
if ((RelZ < 0) || (RelZ >= cChunkDef::Width))
|
||||
{
|
||||
// X coord outside the chunk
|
||||
// Z coord outside the chunk
|
||||
continue;
|
||||
}
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta);
|
||||
if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE))
|
||||
for (int x = 0; x < MaxX; x++)
|
||||
{
|
||||
// Do not expand air nor sponge blocks
|
||||
continue;
|
||||
}
|
||||
for (int y = Placement.y - 1; y >= 0; y--)
|
||||
{
|
||||
BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ);
|
||||
if (ExistingBlock != E_BLOCK_AIR)
|
||||
int RelX = Placement.x + x;
|
||||
if ((RelX < 0) || (RelX >= cChunkDef::Width))
|
||||
{
|
||||
// End the expansion for this column, reached the end
|
||||
break;
|
||||
// X coord outside the chunk
|
||||
continue;
|
||||
}
|
||||
a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta);
|
||||
} // for y
|
||||
} // for x
|
||||
} // for z
|
||||
BLOCKTYPE BlockType;
|
||||
NIBBLETYPE BlockMeta;
|
||||
Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta);
|
||||
if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE))
|
||||
{
|
||||
// Do not expand air nor sponge blocks
|
||||
continue;
|
||||
}
|
||||
for (int y = Placement.y - 1; y >= 0; y--)
|
||||
{
|
||||
BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ);
|
||||
if (ExistingBlock != E_BLOCK_AIR)
|
||||
{
|
||||
// End the expansion for this column, reached the end
|
||||
break;
|
||||
}
|
||||
a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta);
|
||||
} // for y
|
||||
} // for x
|
||||
} // for z
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
121
src/Generating/PrefabPiecePool.cpp
Normal file
121
src/Generating/PrefabPiecePool.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
|
||||
// PrefabPiecePool.cpp
|
||||
|
||||
// Implements the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces
|
||||
|
||||
#include "Globals.h"
|
||||
#include "PrefabPiecePool.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPrefabPiecePool::cPrefabPiecePool(
|
||||
const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
|
||||
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
|
||||
)
|
||||
{
|
||||
AddPieceDefs(a_PieceDefs, a_NumPieceDefs);
|
||||
if (a_StartingPieceDefs != NULL)
|
||||
{
|
||||
AddStartingPieceDefs(a_StartingPieceDefs, a_NumStartingPieceDefs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefabPiecePool::AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs)
|
||||
{
|
||||
ASSERT(a_PieceDefs != NULL);
|
||||
for (size_t i = 0; i < a_NumPieceDefs; i++)
|
||||
{
|
||||
cPrefab * Prefab = new cPrefab(a_PieceDefs[i]);
|
||||
m_AllPieces.push_back(Prefab);
|
||||
AddToPerConnectorMap(Prefab);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefabPiecePool::AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs)
|
||||
{
|
||||
ASSERT(a_StartingPieceDefs != NULL);
|
||||
for (size_t i = 0; i < a_NumStartingPieceDefs; i++)
|
||||
{
|
||||
cPrefab * Prefab = new cPrefab(a_StartingPieceDefs[i]);
|
||||
m_StartingPieces.push_back(Prefab);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefabPiecePool::AddToPerConnectorMap(cPrefab * a_Prefab)
|
||||
{
|
||||
cPiece::cConnectors Connectors = ((const cPiece *)a_Prefab)->GetConnectors();
|
||||
for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
|
||||
{
|
||||
m_PiecesByConnector[itr->m_Type].push_back(a_Prefab);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
cPieces cPrefabPiecePool::GetPiecesWithConnector(int a_ConnectorType)
|
||||
{
|
||||
return m_PiecesByConnector[a_ConnectorType];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPieces cPrefabPiecePool::GetStartingPieces(void)
|
||||
{
|
||||
if (m_StartingPieces.empty())
|
||||
{
|
||||
return m_AllPieces;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_StartingPieces;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cPrefabPiecePool::GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece)
|
||||
{
|
||||
return ((const cPrefab &)a_NewPiece).GetPieceWeight(a_PlacedPiece, a_ExistingConnector);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefabPiecePool::PiecePlaced(const cPiece & a_Piece)
|
||||
{
|
||||
// Do nothing
|
||||
UNUSED(a_Piece);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPrefabPiecePool::Reset(void)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
79
src/Generating/PrefabPiecePool.h
Normal file
79
src/Generating/PrefabPiecePool.h
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
// PrefabPiecePool.h
|
||||
|
||||
// Declares the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PieceGenerator.h"
|
||||
#include "Prefab.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cPrefabPiecePool :
|
||||
public cPiecePool
|
||||
{
|
||||
public:
|
||||
/** Creates an empty instance. Prefabs can be added by calling AddPieceDefs() and AddStartingPieceDefs(). */
|
||||
cPrefabPiecePool(void);
|
||||
|
||||
/** Creates a piece pool with prefabs from the specified definitions.
|
||||
If both a_PieceDefs and a_StartingPieceDefs are given, only the a_StartingPieceDefs are used as starting
|
||||
pieces for the pool, and they do not participate in the generation any further.
|
||||
If only a_PieceDefs is given, any such piece can be chosen as a starting piece, and all the pieces are used
|
||||
for generating.
|
||||
More pieces can be added to the instance afterwards by calling AddPieceDefs() and AddStartingPieceDefs(). */
|
||||
cPrefabPiecePool(
|
||||
const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs,
|
||||
const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs
|
||||
);
|
||||
|
||||
/** Adds pieces from the specified definitions into m_AllPieces. Also adds the pieces into
|
||||
the m_PiecesByConnector map.
|
||||
May be called multiple times with different PieceDefs, will add all such pieces. */
|
||||
void AddPieceDefs(const cPrefab::sDef * a_PieceDefs, size_t a_NumPieceDefs);
|
||||
|
||||
/** Adds pieces from the specified definitions into m_StartingPieces. Doesn't add them to
|
||||
the m_PiecesByConnector map.
|
||||
May be called multiple times with different PieceDefs, will add all such pieces. */
|
||||
void AddStartingPieceDefs(const cPrefab::sDef * a_StartingPieceDefs, size_t a_NumStartingPieceDefs);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** The type used to map a connector type to the list of pieces with that connector */
|
||||
typedef std::map<int, cPieces> cPiecesMap;
|
||||
|
||||
/** All the pieces that are allowed for building.
|
||||
This is the list that's used for memory allocation and deallocation for the pieces. */
|
||||
cPieces m_AllPieces;
|
||||
|
||||
/** The pieces that are used as starting pieces.
|
||||
This list is not shared and the pieces need deallocation. */
|
||||
cPieces m_StartingPieces;
|
||||
|
||||
/** The map that has all pieces by their connector types
|
||||
The pieces are copies out of m_AllPieces and shouldn't be ever delete-d. */
|
||||
cPiecesMap m_PiecesByConnector;
|
||||
|
||||
|
||||
/** Adds the prefab to the m_PiecesByConnector map for all its connectors. */
|
||||
void AddToPerConnectorMap(cPrefab * a_Prefab);
|
||||
|
||||
// cPiecePool overrides:
|
||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
|
||||
virtual cPieces GetStartingPieces(void) override;
|
||||
virtual int GetPieceWeight(const cPlacedPiece & a_PlacedPiece, const cPiece::cConnector & a_ExistingConnector, const cPiece & a_NewPiece) override;
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) override;
|
||||
virtual void Reset(void) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
@ -134,7 +134,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 12, 2, 2: 5\n" /* Type 1, direction X+ */
|
||||
"1: 0, 2, 2: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 2, 2: 4\n" /* Type 1, direction X- */
|
||||
"-1: 12, 2, 2: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 0, 2, 2: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -143,7 +145,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
20,
|
||||
@ -291,7 +293,10 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
// Connectors:
|
||||
"1: 12, 2, 4: 5\n" /* Type 1, direction X+ */
|
||||
"1: 6, 2, 0: 2\n" /* Type 1, direction Z- */
|
||||
"1: 0, 2, 4: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 2, 4: 4\n" /* Type 1, direction X- */
|
||||
"-1: 12, 2, 4: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 6, 2, 0: 2\n" /* Type -1, direction Z- */
|
||||
"-1: 0, 2, 4: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -300,7 +305,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
20,
|
||||
@ -420,7 +425,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -590,7 +595,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -790,7 +795,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
5,
|
||||
@ -991,7 +996,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
10,
|
||||
@ -1085,7 +1090,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -1185,7 +1190,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -1208,7 +1213,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Hitbox (relative to bounding box):
|
||||
0, 0, 0, // MinX, MinY, MinZ
|
||||
4, 6, 15, // MaxX, MaxY, MaxZ
|
||||
4, 16, 15, // MaxX, MaxY, MaxZ
|
||||
|
||||
// Block definitions:
|
||||
".: 0: 0\n" /* air */
|
||||
@ -1364,7 +1369,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
10,
|
||||
@ -1604,7 +1609,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
5,
|
||||
@ -1933,7 +1938,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
20,
|
||||
@ -2052,7 +2057,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
500,
|
||||
@ -2212,7 +2217,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
10,
|
||||
@ -2302,7 +2307,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 10, 1, 2: 5\n" /* Type 1, direction X+ */
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"-1: 10, 1, 2: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -2311,7 +2318,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
300,
|
||||
@ -2401,7 +2408,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 12, 1, 2: 5\n" /* Type 1, direction X+ */
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"-1: 12, 1, 2: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -2410,7 +2419,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
300,
|
||||
@ -2494,7 +2503,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 4, 1, 2: 5\n" /* Type 1, direction X+ */
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"-1: 4, 1, 2: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -2503,7 +2514,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
500,
|
||||
@ -2631,7 +2642,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 2, 1, 10: 3\n" /* Type 1, direction Z+ */
|
||||
"1: 10, 1, 2: 5\n" /* Type 1, direction X+ */,
|
||||
"1: 10, 1, 2: 5\n" /* Type 1, direction X+ */
|
||||
"-1: 2, 1, 10: 3\n" /* Type -1, direction Z+ */
|
||||
"-1: 10, 1, 2: 5\n" /* Type -1, direction X+ */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -2640,7 +2653,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -2769,7 +2782,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 10, 1, 2: 5\n" /* Type 1, direction X+ */
|
||||
"1: 2, 1, 10: 3\n" /* Type 1, direction Z+ */,
|
||||
"1: 2, 1, 10: 3\n" /* Type 1, direction Z+ */
|
||||
"-1: 2, 1, 10: 3\n" /* Type -1, direction Z+ */
|
||||
"-1: 10, 1, 2: 5\n" /* Type -1, direction X+ */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -2778,7 +2793,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -2890,7 +2905,11 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
"1: 8, 1, 4: 5\n" /* Type 1, direction X+ */
|
||||
"1: 4, 1, 0: 2\n" /* Type 1, direction Z- */
|
||||
"1: 4, 1, 8: 3\n" /* Type 1, direction Z+ */
|
||||
"1: 0, 1, 4: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 1, 4: 4\n" /* Type 1, direction X- */
|
||||
"-1: 8, 1, 4: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 4, 1, 8: 3\n" /* Type -1, direction Z+ */
|
||||
"-1: 0, 1, 4: 4\n" /* Type -1, direction X- */
|
||||
"-1: 4, 1, 0: 2\n" /* Type -1, direction Z- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -2899,7 +2918,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -3040,7 +3059,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"1: 8, 8, 2: 5\n" /* Type 1, direction X+ */,
|
||||
"1: 8, 8, 2: 5\n" /* Type 1, direction X+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */
|
||||
"-1: 8, 8, 2: 5\n" /* Type -1, direction X+ */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -3049,7 +3070,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
1000,
|
||||
@ -3139,7 +3160,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"1: 13, 1, 2: 5\n" /* Type 1, direction X+ */,
|
||||
"1: 13, 1, 2: 5\n" /* Type 1, direction X+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */
|
||||
"-1: 13, 1, 2: 5\n" /* Type -1, direction X+ */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -3148,7 +3171,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -3393,7 +3416,10 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
// Connectors:
|
||||
"1: 0, 6, 7: 4\n" /* Type 1, direction X- */
|
||||
"1: 9, 1, 14: 3\n" /* Type 1, direction Z+ */
|
||||
"1: 9, 1, 0: 2\n" /* Type 1, direction Z- */,
|
||||
"1: 9, 1, 0: 2\n" /* Type 1, direction Z- */
|
||||
"-1: 0, 6, 7: 4\n" /* Type -1, direction X- */
|
||||
"-1: 9, 1, 14: 3\n" /* Type -1, direction Z+ */
|
||||
"-1: 9, 1, 0: 2\n" /* Type -1, direction Z- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -3402,7 +3428,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
10,
|
||||
@ -3722,7 +3748,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 11, 1, 7: 5\n" /* Type 1, direction X+ */
|
||||
"1: 0, 9, 7: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 9, 7: 4\n" /* Type 1, direction X- */
|
||||
"-1: 11, 1, 7: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 0, 9, 7: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -3731,7 +3759,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
10,
|
||||
@ -4009,7 +4037,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
10,
|
||||
@ -4186,7 +4214,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 12, 1, 6: 5\n" /* Type 1, direction X+ */
|
||||
"1: 0, 1, 6: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 1, 6: 4\n" /* Type 1, direction X- */
|
||||
"-1: 12, 1, 6: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 0, 1, 6: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -4195,7 +4225,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -4338,7 +4368,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -4481,7 +4511,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -4586,7 +4616,10 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
// Connectors:
|
||||
"1: 0, 1, 4: 4\n" /* Type 1, direction X- */
|
||||
"1: 6, 1, 0: 2\n" /* Type 1, direction Z- */
|
||||
"1: 12, 1, 4: 5\n" /* Type 1, direction X+ */,
|
||||
"1: 12, 1, 4: 5\n" /* Type 1, direction X+ */
|
||||
"-1: 0, 1, 4: 4\n" /* Type -1, direction X- */
|
||||
"-1: 12, 1, 4: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 6, 1, 0: 2\n" /* Type -1, direction Z- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -4595,7 +4628,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -4712,7 +4745,10 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
// Connectors:
|
||||
"1: 0, 1, 6: 4\n" /* Type 1, direction X- */
|
||||
"1: 6, 1, 0: 2\n" /* Type 1, direction Z- */
|
||||
"1: 12, 1, 6: 5\n" /* Type 1, direction X+ */,
|
||||
"1: 12, 1, 6: 5\n" /* Type 1, direction X+ */
|
||||
"-1: 0, 1, 6: 4\n" /* Type -1, direction X- */
|
||||
"-1: 6, 1, 0: 2\n" /* Type -1, direction Z- */
|
||||
"-1: 12, 1, 6: 5\n" /* Type -1, direction X+ */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -4721,7 +4757,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -4806,7 +4842,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 2, 1, 4: 3\n" /* Type 1, direction Z+ */
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"-1: 2, 1, 4: 3\n" /* Type -1, direction Z+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -4815,7 +4853,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -4901,7 +4939,9 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"1: 2, 1, 4: 3\n" /* Type 1, direction Z+ */
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */,
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"-1: 2, 1, 4: 3\n" /* Type -1, direction Z+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -4910,7 +4950,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -4996,7 +5036,11 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
"1: 4, 1, 2: 5\n" /* Type 1, direction X+ */
|
||||
"1: 2, 1, 4: 3\n" /* Type 1, direction Z+ */
|
||||
"1: 0, 1, 2: 4\n" /* Type 1, direction X- */
|
||||
"1: 2, 1, 0: 2\n" /* Type 1, direction Z- */,
|
||||
"1: 2, 1, 0: 2\n" /* Type 1, direction Z- */
|
||||
"-1: 4, 1, 2: 5\n" /* Type -1, direction X+ */
|
||||
"-1: 2, 1, 4: 3\n" /* Type -1, direction Z+ */
|
||||
"-1: 0, 1, 2: 4\n" /* Type -1, direction X- */
|
||||
"-1: 2, 1, 0: 2\n" /* Type -1, direction Z- */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -5005,7 +5049,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -5120,7 +5164,7 @@ const cPrefab::sDef g_NetherFortPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
@ -5314,7 +5358,8 @@ const cPrefab::sDef g_NetherFortStartingPrefabs[] =
|
||||
|
||||
// Connectors:
|
||||
"0: 6, 1, 0: 2\n" /* Type 0, direction Z- */
|
||||
"1: 6, 1, 12: 3\n" /* Type 1, direction Z+ */,
|
||||
"1: 6, 1, 12: 3\n" /* Type 1, direction Z+ */
|
||||
"-1: 6, 1, 12: 3\n" /* Type -1, direction Z+ */,
|
||||
|
||||
// AllowedRotations:
|
||||
7, /* 1, 2, 3 CCW rotation allowed */
|
||||
@ -5323,7 +5368,7 @@ const cPrefab::sDef g_NetherFortStartingPrefabs[] =
|
||||
cBlockArea::msSpongePrint,
|
||||
|
||||
// ShouldExtendFloor:
|
||||
false,
|
||||
true,
|
||||
|
||||
// DefaultWeight:
|
||||
100,
|
||||
|
@ -9,9 +9,6 @@
|
||||
|
||||
|
||||
|
||||
/// How many ravines in each direction are generated for a given chunk. Must be an even number
|
||||
static const int NEIGHBORHOOD_SIZE = 8;
|
||||
|
||||
static const int NUM_RAVINE_POINTS = 4;
|
||||
|
||||
|
||||
@ -42,40 +39,38 @@ typedef std::vector<cRavDefPoint> cRavDefPoints;
|
||||
|
||||
|
||||
|
||||
class cStructGenRavines::cRavine
|
||||
class cStructGenRavines::cRavine :
|
||||
public cGridStructGen::cStructure
|
||||
{
|
||||
typedef cGridStructGen::cStructure super;
|
||||
|
||||
cRavDefPoints m_Points;
|
||||
|
||||
|
||||
/// Generates the shaping defpoints for the ravine, based on the ravine block coords and noise
|
||||
/** Generates the shaping defpoints for the ravine, based on the ravine block coords and noise */
|
||||
void GenerateBaseDefPoints(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise);
|
||||
|
||||
/// Refines (adds and smooths) defpoints from a_Src into a_Dst
|
||||
/** Refines (adds and smooths) defpoints from a_Src into a_Dst */
|
||||
void RefineDefPoints(const cRavDefPoints & a_Src, cRavDefPoints & a_Dst);
|
||||
|
||||
/// Does one round of smoothing, two passes of RefineDefPoints()
|
||||
/** Does one round of smoothing, two passes of RefineDefPoints() */
|
||||
void Smooth(void);
|
||||
|
||||
/// Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block
|
||||
/** Linearly interpolates the points so that the maximum distance between two neighbors is max 1 block */
|
||||
void FinishLinear(void);
|
||||
|
||||
public:
|
||||
// Coords for which the ravine was generated (not necessarily the center)
|
||||
int m_BlockX;
|
||||
int m_BlockZ;
|
||||
|
||||
cRavine(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise);
|
||||
|
||||
/// Carves the ravine into the chunk specified
|
||||
void ProcessChunk(
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
cChunkDef::BlockTypes & a_BlockTypes,
|
||||
cChunkDef::HeightMap & a_HeightMap
|
||||
);
|
||||
|
||||
#ifdef _DEBUG
|
||||
/// Exports itself as a SVG line definition
|
||||
AString ExportAsSVG(int a_Color, int a_OffsetX = 0, int a_OffsetZ = 0) const;
|
||||
#endif // _DEBUG
|
||||
|
||||
protected:
|
||||
// cGridStructGen::cStructure overrides:
|
||||
virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override;
|
||||
} ;
|
||||
|
||||
|
||||
@ -86,6 +81,7 @@ public:
|
||||
// cStructGenRavines:
|
||||
|
||||
cStructGenRavines::cStructGenRavines(int a_Seed, int a_Size) :
|
||||
super(a_Seed, a_Size, a_Size, a_Size * 2, a_Size * 2, 100),
|
||||
m_Noise(a_Seed),
|
||||
m_Size(a_Size)
|
||||
{
|
||||
@ -95,139 +91,9 @@ cStructGenRavines::cStructGenRavines(int a_Seed, int a_Size) :
|
||||
|
||||
|
||||
|
||||
cStructGenRavines::~cStructGenRavines()
|
||||
cGridStructGen::cStructurePtr cStructGenRavines::CreateStructure(int a_OriginX, int a_OriginZ)
|
||||
{
|
||||
ClearCache();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenRavines::ClearCache(void)
|
||||
{
|
||||
for (cRavines::const_iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
} // for itr - m_Cache[]
|
||||
m_Cache.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenRavines::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
cRavines Ravines;
|
||||
GetRavinesForChunk(ChunkX, ChunkZ, Ravines);
|
||||
for (cRavines::const_iterator itr = Ravines.begin(), end = Ravines.end(); itr != end; ++itr)
|
||||
{
|
||||
(*itr)->ProcessChunk(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
|
||||
} // for itr - Ravines[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cStructGenRavines::GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cStructGenRavines::cRavines & a_Ravines)
|
||||
{
|
||||
int BaseX = a_ChunkX * cChunkDef::Width / m_Size;
|
||||
int BaseZ = a_ChunkZ * cChunkDef::Width / m_Size;
|
||||
if (BaseX < 0)
|
||||
{
|
||||
--BaseX;
|
||||
}
|
||||
if (BaseZ < 0)
|
||||
{
|
||||
--BaseZ;
|
||||
}
|
||||
BaseX -= 4;
|
||||
BaseZ -= 4;
|
||||
|
||||
// Walk the cache, move each ravine that we want into a_Ravines:
|
||||
int StartX = BaseX * m_Size;
|
||||
int EndX = (BaseX + NEIGHBORHOOD_SIZE + 1) * m_Size;
|
||||
int StartZ = BaseZ * m_Size;
|
||||
int EndZ = (BaseZ + NEIGHBORHOOD_SIZE + 1) * m_Size;
|
||||
for (cRavines::iterator itr = m_Cache.begin(), end = m_Cache.end(); itr != end;)
|
||||
{
|
||||
if (
|
||||
((*itr)->m_BlockX >= StartX) && ((*itr)->m_BlockX < EndX) &&
|
||||
((*itr)->m_BlockZ >= StartZ) && ((*itr)->m_BlockZ < EndZ)
|
||||
)
|
||||
{
|
||||
// want
|
||||
a_Ravines.push_back(*itr);
|
||||
itr = m_Cache.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't want
|
||||
++itr;
|
||||
}
|
||||
} // for itr - m_Cache[]
|
||||
|
||||
for (int x = 0; x < NEIGHBORHOOD_SIZE; x++)
|
||||
{
|
||||
int RealX = (BaseX + x) * m_Size;
|
||||
for (int z = 0; z < NEIGHBORHOOD_SIZE; z++)
|
||||
{
|
||||
int RealZ = (BaseZ + z) * m_Size;
|
||||
bool Found = false;
|
||||
for (cRavines::const_iterator itr = a_Ravines.begin(), end = a_Ravines.end(); itr != end; ++itr)
|
||||
{
|
||||
if (((*itr)->m_BlockX == RealX) && ((*itr)->m_BlockZ == RealZ))
|
||||
{
|
||||
Found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!Found)
|
||||
{
|
||||
a_Ravines.push_back(new cRavine(RealX, RealZ, m_Size, m_Noise));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy a_Ravines into m_Cache to the beginning:
|
||||
cRavines RavinesCopy(a_Ravines);
|
||||
m_Cache.splice(m_Cache.begin(), RavinesCopy, RavinesCopy.begin(), RavinesCopy.end());
|
||||
|
||||
// Trim the cache if it's too long:
|
||||
if (m_Cache.size() > 100)
|
||||
{
|
||||
cRavines::iterator itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
for (cRavines::iterator end = m_Cache.end(); itr != end; ++itr)
|
||||
{
|
||||
delete *itr;
|
||||
}
|
||||
itr = m_Cache.begin();
|
||||
std::advance(itr, 100);
|
||||
m_Cache.erase(itr, m_Cache.end());
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef _DEBUG
|
||||
// DEBUG: Export as SVG into a file specific for the chunk, for visual verification:
|
||||
AString SVG;
|
||||
SVG.append("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"1024\" height = \"1024\">\n");
|
||||
for (cRavines::const_iterator itr = a_Ravines.begin(), end = a_Ravines.end(); itr != end; ++itr)
|
||||
{
|
||||
SVG.append((*itr)->ExportAsSVG(0, 512, 512));
|
||||
}
|
||||
SVG.append("</svg>\n");
|
||||
|
||||
AString fnam;
|
||||
Printf(fnam, "ravines\\%03d_%03d.svg", a_ChunkX, a_ChunkZ);
|
||||
cFile File(fnam, cFile::fmWrite);
|
||||
File.Write(SVG.c_str(), SVG.size());
|
||||
#endif // _DEBUG
|
||||
//*/
|
||||
return cStructurePtr(new cRavine(a_OriginX, a_OriginZ, m_Size, m_Noise));
|
||||
}
|
||||
|
||||
|
||||
@ -238,14 +104,13 @@ void cStructGenRavines::GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cStructGe
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cStructGenRavines::cRavine
|
||||
|
||||
cStructGenRavines::cRavine::cRavine(int a_BlockX, int a_BlockZ, int a_Size, cNoise & a_Noise) :
|
||||
m_BlockX(a_BlockX),
|
||||
m_BlockZ(a_BlockZ)
|
||||
cStructGenRavines::cRavine::cRavine(int a_OriginX, int a_OriginZ, int a_Size, cNoise & a_Noise) :
|
||||
super(a_OriginX, a_OriginZ)
|
||||
{
|
||||
// Calculate the ravine shape-defining points:
|
||||
GenerateBaseDefPoints(a_BlockX, a_BlockZ, a_Size, a_Noise);
|
||||
GenerateBaseDefPoints(a_OriginX, a_OriginZ, a_Size, a_Noise);
|
||||
|
||||
// Smooth the ravine. A two passes are needed:
|
||||
// Smooth the ravine. Two passes are needed:
|
||||
Smooth();
|
||||
Smooth();
|
||||
|
||||
@ -263,8 +128,8 @@ void cStructGenRavines::cRavine::GenerateBaseDefPoints(int a_BlockX, int a_Block
|
||||
a_Size = (512 + ((a_Noise.IntNoise3DInt(19 * a_BlockX, 11 * a_BlockZ, a_BlockX + a_BlockZ) / 17) % 512)) * a_Size / 1024;
|
||||
|
||||
// The complete offset of the ravine from its cellpoint, up to 2 * a_Size in each direction
|
||||
int OffsetX = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 0) / 9) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * m_BlockZ, 1000) / 7) % (2 * a_Size)) - 2 * a_Size) / 2;
|
||||
int OffsetZ = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 2000) / 7) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * m_BlockZ, 3000) / 9) % (2 * a_Size)) - 2 * a_Size) / 2;
|
||||
int OffsetX = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 0) / 9) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 1000) / 7) % (2 * a_Size)) - 2 * a_Size) / 2;
|
||||
int OffsetZ = (((a_Noise.IntNoise3DInt(50 * a_BlockX, 30 * a_BlockZ, 2000) / 7) % (2 * a_Size)) + ((a_Noise.IntNoise3DInt(30 * a_BlockX, 50 * a_BlockZ, 3000) / 9) % (2 * a_Size)) - 2 * a_Size) / 2;
|
||||
int CenterX = a_BlockX + OffsetX;
|
||||
int CenterZ = a_BlockZ + OffsetZ;
|
||||
|
||||
@ -306,8 +171,14 @@ void cStructGenRavines::cRavine::GenerateBaseDefPoints(int a_BlockX, int a_Block
|
||||
|
||||
void cStructGenRavines::cRavine::RefineDefPoints(const cRavDefPoints & a_Src, cRavDefPoints & a_Dst)
|
||||
{
|
||||
if (a_Src.size() < 2)
|
||||
{
|
||||
// No midpoints, nothing to refine
|
||||
return;
|
||||
}
|
||||
|
||||
// Smoothing: for each line segment, add points on its 1/4 lengths
|
||||
int Num = a_Src.size() - 2; // this many intermediary points
|
||||
size_t Num = a_Src.size() - 2; // this many intermediary points
|
||||
a_Dst.clear();
|
||||
a_Dst.reserve(Num * 2 + 2);
|
||||
cRavDefPoints::const_iterator itr = a_Src.begin() + 1;
|
||||
@ -318,7 +189,7 @@ void cStructGenRavines::cRavine::RefineDefPoints(const cRavDefPoints & a_Src, cR
|
||||
int PrevR = Source.m_Radius;
|
||||
int PrevT = Source.m_Top;
|
||||
int PrevB = Source.m_Bottom;
|
||||
for (int i = 0; i <= Num; ++i, ++itr)
|
||||
for (size_t i = 0; i <= Num; ++i, ++itr)
|
||||
{
|
||||
int dx = itr->m_BlockX - PrevX;
|
||||
int dz = itr->m_BlockZ - PrevZ;
|
||||
@ -423,15 +294,15 @@ AString cStructGenRavines::cRavine::ExportAsSVG(int a_Color, int a_OffsetX, int
|
||||
|
||||
// Base point highlight:
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
||||
a_OffsetX + m_BlockX - 5, a_OffsetZ + m_BlockZ, a_OffsetX + m_BlockX + 5, a_OffsetZ + m_BlockZ
|
||||
a_OffsetX + m_OriginX - 5, a_OffsetZ + m_OriginZ, a_OffsetX + m_OriginX + 5, a_OffsetZ + m_OriginZ
|
||||
);
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#ff0000;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
||||
a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ - 5, a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ + 5
|
||||
a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ - 5, a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ + 5
|
||||
);
|
||||
|
||||
// A gray line from the base point to the first point of the ravine, for identification:
|
||||
AppendPrintf(SVG, "<path style=\"fill:none;stroke:#cfcfcf;stroke-width:1px;\"\nd=\"M %d,%d L %d,%d\"/>\n",
|
||||
a_OffsetX + m_BlockX, a_OffsetZ + m_BlockZ, a_OffsetX + m_Points.front().m_BlockX, a_OffsetZ + m_Points.front().m_BlockZ
|
||||
a_OffsetX + m_OriginX, a_OffsetZ + m_OriginZ, a_OffsetX + m_Points.front().m_BlockX, a_OffsetZ + m_Points.front().m_BlockZ
|
||||
);
|
||||
|
||||
// Offset guides:
|
||||
@ -455,14 +326,10 @@ AString cStructGenRavines::cRavine::ExportAsSVG(int a_Color, int a_OffsetX, int
|
||||
|
||||
|
||||
|
||||
void cStructGenRavines::cRavine::ProcessChunk(
|
||||
int a_ChunkX, int a_ChunkZ,
|
||||
cChunkDef::BlockTypes & a_BlockTypes,
|
||||
cChunkDef::HeightMap & a_HeightMap
|
||||
)
|
||||
void cStructGenRavines::cRavine::DrawIntoChunk(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int BlockStartX = a_ChunkX * cChunkDef::Width;
|
||||
int BlockStartZ = a_ChunkZ * cChunkDef::Width;
|
||||
int BlockStartX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||
int BlockStartZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
|
||||
int BlockEndX = BlockStartX + cChunkDef::Width;
|
||||
int BlockEndZ = BlockStartZ + cChunkDef::Width;
|
||||
for (cRavDefPoints::const_iterator itr = m_Points.begin(), end = m_Points.end(); itr != end; ++itr)
|
||||
@ -488,7 +355,7 @@ void cStructGenRavines::cRavine::ProcessChunk(
|
||||
// DEBUG: Make the ravine shapepoints visible on a single layer (so that we can see with Minutor what's going on)
|
||||
if ((DifX + x == 0) && (DifZ + z == 0))
|
||||
{
|
||||
cChunkDef::SetBlock(a_BlockTypes, x, 4, z, E_BLOCK_LAPIS_ORE);
|
||||
a_ChunkDesc.SetBlockType(x, 4, z, E_BLOCK_LAPIS_ORE);
|
||||
}
|
||||
#endif // _DEBUG
|
||||
|
||||
@ -498,7 +365,7 @@ void cStructGenRavines::cRavine::ProcessChunk(
|
||||
int Top = std::min(itr->m_Top, (int)(cChunkDef::Height)); // Stupid gcc needs int cast
|
||||
for (int y = std::max(itr->m_Bottom, 1); y <= Top; y++)
|
||||
{
|
||||
switch (cChunkDef::GetBlock(a_BlockTypes, x, y, z))
|
||||
switch (a_ChunkDesc.GetBlockType(x, y, z))
|
||||
{
|
||||
// Only carve out these specific block types
|
||||
case E_BLOCK_DIRT:
|
||||
@ -516,7 +383,7 @@ void cStructGenRavines::cRavine::ProcessChunk(
|
||||
case E_BLOCK_REDSTONE_ORE:
|
||||
case E_BLOCK_REDSTONE_ORE_GLOWING:
|
||||
{
|
||||
cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
|
||||
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ComposableGenerator.h"
|
||||
#include "GridStructGen.h"
|
||||
#include "../Noise.h"
|
||||
|
||||
|
||||
@ -17,28 +17,22 @@
|
||||
|
||||
|
||||
class cStructGenRavines :
|
||||
public cFinishGen
|
||||
public cGridStructGen
|
||||
{
|
||||
typedef cGridStructGen super;
|
||||
|
||||
public:
|
||||
cStructGenRavines(int a_Seed, int a_Size);
|
||||
~cStructGenRavines();
|
||||
|
||||
protected:
|
||||
class cRavine; // fwd: Ravines.cpp
|
||||
typedef std::list<cRavine *> cRavines;
|
||||
|
||||
cNoise m_Noise;
|
||||
int m_Size; // Max size, in blocks, of the ravines generated
|
||||
cRavines m_Cache;
|
||||
cNoise m_Noise;
|
||||
int m_Size; // Max size, in blocks, of the ravines generated
|
||||
|
||||
/// Clears everything from the cache
|
||||
void ClearCache(void);
|
||||
|
||||
/// Returns all ravines that *may* intersect the given chunk. All the ravines are valid until the next call to this function.
|
||||
void GetRavinesForChunk(int a_ChunkX, int a_ChunkZ, cRavines & a_Ravines);
|
||||
|
||||
// cFinishGen override:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
// cGridStructGen overrides:
|
||||
virtual cStructurePtr CreateStructure(int a_OriginX, int a_OriginZ) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -136,7 +136,7 @@ inline void PushSomeColumns(int a_BlockX, int a_Height, int a_BlockZ, int a_Colu
|
||||
{
|
||||
int x = a_BlockX + a_Coords[i].x;
|
||||
int z = a_BlockZ + a_Coords[i].z;
|
||||
if (a_Noise.IntNoise3DInt(x + 64 * a_Seq, a_Height + i, z + 64 * a_Seq) <= a_Chance)
|
||||
if (a_Noise.IntNoise3DInt(x + 64 * a_Seq, a_Height + (int)i, z + 64 * a_Seq) <= a_Chance)
|
||||
{
|
||||
for (int j = 0; j < a_ColumnHeight; j++)
|
||||
{
|
||||
|
@ -79,23 +79,24 @@ void cGroupManager::CheckUsers(void)
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int NumKeys = IniFile.GetNumKeys();
|
||||
for (size_t i = 0; i < NumKeys; i++)
|
||||
int NumKeys = IniFile.GetNumKeys();
|
||||
for (int i = 0; i < NumKeys; i++)
|
||||
{
|
||||
AString Player = IniFile.GetKeyName( i );
|
||||
AString Player = IniFile.GetKeyName(i);
|
||||
AString Groups = IniFile.GetValue(Player, "Groups", "");
|
||||
if (!Groups.empty())
|
||||
if (Groups.empty())
|
||||
{
|
||||
AStringVector Split = StringSplit( Groups, "," );
|
||||
for( unsigned int i = 0; i < Split.size(); i++ )
|
||||
{
|
||||
if (!ExistsGroup(Split[i]))
|
||||
{
|
||||
LOGWARNING("The group %s for player %s was not found!", Split[i].c_str(), Player.c_str());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
AStringVector Split = StringSplitAndTrim(Groups, ",");
|
||||
for (AStringVector::const_iterator itr = Split.begin(), end = Split.end(); itr != end; ++itr)
|
||||
{
|
||||
if (!ExistsGroup(*itr))
|
||||
{
|
||||
LOGWARNING("The group %s for player %s was not found!", Split[i].c_str(), Player.c_str());
|
||||
}
|
||||
} // for itr - Split[]
|
||||
} // for i - ini file keys
|
||||
}
|
||||
|
||||
|
||||
@ -128,15 +129,15 @@ void cGroupManager::LoadGroups()
|
||||
IniFile.WriteFile("groups.ini");
|
||||
}
|
||||
|
||||
unsigned int NumKeys = IniFile.GetNumKeys();
|
||||
for (size_t i = 0; i < NumKeys; i++)
|
||||
int NumKeys = IniFile.GetNumKeys();
|
||||
for (int i = 0; i < NumKeys; i++)
|
||||
{
|
||||
AString KeyName = IniFile.GetKeyName( i );
|
||||
cGroup* Group = GetGroup( KeyName.c_str() );
|
||||
AString KeyName = IniFile.GetKeyName(i);
|
||||
cGroup * Group = GetGroup(KeyName.c_str());
|
||||
|
||||
Group->ClearPermission(); // Needed in case the groups are reloaded.
|
||||
|
||||
LOGD("Loading group: %s", KeyName.c_str() );
|
||||
LOGD("Loading group %s", KeyName.c_str());
|
||||
|
||||
Group->SetName(KeyName);
|
||||
AString Color = IniFile.GetValue(KeyName, "Color", "-");
|
||||
|
@ -97,7 +97,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
|
||||
{
|
||||
ASSERT(m_State != psFinished); // Calling Parse() after Finish() is wrong!
|
||||
|
||||
int Last = 0;
|
||||
size_t Last = 0;
|
||||
for (size_t i = 0; i < a_Size;)
|
||||
{
|
||||
switch (m_State)
|
||||
|
@ -376,6 +376,7 @@ bool cInventory::DamageItem(int a_SlotNum, short a_Amount)
|
||||
if (!Grid->DamageItem(GridSlotNum, a_Amount))
|
||||
{
|
||||
// The item has been damaged, but did not break yet
|
||||
SendSlot(a_SlotNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -151,6 +151,8 @@ void cItem::GetJson(Json::Value & a_OutValue) const
|
||||
a_OutValue["Colours"] = m_FireworkItem.ColoursToString(m_FireworkItem);
|
||||
a_OutValue["FadeColours"] = m_FireworkItem.FadeColoursToString(m_FireworkItem);
|
||||
}
|
||||
|
||||
a_OutValue["RepairCost"] = m_RepairCost;
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +181,8 @@ void cItem::FromJson(const Json::Value & a_Value)
|
||||
m_FireworkItem.ColoursFromString(a_Value.get("Colours", "").asString(), m_FireworkItem);
|
||||
m_FireworkItem.FadeColoursFromString(a_Value.get("FadeColours", "").asString(), m_FireworkItem);
|
||||
}
|
||||
|
||||
m_RepairCost = a_Value.get("RepairCost", 0).asInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
20
src/Item.h
20
src/Item.h
@ -40,6 +40,7 @@ public:
|
||||
m_ItemDamage(0),
|
||||
m_CustomName(""),
|
||||
m_Lore(""),
|
||||
m_RepairCost(0),
|
||||
m_FireworkItem()
|
||||
{
|
||||
}
|
||||
@ -60,6 +61,7 @@ public:
|
||||
m_Enchantments(a_Enchantments),
|
||||
m_CustomName (a_CustomName),
|
||||
m_Lore (a_Lore),
|
||||
m_RepairCost (0),
|
||||
m_FireworkItem()
|
||||
{
|
||||
if (!IsValidItem(m_ItemType))
|
||||
@ -85,6 +87,7 @@ public:
|
||||
m_Enchantments(a_CopyFrom.m_Enchantments),
|
||||
m_CustomName (a_CopyFrom.m_CustomName),
|
||||
m_Lore (a_CopyFrom.m_Lore),
|
||||
m_RepairCost (a_CopyFrom.m_RepairCost),
|
||||
m_FireworkItem(a_CopyFrom.m_FireworkItem)
|
||||
{
|
||||
}
|
||||
@ -100,6 +103,7 @@ public:
|
||||
m_Enchantments.Clear();
|
||||
m_CustomName = "";
|
||||
m_Lore = "";
|
||||
m_RepairCost = 0;
|
||||
m_FireworkItem.EmptyData();
|
||||
}
|
||||
|
||||
@ -109,6 +113,7 @@ public:
|
||||
m_ItemType = E_ITEM_EMPTY;
|
||||
m_ItemCount = 0;
|
||||
m_ItemDamage = 0;
|
||||
m_RepairCost = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -190,14 +195,15 @@ public:
|
||||
|
||||
// tolua_begin
|
||||
|
||||
short m_ItemType;
|
||||
char m_ItemCount;
|
||||
short m_ItemDamage;
|
||||
cEnchantments m_Enchantments;
|
||||
AString m_CustomName;
|
||||
AString m_Lore;
|
||||
short m_ItemType;
|
||||
char m_ItemCount;
|
||||
short m_ItemDamage;
|
||||
cEnchantments m_Enchantments;
|
||||
AString m_CustomName;
|
||||
AString m_Lore;
|
||||
|
||||
cFireworkItem m_FireworkItem;
|
||||
int m_RepairCost;
|
||||
cFireworkItem m_FireworkItem;
|
||||
};
|
||||
// tolua_end
|
||||
|
||||
|
@ -60,6 +60,49 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
|
||||
{
|
||||
switch (m_ItemType)
|
||||
{
|
||||
case E_ITEM_CHAIN_BOOTS:
|
||||
case E_ITEM_CHAIN_CHESTPLATE:
|
||||
case E_ITEM_CHAIN_HELMET:
|
||||
case E_ITEM_CHAIN_LEGGINGS:
|
||||
{
|
||||
return (a_ItemType == E_ITEM_IRON);
|
||||
}
|
||||
case E_ITEM_DIAMOND_BOOTS:
|
||||
case E_ITEM_DIAMOND_CHESTPLATE:
|
||||
case E_ITEM_DIAMOND_HELMET:
|
||||
case E_ITEM_DIAMOND_LEGGINGS:
|
||||
{
|
||||
return (a_ItemType == E_ITEM_DIAMOND);
|
||||
}
|
||||
case E_ITEM_IRON_BOOTS:
|
||||
case E_ITEM_IRON_CHESTPLATE:
|
||||
case E_ITEM_IRON_HELMET:
|
||||
case E_ITEM_IRON_LEGGINGS:
|
||||
{
|
||||
return (a_ItemType == E_ITEM_IRON);
|
||||
}
|
||||
case E_ITEM_GOLD_BOOTS:
|
||||
case E_ITEM_GOLD_CHESTPLATE:
|
||||
case E_ITEM_GOLD_HELMET:
|
||||
case E_ITEM_GOLD_LEGGINGS:
|
||||
{
|
||||
return (a_ItemType == E_ITEM_GOLD);
|
||||
}
|
||||
case E_ITEM_LEATHER_BOOTS:
|
||||
case E_ITEM_LEATHER_CAP:
|
||||
case E_ITEM_LEATHER_PANTS:
|
||||
case E_ITEM_LEATHER_TUNIC:
|
||||
{
|
||||
return (a_ItemType == E_ITEM_LEATHER);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -511,6 +511,16 @@ bool cItemHandler::IsPlaceable(void)
|
||||
|
||||
|
||||
|
||||
|
||||
bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
|
||||
{
|
||||
UNUSED(a_BlockType);
|
||||
|
@ -85,6 +85,9 @@ public:
|
||||
/** Blocks simply get placed */
|
||||
virtual bool IsPlaceable(void);
|
||||
|
||||
/** Can the anvil repair this item, when a_Item is the second input? */
|
||||
virtual bool CanRepairWithRawMaterial(short a_ItemType);
|
||||
|
||||
/** Called before a block is placed into a world.
|
||||
The handler should return true to allow placement, false to refuse.
|
||||
Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block.
|
||||
|
@ -47,9 +47,9 @@ public:
|
||||
public cBlockTracer::cCallbacks
|
||||
{
|
||||
public:
|
||||
cCallbacks(cWorld * a_CBWorld) :
|
||||
m_HasHitFluid(false),
|
||||
m_World(a_CBWorld)
|
||||
|
||||
cCallbacks(void) :
|
||||
m_HasHitFluid(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -62,10 +62,9 @@ public:
|
||||
return false;
|
||||
}
|
||||
AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, BLOCK_FACE_YP); // Always place pad at top of water block
|
||||
BLOCKTYPE Block = m_World->GetBlock(a_CBBlockX, a_CBBlockY, a_CBBlockZ);
|
||||
if (
|
||||
!IsBlockWater(Block) &&
|
||||
cBlockInfo::FullyOccupiesVoxel(Block)
|
||||
!IsBlockWater(a_CBBlockType) &&
|
||||
cBlockInfo::FullyOccupiesVoxel(a_CBBlockType)
|
||||
)
|
||||
{
|
||||
// Can't place lilypad on air/in another block!
|
||||
@ -80,11 +79,10 @@ public:
|
||||
|
||||
Vector3i m_Pos;
|
||||
bool m_HasHitFluid;
|
||||
cWorld * m_World;
|
||||
|
||||
};
|
||||
|
||||
cCallbacks Callbacks(a_World);
|
||||
cCallbacks Callbacks;
|
||||
cLineBlockTracer Tracer(*a_Player->GetWorld(), Callbacks);
|
||||
Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
|
||||
Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -76,6 +76,7 @@ public:
|
||||
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||
case E_BLOCK_BRICK:
|
||||
case E_BLOCK_COBBLESTONE_STAIRS:
|
||||
case E_BLOCK_COBBLESTONE_WALL:
|
||||
case E_BLOCK_STONE_BRICK_STAIRS:
|
||||
case E_BLOCK_NETHER_BRICK_STAIRS:
|
||||
case E_BLOCK_CAULDRON:
|
||||
@ -85,6 +86,19 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
|
||||
{
|
||||
switch (m_ItemType)
|
||||
{
|
||||
case E_ITEM_WOODEN_PICKAXE: return (a_ItemType == E_BLOCK_PLANKS);
|
||||
case E_ITEM_STONE_PICKAXE: return (a_ItemType == E_BLOCK_COBBLESTONE);
|
||||
case E_ITEM_IRON_PICKAXE: return (a_ItemType == E_ITEM_IRON);
|
||||
case E_ITEM_GOLD_PICKAXE: return (a_ItemType == E_ITEM_GOLD);
|
||||
case E_ITEM_DIAMOND_PICKAXE: return (a_ItemType == E_ITEM_DIAMOND);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -41,4 +41,18 @@ public:
|
||||
{
|
||||
return (a_BlockType == E_BLOCK_SNOW);
|
||||
}
|
||||
|
||||
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
|
||||
{
|
||||
switch (m_ItemType)
|
||||
{
|
||||
case E_ITEM_WOODEN_SHOVEL: return (a_ItemType == E_BLOCK_PLANKS);
|
||||
case E_ITEM_STONE_SHOVEL: return (a_ItemType == E_BLOCK_COBBLESTONE);
|
||||
case E_ITEM_IRON_SHOVEL: return (a_ItemType == E_ITEM_IRON);
|
||||
case E_ITEM_GOLD_SHOVEL: return (a_ItemType == E_ITEM_GOLD);
|
||||
case E_ITEM_DIAMOND_SHOVEL: return (a_ItemType == E_ITEM_DIAMOND);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -33,7 +33,10 @@ public:
|
||||
a_BlockY--;
|
||||
}
|
||||
|
||||
if (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, (cMonster::eType)(a_Item.m_ItemDamage)) >= 0)
|
||||
cMonster::eType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage);
|
||||
if (
|
||||
(MonsterType != cMonster::mtInvalidType) && // Valid monster type
|
||||
(a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) >= 0)) // Spawning succeeded
|
||||
{
|
||||
if (!a_Player->IsGameModeCreative())
|
||||
{
|
||||
@ -45,6 +48,41 @@ public:
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** Converts the Spawn egg item damage to the monster type to spawn.
|
||||
Returns mtInvalidType for invalid damage values. */
|
||||
static cMonster::eType ItemDamageToMonsterType(short a_ItemDamage)
|
||||
{
|
||||
switch (a_ItemDamage)
|
||||
{
|
||||
case E_META_SPAWN_EGG_BAT: return cMonster::mtBat;
|
||||
case E_META_SPAWN_EGG_BLAZE: return cMonster::mtBlaze;
|
||||
case E_META_SPAWN_EGG_CAVE_SPIDER: return cMonster::mtCaveSpider;
|
||||
case E_META_SPAWN_EGG_CHICKEN: return cMonster::mtChicken;
|
||||
case E_META_SPAWN_EGG_COW: return cMonster::mtCow;
|
||||
case E_META_SPAWN_EGG_CREEPER: return cMonster::mtCreeper;
|
||||
case E_META_SPAWN_EGG_ENDERMAN: return cMonster::mtEnderman;
|
||||
case E_META_SPAWN_EGG_GHAST: return cMonster::mtGhast;
|
||||
case E_META_SPAWN_EGG_HORSE: return cMonster::mtHorse;
|
||||
case E_META_SPAWN_EGG_MAGMA_CUBE: return cMonster::mtMagmaCube;
|
||||
case E_META_SPAWN_EGG_MOOSHROOM: return cMonster::mtMooshroom;
|
||||
case E_META_SPAWN_EGG_OCELOT: return cMonster::mtOcelot;
|
||||
case E_META_SPAWN_EGG_PIG: return cMonster::mtPig;
|
||||
case E_META_SPAWN_EGG_SHEEP: return cMonster::mtSheep;
|
||||
case E_META_SPAWN_EGG_SILVERFISH: return cMonster::mtSilverfish;
|
||||
case E_META_SPAWN_EGG_SKELETON: return cMonster::mtSkeleton;
|
||||
case E_META_SPAWN_EGG_SLIME: return cMonster::mtSlime;
|
||||
case E_META_SPAWN_EGG_SPIDER: return cMonster::mtSpider;
|
||||
case E_META_SPAWN_EGG_SQUID: return cMonster::mtSquid;
|
||||
case E_META_SPAWN_EGG_VILLAGER: return cMonster::mtVillager;
|
||||
case E_META_SPAWN_EGG_WITCH: return cMonster::mtWitch;
|
||||
case E_META_SPAWN_EGG_WOLF: return cMonster::mtWolf;
|
||||
case E_META_SPAWN_EGG_ZOMBIE: return cMonster::mtZombie;
|
||||
case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return cMonster::mtZombiePigman;
|
||||
}
|
||||
return cMonster::mtInvalidType;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -23,6 +23,19 @@ public:
|
||||
{
|
||||
return (a_BlockType == E_BLOCK_COBWEB);
|
||||
}
|
||||
|
||||
virtual bool CanRepairWithRawMaterial(short a_ItemType) override
|
||||
{
|
||||
switch (m_ItemType)
|
||||
{
|
||||
case E_ITEM_WOODEN_SWORD: return (a_ItemType == E_BLOCK_PLANKS);
|
||||
case E_ITEM_STONE_SWORD: return (a_ItemType == E_BLOCK_COBBLESTONE);
|
||||
case E_ITEM_IRON_SWORD: return (a_ItemType == E_ITEM_IRON);
|
||||
case E_ITEM_GOLD_SWORD: return (a_ItemType == E_ITEM_GOLD);
|
||||
case E_ITEM_DIAMOND_SWORD: return (a_ItemType == E_ITEM_DIAMOND);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -28,15 +28,19 @@ public:
|
||||
|
||||
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
|
||||
{
|
||||
Vector3d Pos = a_Player->GetThrowStartPos();
|
||||
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
|
||||
|
||||
if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!a_Player->IsGameModeCreative())
|
||||
{
|
||||
a_Player->GetInventory().RemoveOneEquippedItem();
|
||||
}
|
||||
|
||||
Vector3d Pos = a_Player->GetThrowStartPos();
|
||||
Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
|
||||
a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -127,7 +131,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem());
|
||||
if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem()) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!a_Player->IsGameModeCreative())
|
||||
{
|
||||
|
@ -106,11 +106,13 @@ void cLightingThread::Stop(void)
|
||||
cCSLock Lock(m_CS);
|
||||
for (cChunkStays::iterator itr = m_PendingQueue.begin(), end = m_PendingQueue.end(); itr != end; ++itr)
|
||||
{
|
||||
(*itr)->Disable();
|
||||
delete *itr;
|
||||
}
|
||||
m_PendingQueue.clear();
|
||||
for (cChunkStays::iterator itr = m_Queue.begin(), end = m_Queue.end(); itr != end; ++itr)
|
||||
{
|
||||
(*itr)->Disable();
|
||||
delete *itr;
|
||||
}
|
||||
m_Queue.clear();
|
||||
|
@ -614,7 +614,7 @@ unsigned int cMap::GetNumPixels(void) const
|
||||
|
||||
|
||||
|
||||
unsigned int cMap::GetNumDecorators(void) const
|
||||
size_t cMap::GetNumDecorators(void) const
|
||||
{
|
||||
return m_Decorators.size();
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ public:
|
||||
|
||||
// tolua_end
|
||||
|
||||
unsigned int GetNumDecorators(void) const;
|
||||
size_t GetNumDecorators(void) const;
|
||||
|
||||
const cColorList & GetData(void) const { return m_Data; }
|
||||
|
||||
|
@ -86,7 +86,7 @@ cMap * cMapManager::CreateMap(int a_CenterX, int a_CenterY, int a_Scale)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cMap Map(m_MapData.size(), a_CenterX, a_CenterY, m_World, a_Scale);
|
||||
cMap Map((unsigned)m_MapData.size(), a_CenterX, a_CenterY, m_World, a_Scale);
|
||||
|
||||
m_MapData.push_back(Map);
|
||||
|
||||
@ -97,7 +97,7 @@ cMap * cMapManager::CreateMap(int a_CenterX, int a_CenterY, int a_Scale)
|
||||
|
||||
|
||||
|
||||
unsigned int cMapManager::GetNumMaps(void) const
|
||||
size_t cMapManager::GetNumMaps(void) const
|
||||
{
|
||||
return m_MapData.size();
|
||||
}
|
||||
@ -151,7 +151,7 @@ void cMapManager::SaveMapData(void)
|
||||
|
||||
cIDCountSerializer IDSerializer(m_World->GetName());
|
||||
|
||||
IDSerializer.SetMapCount(m_MapData.size());
|
||||
IDSerializer.SetMapCount((unsigned)m_MapData.size());
|
||||
|
||||
if (!IDSerializer.Save())
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
*/
|
||||
bool ForEachMap(cMapCallback & a_Callback);
|
||||
|
||||
unsigned int GetNumMaps(void) const; // tolua_export
|
||||
size_t GetNumMaps(void) const; // tolua_export
|
||||
|
||||
/** Loads the map data from the disk */
|
||||
void LoadMapData(void);
|
||||
|
@ -64,7 +64,7 @@ void cMobCensus::CollectSpawnableChunk(cChunk & a_Chunk)
|
||||
|
||||
int cMobCensus::GetNumChunks(void)
|
||||
{
|
||||
return m_EligibleForSpawnChunks.size();
|
||||
return (int)m_EligibleForSpawnChunks.size();
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@ void cMobFamilyCollecter::CollectMob(cMonster & a_Monster)
|
||||
|
||||
int cMobFamilyCollecter::GetNumberOfCollectedMobs(cMonster::eFamily a_Family)
|
||||
{
|
||||
return m_Mobs[a_Family].size();
|
||||
return (int)m_Mobs[a_Family].size();
|
||||
}
|
||||
|
||||
|
||||
|
@ -104,13 +104,13 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome)
|
||||
}
|
||||
}
|
||||
|
||||
int allowedMobsSize = allowedMobs.size();
|
||||
size_t allowedMobsSize = allowedMobs.size();
|
||||
if (allowedMobsSize > 0)
|
||||
{
|
||||
std::set<cMonster::eType>::iterator itr = allowedMobs.begin();
|
||||
int iRandom = m_Random.NextInt(allowedMobsSize,a_Biome);
|
||||
int iRandom = m_Random.NextInt((int)allowedMobsSize, a_Biome);
|
||||
|
||||
for(int i = 0; i < iRandom; i++)
|
||||
for (int i = 0; i < iRandom; i++)
|
||||
{
|
||||
++itr;
|
||||
}
|
||||
|
@ -108,14 +108,13 @@ void cAggressiveMonster::Attack(float a_Dt)
|
||||
|
||||
bool cAggressiveMonster::IsMovingToTargetPosition()
|
||||
{
|
||||
static const float epsilon = 0.000000000001f;
|
||||
// Difference between destination x and target x is negligible (to 10^-12 precision)
|
||||
if (fabsf((float)m_FinalDestination.x - (float)m_Target->GetPosX()) < epsilon)
|
||||
if (fabsf((float)m_FinalDestination.x - (float)m_Target->GetPosX()) < std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Difference between destination z and target z is negligible (to 10^-12 precision)
|
||||
else if (fabsf((float)m_FinalDestination.z - (float)m_Target->GetPosZ()) > epsilon)
|
||||
else if (fabsf((float)m_FinalDestination.z - (float)m_Target->GetPosZ()) > std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -827,6 +827,10 @@ cMonster * cMonster::NewMonsterFromType(cMonster::eType a_MobType)
|
||||
switch (a_MobType)
|
||||
{
|
||||
case mtMagmaCube:
|
||||
{
|
||||
toReturn = new cMagmaCube(Random.NextInt(2) + 1);
|
||||
break;
|
||||
}
|
||||
case mtSlime:
|
||||
{
|
||||
toReturn = new cSlime(Random.NextInt(2) + 1);
|
||||
|
@ -814,7 +814,7 @@ void cPerlinNoise::SetSeed(int a_Seed)
|
||||
|
||||
void cPerlinNoise::AddOctave(float a_Frequency, float a_Amplitude)
|
||||
{
|
||||
m_Octaves.push_back(cOctave(m_Seed * (m_Octaves.size() + 4) * 4 + 1024, a_Frequency, a_Amplitude));
|
||||
m_Octaves.push_back(cOctave(m_Seed * ((int)m_Octaves.size() + 4) * 4 + 1024, a_Frequency, a_Amplitude));
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
fopen_s(&m_File, (FILE_IO_PREFIX + iFileName).c_str(), Mode);
|
||||
m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), Mode, _SH_DENYWR);
|
||||
#else
|
||||
m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), Mode);
|
||||
#endif // _WIN32
|
||||
@ -88,7 +88,7 @@ bool cFile::Open(const AString & iFileName, eMode iMode)
|
||||
// Simply re-open for read-writing, erasing existing contents:
|
||||
|
||||
#ifdef _WIN32
|
||||
fopen_s(&m_File, (FILE_IO_PREFIX + iFileName).c_str(), "wb+");
|
||||
m_File = _fsopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+", _SH_DENYWR);
|
||||
#else
|
||||
m_File = fopen((FILE_IO_PREFIX + iFileName).c_str(), "wb+");
|
||||
#endif // _WIN32
|
||||
|
@ -214,7 +214,7 @@ void cListenThread::Execute(void)
|
||||
timeval tv; // On Linux select() doesn't seem to wake up when socket is closed, so let's kinda busy-wait:
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
if (select(Highest + 1, &fdRead, NULL, NULL, &tv) == -1)
|
||||
if (select((int)Highest + 1, &fdRead, NULL, NULL, &tv) == -1)
|
||||
{
|
||||
LOG("select(R) call failed in cListenThread: \"%s\"", cSocket::GetLastErrorString().c_str());
|
||||
continue;
|
||||
|
@ -328,18 +328,18 @@ bool cSocket::ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Por
|
||||
|
||||
|
||||
|
||||
int cSocket::Receive(char * a_Buffer, unsigned int a_Length, unsigned int a_Flags)
|
||||
int cSocket::Receive(char * a_Buffer, size_t a_Length, unsigned int a_Flags)
|
||||
{
|
||||
return recv(m_Socket, a_Buffer, a_Length, a_Flags);
|
||||
return recv(m_Socket, a_Buffer, (int)a_Length, a_Flags);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cSocket::Send(const char * a_Buffer, unsigned int a_Length)
|
||||
int cSocket::Send(const char * a_Buffer, size_t a_Length)
|
||||
{
|
||||
return send(m_Socket, a_Buffer, a_Length, MSG_NOSIGNAL);
|
||||
return send(m_Socket, a_Buffer, (int)a_Length, MSG_NOSIGNAL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -110,8 +110,8 @@ public:
|
||||
/// Connects to the specified host or string IP address and port, using IPv4. Returns true if successful.
|
||||
bool ConnectIPv4(const AString & a_HostNameOrAddr, unsigned short a_Port);
|
||||
|
||||
int Receive(char * a_Buffer, unsigned int a_Length, unsigned int a_Flags);
|
||||
int Send (const char * a_Buffer, unsigned int a_Length);
|
||||
int Receive(char * a_Buffer, size_t a_Length, unsigned int a_Flags);
|
||||
int Send (const char * a_Buffer, size_t a_Length);
|
||||
|
||||
unsigned short GetPort(void) const; // Returns 0 on failure
|
||||
|
||||
|
@ -406,7 +406,7 @@ void cSocketThreads::cSocketThread::Execute(void)
|
||||
timeval Timeout;
|
||||
Timeout.tv_sec = 5;
|
||||
Timeout.tv_usec = 0;
|
||||
if (select(Highest + 1, &fdRead, &fdWrite, NULL, &Timeout) == -1)
|
||||
if (select((int)Highest + 1, &fdRead, &fdWrite, NULL, &Timeout) == -1)
|
||||
{
|
||||
LOG("select() call failed in cSocketThread: \"%s\"", cSocket::GetLastErrorString().c_str());
|
||||
continue;
|
||||
|
@ -118,7 +118,7 @@ int cProbabDistrib::MapValue(int a_OrigValue) const
|
||||
size_t Hi = m_Cumulative.size() - 1;
|
||||
while (Hi - Lo > 1)
|
||||
{
|
||||
int Mid = (Lo + Hi) / 2;
|
||||
size_t Mid = (Lo + Hi) / 2;
|
||||
int MidProbab = m_Cumulative[Mid].m_Probability;
|
||||
if (MidProbab < a_OrigValue)
|
||||
{
|
||||
|
@ -214,7 +214,7 @@ bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_S
|
||||
ReplaceString(ActualAddress, "%SERVERID%", a_ServerId);
|
||||
|
||||
AString Request;
|
||||
Request += "GET " + ActualAddress + " HTTP/1.1\r\n";
|
||||
Request += "GET " + ActualAddress + " HTTP/1.0\r\n";
|
||||
Request += "Host: " + m_Server + "\r\n";
|
||||
Request += "User-Agent: MCServer\r\n";
|
||||
Request += "Connection: close\r\n";
|
||||
|
@ -197,7 +197,7 @@ void cProtocol172::SendBlockChanges(int a_ChunkX, int a_ChunkZ, const sSetBlockV
|
||||
Pkt.WriteInt(a_ChunkX);
|
||||
Pkt.WriteInt(a_ChunkZ);
|
||||
Pkt.WriteShort((short)a_Changes.size());
|
||||
Pkt.WriteInt(a_Changes.size() * 4);
|
||||
Pkt.WriteInt((int)a_Changes.size() * 4);
|
||||
for (sSetBlockVector::const_iterator itr = a_Changes.begin(), end = a_Changes.end(); itr != end; ++itr)
|
||||
{
|
||||
unsigned int Coords = itr->y | (itr->z << 8) | (itr->x << 12);
|
||||
@ -532,7 +532,7 @@ void cProtocol172::SendExplosion(double a_BlockX, double a_BlockY, double a_Bloc
|
||||
Pkt.WriteFloat((float)a_BlockY);
|
||||
Pkt.WriteFloat((float)a_BlockZ);
|
||||
Pkt.WriteFloat((float)a_Radius);
|
||||
Pkt.WriteInt(a_BlocksAffected.size());
|
||||
Pkt.WriteInt((int)a_BlocksAffected.size());
|
||||
for (cVector3iArray::const_iterator itr = a_BlocksAffected.begin(), end = a_BlocksAffected.end(); itr != end; ++itr)
|
||||
{
|
||||
Pkt.WriteChar((char)itr->x);
|
||||
@ -698,7 +698,7 @@ void cProtocol172::SendMapDecorators(int a_ID, const cMapDecoratorList & a_Decor
|
||||
|
||||
cPacketizer Pkt(*this, 0x34);
|
||||
Pkt.WriteVarInt(a_ID);
|
||||
Pkt.WriteShort (1 + (3 * a_Decorators.size()));
|
||||
Pkt.WriteShort ((short)(1 + (3 * a_Decorators.size())));
|
||||
|
||||
Pkt.WriteByte(1);
|
||||
|
||||
@ -1174,7 +1174,7 @@ void cProtocol172::SendTabCompletionResults(const AStringVector & a_Results)
|
||||
ASSERT(m_State == 3); // In game mode?
|
||||
|
||||
cPacketizer Pkt(*this, 0x3a); // Tab-Complete packet
|
||||
Pkt.WriteVarInt(a_Results.size());
|
||||
Pkt.WriteVarInt((int)a_Results.size());
|
||||
|
||||
for (AStringVector::const_iterator itr = a_Results.begin(), end = a_Results.end(); itr != end; ++itr)
|
||||
{
|
||||
@ -1743,7 +1743,7 @@ void cProtocol172::HandlePacketLoginStart(cByteBuffer & a_ByteBuffer)
|
||||
cPacketizer Pkt(*this, 0x01);
|
||||
Pkt.WriteString(Server->GetServerID());
|
||||
const AString & PubKeyDer = Server->GetPublicKeyDER();
|
||||
Pkt.WriteShort(PubKeyDer.size());
|
||||
Pkt.WriteShort((short)PubKeyDer.size());
|
||||
Pkt.WriteBuf(PubKeyDer.data(), PubKeyDer.size());
|
||||
Pkt.WriteShort(4);
|
||||
Pkt.WriteInt((int)(intptr_t)this); // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :)
|
||||
@ -2138,7 +2138,7 @@ void cProtocol172::WritePacket(cByteBuffer & a_Packet)
|
||||
cCSLock Lock(m_CSPacket);
|
||||
AString Pkt;
|
||||
a_Packet.ReadAll(Pkt);
|
||||
WriteVarInt(Pkt.size());
|
||||
WriteVarInt((UInt32)Pkt.size());
|
||||
SendData(Pkt.data(), Pkt.size());
|
||||
Flush();
|
||||
}
|
||||
@ -2278,6 +2278,13 @@ void cProtocol172::ParseItemMetadata(cItem & a_Item, const AString & a_Metadata)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TAG_Int:
|
||||
{
|
||||
if (TagName == "RepairCost")
|
||||
{
|
||||
a_Item.m_RepairCost = NBT.GetInt(tag);
|
||||
}
|
||||
}
|
||||
default: LOGD("Unimplemented NBT data when parsing!"); break;
|
||||
}
|
||||
}
|
||||
@ -2396,7 +2403,7 @@ cProtocol172::cPacketizer::~cPacketizer()
|
||||
AString DataToSend;
|
||||
|
||||
// Send the packet length
|
||||
UInt32 PacketLen = m_Out.GetUsedSpace();
|
||||
UInt32 PacketLen = (UInt32)m_Out.GetUsedSpace();
|
||||
m_Protocol.m_OutPacketLenBuffer.WriteVarInt(PacketLen);
|
||||
m_Protocol.m_OutPacketLenBuffer.ReadAll(DataToSend);
|
||||
m_Protocol.SendData(DataToSend.data(), DataToSend.size());
|
||||
@ -2451,6 +2458,10 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
||||
|
||||
// Send the enchantments and custom names:
|
||||
cFastNBTWriter Writer;
|
||||
if (a_Item.m_RepairCost != 0)
|
||||
{
|
||||
Writer.AddInt("RepairCost", a_Item.m_RepairCost);
|
||||
}
|
||||
if (!a_Item.m_Enchantments.IsEmpty())
|
||||
{
|
||||
const char * TagName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
|
||||
@ -2489,7 +2500,7 @@ void cProtocol172::cPacketizer::WriteItem(const cItem & a_Item)
|
||||
Writer.Finish();
|
||||
AString Compressed;
|
||||
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
||||
WriteShort(Compressed.size());
|
||||
WriteShort((short)Compressed.size());
|
||||
WriteBuf(Compressed.data(), Compressed.size());
|
||||
}
|
||||
|
||||
@ -2559,7 +2570,7 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||
|
||||
AString Compressed;
|
||||
CompressStringGZIP(Writer.GetResult().data(), Writer.GetResult().size(), Compressed);
|
||||
WriteShort(Compressed.size());
|
||||
WriteShort((short)Compressed.size());
|
||||
WriteBuf(Compressed.data(), Compressed.size());
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ protected:
|
||||
bool m_IsEncrypted;
|
||||
|
||||
cAesCfb128Decryptor m_Decryptor;
|
||||
cAesCfb128Decryptor m_Encryptor;
|
||||
cAesCfb128Encryptor m_Encryptor;
|
||||
|
||||
/** The logfile where the comm is logged, when g_ShouldLogComm is true */
|
||||
cFile m_CommLogFile;
|
||||
|
@ -871,7 +871,7 @@ bool cProtocolRecognizer::TryRecognizeProtocol(void)
|
||||
// Not enough bytes for the packet length, keep waiting
|
||||
return false;
|
||||
}
|
||||
ReadSoFar -= m_Buffer.GetReadableSpace();
|
||||
ReadSoFar -= (UInt32)m_Buffer.GetReadableSpace();
|
||||
if (!m_Buffer.CanReadBytes(PacketLen))
|
||||
{
|
||||
// Not enough bytes for the packet, keep waiting
|
||||
@ -961,7 +961,7 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
|
||||
{
|
||||
return false;
|
||||
}
|
||||
NumBytesRead -= m_Buffer.GetReadableSpace();
|
||||
NumBytesRead -= (UInt32)m_Buffer.GetReadableSpace();
|
||||
switch (ProtocolVersion)
|
||||
{
|
||||
case PROTO_VERSION_1_7_2:
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
|
||||
virtual void Finished(void) override
|
||||
{
|
||||
m_Connection.SendResponse(m_RequestID, RCON_PACKET_RESPONSE, m_Buffer.size(), m_Buffer.c_str());
|
||||
m_Connection.SendResponse(m_RequestID, RCON_PACKET_RESPONSE, (int)m_Buffer.size(), m_Buffer.c_str());
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
14
src/Root.cpp
14
src/Root.cpp
@ -590,13 +590,13 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallbac
|
||||
{
|
||||
class cCallback : public cPlayerListCallback
|
||||
{
|
||||
unsigned m_BestRating;
|
||||
unsigned m_NameLength;
|
||||
size_t m_BestRating;
|
||||
size_t m_NameLength;
|
||||
const AString m_PlayerName;
|
||||
|
||||
virtual bool Item (cPlayer * a_pPlayer)
|
||||
{
|
||||
unsigned int Rating = RateCompareString (m_PlayerName, a_pPlayer->GetName());
|
||||
size_t Rating = RateCompareString (m_PlayerName, a_pPlayer->GetName());
|
||||
if ((Rating > 0) && (Rating >= m_BestRating))
|
||||
{
|
||||
m_BestMatch = a_pPlayer;
|
||||
@ -626,7 +626,7 @@ bool cRoot::FindAndDoWithPlayer(const AString & a_PlayerName, cPlayerListCallbac
|
||||
cPlayer * m_BestMatch;
|
||||
unsigned m_NumMatches;
|
||||
} Callback (a_PlayerName);
|
||||
ForEachPlayer( Callback );
|
||||
ForEachPlayer(Callback);
|
||||
|
||||
if (Callback.m_NumMatches == 1)
|
||||
{
|
||||
@ -763,8 +763,8 @@ void cRoot::LogChunkStats(cCommandOutputCallback & a_Output)
|
||||
{
|
||||
cWorld * World = itr->second;
|
||||
int NumInGenerator = World->GetGeneratorQueueLength();
|
||||
int NumInSaveQueue = World->GetStorageSaveQueueLength();
|
||||
int NumInLoadQueue = World->GetStorageLoadQueueLength();
|
||||
int NumInSaveQueue = (int)World->GetStorageSaveQueueLength();
|
||||
int NumInLoadQueue = (int)World->GetStorageLoadQueueLength();
|
||||
int NumValid = 0;
|
||||
int NumDirty = 0;
|
||||
int NumInLighting = 0;
|
||||
@ -784,8 +784,6 @@ void cRoot::LogChunkStats(cCommandOutputCallback & a_Output)
|
||||
a_Output.Out(" block lighting: " SIZE_T_FMT_PRECISION(6) " bytes (" SIZE_T_FMT_PRECISION(3) " KiB)", 2 * sizeof(cChunkDef::BlockNibbles), (2 * sizeof(cChunkDef::BlockNibbles) + 1023) / 1024);
|
||||
a_Output.Out(" heightmap: " SIZE_T_FMT_PRECISION(6) " bytes (" SIZE_T_FMT_PRECISION(3) " KiB)", sizeof(cChunkDef::HeightMap), (sizeof(cChunkDef::HeightMap) + 1023) / 1024);
|
||||
a_Output.Out(" biomemap: " SIZE_T_FMT_PRECISION(6) " bytes (" SIZE_T_FMT_PRECISION(3) " KiB)", sizeof(cChunkDef::BiomeMap), (sizeof(cChunkDef::BiomeMap) + 1023) / 1024);
|
||||
int Rest = sizeof(cChunk) - sizeof(cChunkDef::BlockTypes) - 3 * sizeof(cChunkDef::BlockNibbles) - sizeof(cChunkDef::HeightMap) - sizeof(cChunkDef::BiomeMap);
|
||||
a_Output.Out(" other: %6d bytes (%3d KiB)", Rest, (Rest + 1023) / 1024);
|
||||
SumNumValid += NumValid;
|
||||
SumNumDirty += NumDirty;
|
||||
SumNumInLighting += NumInLighting;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user