diff options
author | Tiger Wang <ziwei.tiger@outlook.com> | 2020-09-08 10:46:16 +0200 |
---|---|---|
committer | Tiger Wang <ziwei.tiger@outlook.com> | 2020-12-21 01:11:34 +0100 |
commit | 742e27ad2f037205285e475be487ec9ed874ca91 (patch) | |
tree | 3218d3c2791e823c88a294ba7fdb10035c8fbb9b /src/Bindings/BlockState.cpp | |
parent | Enable LOS checks for Hostile Mobs. (diff) | |
download | cuberite-742e27ad2f037205285e475be487ec9ed874ca91.tar cuberite-742e27ad2f037205285e475be487ec9ed874ca91.tar.gz cuberite-742e27ad2f037205285e475be487ec9ed874ca91.tar.bz2 cuberite-742e27ad2f037205285e475be487ec9ed874ca91.tar.lz cuberite-742e27ad2f037205285e475be487ec9ed874ca91.tar.xz cuberite-742e27ad2f037205285e475be487ec9ed874ca91.tar.zst cuberite-742e27ad2f037205285e475be487ec9ed874ca91.zip |
Diffstat (limited to 'src/Bindings/BlockState.cpp')
-rw-r--r-- | src/Bindings/BlockState.cpp | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/Bindings/BlockState.cpp b/src/Bindings/BlockState.cpp new file mode 100644 index 000000000..8ee87c50f --- /dev/null +++ b/src/Bindings/BlockState.cpp @@ -0,0 +1,213 @@ +#include "Globals.h" +#include "BlockState.h" + + + + + +BlockState::BlockState(): + mChecksum(initializeChecksum()) +{ + // Nothing needed yet +} + + + + + +BlockState::BlockState(const AString & aKey, const AString & aValue): + mState({{aKey, aValue}}), + mChecksum(initializeChecksum()) +{ +} + + + + + +BlockState::BlockState(std::initializer_list<std::pair<const AString, AString>> aKeysAndValues): + mState(aKeysAndValues), + mChecksum(initializeChecksum()) +{ +} + + + + + +BlockState::BlockState(const std::map<AString, AString> & aKeysAndValues): + mState(aKeysAndValues), + mChecksum(initializeChecksum()) +{ +} + + + + + +BlockState::BlockState(std::map<AString, AString> && aKeysAndValues): + mState(std::move(aKeysAndValues)), + mChecksum(initializeChecksum()) +{ +} + + + + + +BlockState::BlockState(const BlockState & aCopyFrom, std::initializer_list<std::pair<const AString, AString>> aAdditionalKeysAndValues): + mState(aCopyFrom.mState) +{ + for (const auto & kav: aAdditionalKeysAndValues) + { + mState[kav.first] = kav.second; + } + mChecksum = initializeChecksum(); +} + + + + + +BlockState::BlockState(const BlockState & aCopyFrom, const std::map<AString, AString> & aAdditionalKeysAndValues): + mState(aCopyFrom.mState) +{ + for (const auto & kav: aAdditionalKeysAndValues) + { + mState[kav.first] = kav.second; + } + mChecksum = initializeChecksum(); +} + + + + + +bool BlockState::operator <(const BlockState & aOther) const +{ + // Fast-return this using checksum + if (mChecksum != aOther.mChecksum) + { + return (mChecksum < aOther.mChecksum); + } + + // Can fast-return this due to how comparison works + if (mState.size() != aOther.mState.size()) + { + return (mState.size() < aOther.mState.size()); + } + + auto itA = mState.begin(); + auto itOther = aOther.mState.begin(); + + // don't need to check itOther, size checks above ensure size(A) == size(O) + while (itA != mState.end()) + { + { + const auto cmp = itA->first.compare(itOther->first); + if (cmp != 0) + { + return (cmp < 0); + } + } + { + const auto cmp = itA->second.compare(itOther->second); + if (cmp != 0) + { + return (cmp < 0); + } + } + + ++itA; + ++itOther; + } + + return false; +} + + + + + +bool BlockState::operator ==(const BlockState & aOther) const +{ + // Fast-fail if the checksums differ or differrent counts: + if ((mChecksum != aOther.mChecksum) || (mState.size() != aOther.mState.size())) + { + return false; + } + + // Slow-check everything if the checksums match: + return std::equal(mState.begin(), mState.end(), aOther.mState.begin()); +} + + + + + +const AString & BlockState::value(const AString & aKey) const +{ + auto itr = mState.find(aKey); + if (itr == mState.end()) + { + static AString empty; + return empty; + } + return itr->second; +} + + + + + +UInt32 BlockState::initializeChecksum() +{ + removeEmptyKeys(); + + // Calculate the checksum as a XOR of all mState keys' and values' checksums + // This way we don't depend on the std::map's ordering + UInt32 res = 0; + for (const auto & kv: mState) + { + auto partial = partialChecksum(kv.first) ^ partialChecksum(kv.second); + res = res ^ partial; + } + return res; +} + + + + + +void BlockState::removeEmptyKeys() +{ + for (auto itr = mState.begin(); itr != mState.end();) + { + if (itr->second.empty()) + { + itr = mState.erase(itr); + } + else + { + ++itr; + } + } +} + + + + + +UInt32 BlockState::partialChecksum(const AString & aString) +{ + UInt32 shift = 0; + UInt32 res = 0; + for (auto ch: aString) + { + UInt32 v = static_cast<UInt8>(ch); + v = v << shift; + shift = (shift + 1) % 24; + res = res ^ v; + } + return res; +} |