Merge branch 'master' into MobSpawner
This commit is contained in:
commit
09ca7d144a
|
@ -1502,7 +1502,7 @@ function OnPlayerJoined(a_Player)
|
|||
-- Test composite chat chaining:
|
||||
a_Player:SendMessage(cCompositeChat()
|
||||
:AddTextPart("Hello, ")
|
||||
:AddUrlPart(a_Player:GetName(), "www.mc-server.org", "u@2")
|
||||
:AddUrlPart(a_Player:GetName(), "http://www.mc-server.org", "u@2")
|
||||
:AddSuggestCommandPart(", and welcome.", "/help", "u")
|
||||
:AddRunCommandPart(" SetDay", "/time set 0")
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <memory>
|
||||
#include "ChunkCache.h"
|
||||
#include "ChunkSource.h"
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <QObject>
|
||||
#include <QCache>
|
||||
#include <QMutex>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -120,8 +120,8 @@ static void biomesToImage(cChunkDef::BiomeMap & a_Biomes, Chunk::Image & a_Image
|
|||
{
|
||||
// Make sure the two arrays are of the same size, compile-time.
|
||||
// Note that a_Image is actually 4 items per pixel, so the array is 4 times bigger:
|
||||
static const char Check1[4 * ARRAYCOUNT(a_Biomes) - ARRAYCOUNT(a_Image) + 1];
|
||||
static const char Check2[ARRAYCOUNT(a_Image) - 4 * ARRAYCOUNT(a_Biomes) + 1];
|
||||
static const char Check1[4 * ARRAYCOUNT(a_Biomes) - ARRAYCOUNT(a_Image) + 1] = {};
|
||||
static const char Check2[ARRAYCOUNT(a_Image) - 4 * ARRAYCOUNT(a_Biomes) + 1] = {};
|
||||
|
||||
// Convert the biomes into color:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(a_Biomes); i++)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <QString>
|
||||
#include <QMutex>
|
||||
#include "Chunk.h"
|
||||
|
||||
|
||||
|
|
|
@ -55,5 +55,6 @@ INCLUDEPATH += $$_PRO_FILE_PWD_ \
|
|||
$$_PRO_FILE_PWD_/../../lib
|
||||
|
||||
|
||||
CONFIG += C++11
|
||||
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 203c2fb68bbf871eaf4ca98756a113d74d620dea
|
||||
Subproject commit 55edadd56d0d6f506954ad00c3b9a5d425814a2f
|
|
@ -427,7 +427,7 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac
|
|||
if (a_CanDrop)
|
||||
{
|
||||
if ((a_Digger != NULL) && (a_Digger->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0))
|
||||
{
|
||||
{
|
||||
switch (m_BlockType)
|
||||
{
|
||||
case E_BLOCK_CAKE:
|
||||
|
|
|
@ -312,8 +312,16 @@ void cClientHandle::Authenticate(const AString & a_Name, const AString & a_UUID,
|
|||
ASSERT(m_Player == NULL);
|
||||
|
||||
m_Username = a_Name;
|
||||
m_UUID = a_UUID;
|
||||
m_Properties = a_Properties;
|
||||
|
||||
// Only assign UUID and properties if not already pre-assigned (BungeeCord sends those in the Handshake packet):
|
||||
if (m_UUID.empty())
|
||||
{
|
||||
m_UUID = a_UUID;
|
||||
}
|
||||
if (m_Properties.empty())
|
||||
{
|
||||
m_Properties = a_Properties;
|
||||
}
|
||||
|
||||
// Send login success (if the protocol supports it):
|
||||
m_Protocol->SendLoginSuccess();
|
||||
|
|
|
@ -64,15 +64,27 @@ public:
|
|||
|
||||
const AString & GetIPString(void) const { return m_IPString; } // tolua_export
|
||||
|
||||
/** Sets the IP string that the client is using. Overrides the IP string that was read from the socket.
|
||||
Used mainly by BungeeCord compatibility code. */
|
||||
void SetIPString(const AString & a_IPString) { m_IPString = a_IPString; }
|
||||
|
||||
cPlayer * GetPlayer(void) { return m_Player; } // tolua_export
|
||||
|
||||
/** Returns the player's UUID, as used by the protocol, in the short form (no dashes) */
|
||||
const AString & GetUUID(void) const { return m_UUID; } // tolua_export
|
||||
|
||||
void SetUUID(const AString & a_UUID) { m_UUID = a_UUID; }
|
||||
/** Sets the player's UUID, as used by the protocol. Short UUID form (no dashes) is expected.
|
||||
Used mainly by BungeeCord compatibility code - when authenticating is done on the BungeeCord server
|
||||
and the results are passed to MCS running in offline mode. */
|
||||
void SetUUID(const AString & a_UUID) { ASSERT(a_UUID.size() == 32); m_UUID = a_UUID; }
|
||||
|
||||
const Json::Value & GetProperties(void) const { return m_Properties; }
|
||||
|
||||
/** Sets the player's properties, such as skin image and signature.
|
||||
Used mainly by BungeeCord compatibility code - property querying is done on the BungeeCord server
|
||||
and the results are passed to MCS running in offline mode. */
|
||||
void SetProperties(const Json::Value & a_Properties) { m_Properties = a_Properties; }
|
||||
|
||||
/** Generates an UUID based on the username stored for this client, and stores it in the m_UUID member.
|
||||
This is used for the offline (non-auth) mode, when there's no UUID source.
|
||||
Each username generates a unique and constant UUID, so that when the player reconnects with the same name, their UUID is the same.
|
||||
|
|
|
@ -115,12 +115,14 @@ enum eGameMode
|
|||
eGameMode_Survival = 0,
|
||||
eGameMode_Creative = 1,
|
||||
eGameMode_Adventure = 2,
|
||||
eGameMode_Spectator = 3,
|
||||
|
||||
// Easier-to-use synonyms:
|
||||
gmNotSet = eGameMode_NotSet,
|
||||
gmSurvival = eGameMode_Survival,
|
||||
gmCreative = eGameMode_Creative,
|
||||
gmAdventure = eGameMode_Adventure,
|
||||
gmSpectator = eGameMode_Spectator,
|
||||
|
||||
// These two are used to check GameMode for validity when converting from integers.
|
||||
gmMax, // Gets automatically assigned
|
||||
|
|
|
@ -451,6 +451,11 @@ void cPlayer::CancelChargingBow(void)
|
|||
|
||||
void cPlayer::SetTouchGround(bool a_bTouchGround)
|
||||
{
|
||||
if (IsGameModeSpectator()) // You can fly through the ground in Spectator
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_bTouchGround = a_bTouchGround;
|
||||
|
||||
if (!m_bTouchGround)
|
||||
|
@ -585,7 +590,7 @@ bool cPlayer::Feed(int a_Food, double a_Saturation)
|
|||
|
||||
void cPlayer::AddFoodExhaustion(double a_Exhaustion)
|
||||
{
|
||||
if (!IsGameModeCreative())
|
||||
if (!(IsGameModeCreative() || IsGameModeSpectator()))
|
||||
{
|
||||
m_FoodExhaustionLevel = std::min(m_FoodExhaustionLevel + a_Exhaustion, 40.0);
|
||||
}
|
||||
|
@ -823,9 +828,9 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
|
|||
{
|
||||
if ((a_TDI.DamageType != dtInVoid) && (a_TDI.DamageType != dtPlugin))
|
||||
{
|
||||
if (IsGameModeCreative())
|
||||
if (IsGameModeCreative() || IsGameModeSpectator())
|
||||
{
|
||||
// No damage / health in creative mode if not void or plugin damage
|
||||
// No damage / health in creative or spectator mode if not void or plugin damage
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1043,6 +1048,14 @@ bool cPlayer::IsGameModeAdventure(void) const
|
|||
|
||||
|
||||
|
||||
bool cPlayer::IsGameModeSpectator(void) const
|
||||
{
|
||||
return (m_GameMode == gmSpectator) || // Either the player is explicitly in Spectator
|
||||
((m_GameMode == gmNotSet) && m_World->IsGameModeSpectator()); // or they inherit from the world and the world is Adventure
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void cPlayer::SetTeam(cTeam * a_Team)
|
||||
{
|
||||
|
@ -1158,7 +1171,7 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
|
|||
m_GameMode = a_GameMode;
|
||||
m_ClientHandle->SendGameMode(a_GameMode);
|
||||
|
||||
if (!IsGameModeCreative())
|
||||
if (!(IsGameModeCreative() || IsGameModeSpectator()))
|
||||
{
|
||||
SetFlying(false);
|
||||
SetCanFly(false);
|
||||
|
@ -1340,6 +1353,7 @@ void cPlayer::MoveTo( const Vector3d & a_NewPos)
|
|||
|
||||
void cPlayer::SetVisible(bool a_bVisible)
|
||||
{
|
||||
// Need to Check if the player or other players are in gamemode spectator, but will break compatibility
|
||||
if (a_bVisible && !m_bVisible) // Make visible
|
||||
{
|
||||
m_bVisible = true;
|
||||
|
@ -1500,6 +1514,11 @@ void cPlayer::TossPickup(const cItem & a_Item)
|
|||
|
||||
void cPlayer::TossItems(const cItems & a_Items)
|
||||
{
|
||||
if (IsGameModeSpectator()) // Players can't toss items in spectator
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Stats.AddValue(statItemsDropped, (StatValue)a_Items.Size());
|
||||
|
||||
double vX = 0, vY = 0, vZ = 0;
|
||||
|
@ -1786,7 +1805,7 @@ bool cPlayer::SaveToDisk()
|
|||
|
||||
void cPlayer::UseEquippedItem(int a_Amount)
|
||||
{
|
||||
if (IsGameModeCreative()) // No damage in creative
|
||||
if (IsGameModeCreative() || IsGameModeSpectator()) // No damage in creative or spectator
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -171,6 +171,9 @@ public:
|
|||
/** Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current world */
|
||||
bool IsGameModeAdventure(void) const;
|
||||
|
||||
/** Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current world */
|
||||
bool IsGameModeSpectator(void) const;
|
||||
|
||||
AString GetIP(void) const { return m_IP; } // tolua_export
|
||||
|
||||
/** Returns the associated team, NULL if none */
|
||||
|
|
|
@ -12,72 +12,6 @@
|
|||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cBiomeGen:
|
||||
|
||||
cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault)
|
||||
{
|
||||
AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", "");
|
||||
if (BiomeGenName.empty())
|
||||
{
|
||||
LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\".");
|
||||
BiomeGenName = "MultiStepMap";
|
||||
}
|
||||
|
||||
cBiomeGen * res = NULL;
|
||||
a_CacheOffByDefault = false;
|
||||
if (NoCaseCompare(BiomeGenName, "constant") == 0)
|
||||
{
|
||||
res = new cBioGenConstant;
|
||||
a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :)
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0)
|
||||
{
|
||||
res = new cBioGenCheckerboard;
|
||||
a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "voronoi") == 0)
|
||||
{
|
||||
res = new cBioGenVoronoi(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0)
|
||||
{
|
||||
res = new cBioGenDistortedVoronoi(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "twolevel") == 0)
|
||||
{
|
||||
res = new cBioGenTwoLevel(a_Seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NoCaseCompare(BiomeGenName, "multistepmap") != 0)
|
||||
{
|
||||
LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str());
|
||||
}
|
||||
res = new cBioGenMultiStepMap(a_Seed);
|
||||
|
||||
/*
|
||||
// Performance-testing:
|
||||
LOGINFO("Measuring performance of cBioGenMultiStepMap...");
|
||||
clock_t BeginTick = clock();
|
||||
for (int x = 0; x < 5000; x++)
|
||||
{
|
||||
cChunkDef::BiomeMap Biomes;
|
||||
res->GenBiomes(x * 5, x * 5, Biomes);
|
||||
}
|
||||
clock_t Duration = clock() - BeginTick;
|
||||
LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
|
||||
//*/
|
||||
}
|
||||
res->InitializeBiomeGen(a_IniFile);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cBioGenConstant:
|
||||
|
||||
|
@ -402,8 +336,13 @@ void cBioGenVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap &
|
|||
void cBioGenVoronoi::InitializeBiomeGen(cIniFile & a_IniFile)
|
||||
{
|
||||
super::InitializeBiomeGen(a_IniFile);
|
||||
m_Voronoi.SetCellSize(a_IniFile.GetValueSetI("Generator", "VoronoiCellSize", 64));
|
||||
InitializeBiomes (a_IniFile.GetValueSet ("Generator", "VoronoiBiomes", ""));
|
||||
int CellSize = a_IniFile.GetValueSetI("Generator", "VoronoiCellSize", 128);
|
||||
int JitterSize = a_IniFile.GetValueSetI("Generator", "VoronoiJitterSize", CellSize);
|
||||
int OddRowOffset = a_IniFile.GetValueSetI("Generator", "VoronoiOddRowOffset", 0);
|
||||
m_Voronoi.SetCellSize(CellSize);
|
||||
m_Voronoi.SetJitterSize(JitterSize);
|
||||
m_Voronoi.SetOddRowOffset(OddRowOffset);
|
||||
InitializeBiomes(a_IniFile.GetValueSet ("Generator", "VoronoiBiomes", ""));
|
||||
}
|
||||
|
||||
|
||||
|
@ -846,9 +785,10 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
|
|||
{
|
||||
for (int x = 0; x < cChunkDef::Width; x++)
|
||||
{
|
||||
int MinDist1, MinDist2;
|
||||
int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z], MinDist1, MinDist2) / 7;
|
||||
int BiomeIdx = m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], MinDist1, MinDist2) / 11;
|
||||
int SeedX, SeedZ, MinDist2;
|
||||
int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 7;
|
||||
int BiomeIdx = m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 11;
|
||||
int MinDist1 = (DistortX[x][z] - SeedX) * (DistortX[x][z] - SeedX) + (DistortZ[x][z] - SeedZ) * (DistortZ[x][z] - SeedZ);
|
||||
cChunkDef::SetBiome(a_BiomeMap, x, z, SelectBiome(BiomeGroup, BiomeIdx, (MinDist1 < MinDist2 / 4) ? 0 : 1));
|
||||
}
|
||||
}
|
||||
|
@ -987,3 +927,69 @@ void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile)
|
|||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cBiomeGen:
|
||||
|
||||
cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault)
|
||||
{
|
||||
AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", "");
|
||||
if (BiomeGenName.empty())
|
||||
{
|
||||
LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\".");
|
||||
BiomeGenName = "MultiStepMap";
|
||||
}
|
||||
|
||||
cBiomeGen * res = NULL;
|
||||
a_CacheOffByDefault = false;
|
||||
if (NoCaseCompare(BiomeGenName, "constant") == 0)
|
||||
{
|
||||
res = new cBioGenConstant;
|
||||
a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :)
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0)
|
||||
{
|
||||
res = new cBioGenCheckerboard;
|
||||
a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "voronoi") == 0)
|
||||
{
|
||||
res = new cBioGenVoronoi(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0)
|
||||
{
|
||||
res = new cBioGenDistortedVoronoi(a_Seed);
|
||||
}
|
||||
else if (NoCaseCompare(BiomeGenName, "twolevel") == 0)
|
||||
{
|
||||
res = new cBioGenTwoLevel(a_Seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NoCaseCompare(BiomeGenName, "multistepmap") != 0)
|
||||
{
|
||||
LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str());
|
||||
}
|
||||
res = new cBioGenMultiStepMap(a_Seed);
|
||||
|
||||
/*
|
||||
// Performance-testing:
|
||||
LOGINFO("Measuring performance of cBioGenMultiStepMap...");
|
||||
clock_t BeginTick = clock();
|
||||
for (int x = 0; x < 5000; x++)
|
||||
{
|
||||
cChunkDef::BiomeMap Biomes;
|
||||
res->GenBiomes(x * 5, x * 5, Biomes);
|
||||
}
|
||||
clock_t Duration = clock() - BeginTick;
|
||||
LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
|
||||
//*/
|
||||
}
|
||||
res->InitializeBiomeGen(a_IniFile);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -100,6 +100,19 @@ cProtocol172::cProtocol172(cClientHandle * a_Client, const AString & a_ServerAdd
|
|||
m_IsEncrypted(false),
|
||||
m_LastSentDimension(dimNotSet)
|
||||
{
|
||||
// BungeeCord handling:
|
||||
// If BC is setup with ip_forward == true, it sends additional data in the login packet's ServerAddress field:
|
||||
// hostname\00ip-address\00uuid\00profile-properties-as-json
|
||||
AStringVector Params;
|
||||
if (cRoot::Get()->GetServer()->ShouldAllowBungeeCord() && SplitZeroTerminatedStrings(a_ServerAddress, Params) && (Params.size() == 4))
|
||||
{
|
||||
LOGD("Player at %s connected via BungeeCord", Params[1].c_str());
|
||||
m_ServerAddress = Params[0];
|
||||
m_Client->SetIPString(Params[1]);
|
||||
m_Client->SetUUID(cMojangAPI::MakeUUIDShort(Params[2]));
|
||||
m_Client->SetProperties(Params[3]);
|
||||
}
|
||||
|
||||
// Create the comm log file, if so requested:
|
||||
if (g_ShouldLogCommIn || g_ShouldLogCommOut)
|
||||
{
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
cProtocolRecognizer::cProtocolRecognizer(cClientHandle * a_Client) :
|
||||
super(a_Client),
|
||||
m_Protocol(NULL),
|
||||
m_Buffer(512)
|
||||
m_Buffer(8192) // We need a larger buffer to support BungeeCord - it sends one huge packet at the start
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -113,8 +113,8 @@ void cRoot::Start(void)
|
|||
LOG("--- Started Log ---\n");
|
||||
|
||||
#ifdef BUILD_ID
|
||||
LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID );
|
||||
LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME );
|
||||
LOG("MCServer " BUILD_SERIES_NAME " build id: " BUILD_ID);
|
||||
LOG("from commit id: " BUILD_COMMIT_ID " built at: " BUILD_DATETIME);
|
||||
#endif
|
||||
|
||||
cDeadlockDetect dd;
|
||||
|
|
|
@ -259,6 +259,13 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
|
|||
m_ServerID = sid.str();
|
||||
m_ServerID.resize(16, '0');
|
||||
}
|
||||
|
||||
// Check if both BungeeCord and online mode are on, if so, warn the admin:
|
||||
m_ShouldAllowBungeeCord = a_SettingsIni.GetValueSetB("Authentication", "AllowBungeeCord", false);
|
||||
if (m_ShouldAllowBungeeCord && m_ShouldAuthenticate)
|
||||
{
|
||||
LOGWARNING("WARNING: BungeeCord is allowed and server set to online mode. This is unsafe and will not work properly. Disable either authentication or BungeeCord in settings.ini.");
|
||||
}
|
||||
|
||||
m_ShouldLoadOfflinePlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false);
|
||||
m_ShouldLoadNamedPlayerData = a_SettingsIni.GetValueSetB("PlayerData", "LoadNamedPlayerData", true);
|
||||
|
|
|
@ -131,6 +131,11 @@ public: // tolua_export
|
|||
Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
|
||||
bool ShouldLoadNamedPlayerData(void) const { return m_ShouldLoadNamedPlayerData; }
|
||||
|
||||
/** Returns true if BungeeCord logins (that specify the player's UUID) are allowed.
|
||||
Read from settings, admins should set this to true only when they chain to BungeeCord,
|
||||
it makes the server vulnerable to identity theft through direct connections. */
|
||||
bool ShouldAllowBungeeCord(void) const { return m_ShouldAllowBungeeCord; }
|
||||
|
||||
private:
|
||||
|
||||
friend class cRoot; // so cRoot can create and destroy cServer
|
||||
|
@ -230,6 +235,9 @@ private:
|
|||
This allows a seamless transition from name-based to UUID-based player storage.
|
||||
Loaded from the settings.ini [PlayerData].LoadNamedPlayerData setting. */
|
||||
bool m_ShouldLoadNamedPlayerData;
|
||||
|
||||
/** True if BungeeCord handshake packets (with player UUID) should be accepted. */
|
||||
bool m_ShouldAllowBungeeCord;
|
||||
|
||||
|
||||
cServer(void);
|
||||
|
|
|
@ -869,3 +869,31 @@ void SetBEInt(char * a_Mem, Int32 a_Value)
|
|||
|
||||
|
||||
|
||||
|
||||
bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output)
|
||||
{
|
||||
a_Output.clear();
|
||||
size_t size = a_Strings.size();
|
||||
size_t start = 0;
|
||||
bool res = false;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
if (a_Strings[i] == 0)
|
||||
{
|
||||
a_Output.push_back(a_Strings.substr(start, i - start));
|
||||
start = i + 1;
|
||||
res = true;
|
||||
}
|
||||
}
|
||||
if (start < size)
|
||||
{
|
||||
a_Output.push_back(a_Strings.substr(start, size - start));
|
||||
res = true;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -99,6 +99,11 @@ extern int GetBEInt(const char * a_Mem);
|
|||
/// Writes four bytes to the specified memory location so that they interpret as BigEndian int
|
||||
extern void SetBEInt(char * a_Mem, Int32 a_Value);
|
||||
|
||||
/** Splits a string that has embedded \0 characters, on those characters.
|
||||
a_Output is first cleared and then each separate string is pushed back into a_Output.
|
||||
Returns true if there are at least two strings in a_Output (there was at least one \0 separator). */
|
||||
extern bool SplitZeroTerminatedStrings(const AString & a_Strings, AStringVector & a_Output);
|
||||
|
||||
/// Parses any integer type. Checks bounds and returns errors out of band.
|
||||
template <class T>
|
||||
bool StringToInteger(const AString & a_str, T & a_Num)
|
||||
|
|
|
@ -59,8 +59,8 @@ void cVoronoiMap::SetOddRowOffset(int a_OddRowOffset)
|
|||
|
||||
int cVoronoiMap::GetValueAt(int a_X, int a_Y)
|
||||
{
|
||||
int MinDist1, MinDist2;
|
||||
return GetValueAt(a_X, a_Y, MinDist1, MinDist2);
|
||||
int SeedX, SeedY, MinDist2;
|
||||
return GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,41 +69,47 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y)
|
|||
|
||||
int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist)
|
||||
{
|
||||
int MinDist2;
|
||||
return GetValueAt(a_X, a_Y, a_MinDist, MinDist2);
|
||||
int SeedX, SeedY, MinDist2;
|
||||
int res = GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2);
|
||||
a_MinDist = (a_X - SeedX) * (a_X - SeedX) + (a_Y - SeedY) * (a_Y - SeedY);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2)
|
||||
int cVoronoiMap::GetValueAt(
|
||||
int a_X, int a_Y, // Coords to query
|
||||
int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell
|
||||
int & a_MinDist2 // Distance to the second closest cell
|
||||
)
|
||||
{
|
||||
// Note that due to historical reasons, the algorithm uses XZ coords, while the input uses XY coords.
|
||||
// This is because the algorithm was first implemented directly in the biome generators which use MC coords.
|
||||
|
||||
int CellX = a_X / m_CellSize;
|
||||
int CellZ = a_Y / m_CellSize;
|
||||
int CellY = a_Y / m_CellSize;
|
||||
|
||||
UpdateCell(CellX, CellZ);
|
||||
UpdateCell(CellX, CellY);
|
||||
|
||||
// Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell
|
||||
int NearestSeedX = 0, NearestSeedY = 0;
|
||||
int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this
|
||||
int MinDist2 = MinDist;
|
||||
int res = 0; // Will be overriden
|
||||
for (int x = 0; x < 5; x++)
|
||||
{
|
||||
for (int z = 0; z < 5; z++)
|
||||
for (int y = 0; y < 5; y++)
|
||||
{
|
||||
int SeedX = m_SeedX[x][z];
|
||||
int SeedZ = m_SeedZ[x][z];
|
||||
int SeedX = m_SeedX[x][y];
|
||||
int SeedY = m_SeedZ[x][y];
|
||||
|
||||
int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedZ - a_Y) * (SeedZ - a_Y);
|
||||
int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y);
|
||||
if (Dist < MinDist)
|
||||
{
|
||||
NearestSeedX = SeedX;
|
||||
NearestSeedY = SeedY;
|
||||
MinDist2 = MinDist;
|
||||
MinDist = Dist;
|
||||
res = m_Noise3.IntNoise2DInt(x + CellX - 2, z + CellZ - 2);
|
||||
res = m_Noise3.IntNoise2DInt(x + CellX - 2, y + CellY - 2);
|
||||
}
|
||||
else if (Dist < MinDist2)
|
||||
{
|
||||
|
@ -112,7 +118,8 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2
|
|||
} // for z
|
||||
} // for x
|
||||
|
||||
a_MinDist1 = MinDist;
|
||||
a_NearestSeedX = NearestSeedX;
|
||||
a_NearestSeedY = NearestSeedY;
|
||||
a_MinDist2 = MinDist2;
|
||||
return res;
|
||||
}
|
||||
|
@ -121,6 +128,58 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2
|
|||
|
||||
|
||||
|
||||
void cVoronoiMap::FindNearestSeeds(
|
||||
int a_X, int a_Y,
|
||||
int & a_NearestSeedX, int & a_NearestSeedY,
|
||||
int & a_SecondNearestSeedX, int & a_SecondNearestSeedY
|
||||
)
|
||||
{
|
||||
int CellX = a_X / m_CellSize;
|
||||
int CellY = a_Y / m_CellSize;
|
||||
|
||||
UpdateCell(CellX, CellY);
|
||||
|
||||
// Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell
|
||||
int NearestSeedX = 0, NearestSeedY = 0;
|
||||
int SecondNearestSeedX = 0, SecondNearestSeedY = 0;
|
||||
int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this
|
||||
int MinDist2 = MinDist;
|
||||
for (int x = 0; x < 5; x++)
|
||||
{
|
||||
for (int y = 0; y < 5; y++)
|
||||
{
|
||||
int SeedX = m_SeedX[x][y];
|
||||
int SeedY = m_SeedZ[x][y];
|
||||
|
||||
int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y);
|
||||
if (Dist < MinDist)
|
||||
{
|
||||
SecondNearestSeedX = NearestSeedX;
|
||||
SecondNearestSeedY = NearestSeedY;
|
||||
MinDist2 = MinDist;
|
||||
NearestSeedX = SeedX;
|
||||
NearestSeedY = SeedY;
|
||||
MinDist = Dist;
|
||||
}
|
||||
else if (Dist < MinDist2)
|
||||
{
|
||||
SecondNearestSeedX = SeedX;
|
||||
SecondNearestSeedY = SeedY;
|
||||
MinDist2 = Dist;
|
||||
}
|
||||
} // for z
|
||||
} // for x
|
||||
|
||||
a_NearestSeedX = NearestSeedX;
|
||||
a_NearestSeedY = NearestSeedY;
|
||||
a_SecondNearestSeedX = SecondNearestSeedX;
|
||||
a_SecondNearestSeedY = SecondNearestSeedY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cVoronoiMap::UpdateCell(int a_CellX, int a_CellZ)
|
||||
{
|
||||
// If the specified cell is currently cached, bail out:
|
||||
|
|
|
@ -40,7 +40,18 @@ public:
|
|||
|
||||
/** Returns the value in the cell into which the specified point lies,
|
||||
and the distances to the 2 nearest Voronoi seeds. Uses a cache. */
|
||||
int GetValueAt(int a_X, int a_Y, int & a_MinDistance1, int & a_MinDistance2);
|
||||
int GetValueAt(
|
||||
int a_X, int a_Y, // Coords to query
|
||||
int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell's seed
|
||||
int & a_MinDist2 // Distance to the second closest cell's seed
|
||||
);
|
||||
|
||||
/** Finds the nearest and second nearest seeds, returns their coords. */
|
||||
void FindNearestSeeds(
|
||||
int a_X, int a_Y,
|
||||
int & a_NearestSeedX, int & a_NearestSeedY,
|
||||
int & a_SecondNearestSeedX, int & a_SecondNearestSeedY
|
||||
);
|
||||
|
||||
protected:
|
||||
/// The noise used for generating Voronoi seeds
|
||||
|
|
|
@ -188,6 +188,9 @@ public:
|
|||
/** Returns true if the world is in Adventure mode */
|
||||
bool IsGameModeAdventure(void) const { return (m_GameMode == gmAdventure); }
|
||||
|
||||
/** Returns true if the world is in Spectator mode */
|
||||
bool IsGameModeSpectator(void) const { return (m_GameMode == gmSpectator); }
|
||||
|
||||
bool IsPVPEnabled(void) const { return m_bEnabledPVP; }
|
||||
bool IsDeepSnowEnabled(void) const { return m_IsDeepSnowEnabled; }
|
||||
|
||||
|
|
Loading…
Reference in New Issue