diff --git a/src/mc/world/level/block/Block.h b/src/mc/world/level/block/Block.h index c3d7f24e6f..07e6dae7e5 100644 --- a/src/mc/world/level/block/Block.h +++ b/src/mc/world/level/block/Block.h @@ -90,6 +90,27 @@ class Block { ::ll::TypedStorage<1, 1, bool> mHasRuntimeId; // NOLINTEND +public: + template + T getState(uint64 id) const { + return mLegacyBlock->get()->getState(id, mData); + } + + template + T getState(BlockState const& state) const { + return mLegacyBlock->get()->getState(state, mData); + } + + template + optional_ref setState(uint64 id, T value) const { + return mLegacyBlock->get()->trySetState(id, value, mData); + } + + template + optional_ref setState(BlockState const& state, T value) const { + return mLegacyBlock->get()->trySetState(state, value, mData); + } + public: // virtual functions // NOLINTBEGIN diff --git a/src/mc/world/level/block/BlockLegacy.h b/src/mc/world/level/block/BlockLegacy.h index ef1a1be457..ccbe97421f 100644 --- a/src/mc/world/level/block/BlockLegacy.h +++ b/src/mc/world/level/block/BlockLegacy.h @@ -1,6 +1,8 @@ #pragma once #include "mc/_HeaderOutputPredefine.h" +#include "mc/world/level/block/states/BlockState.h" +#include "mc/world/level/block/states/BlockStateInstance.h" // auto generated inclusion list #include "mc/common/WeakPtr.h" @@ -331,6 +333,62 @@ class BlockLegacy { LLNDAPI static optional_ref tryGetFromRegistry(std::string_view name); LLNDAPI static optional_ref tryGetFromRegistry(uint legacyBlockID); + template + T getState(uint64 id, ushort data) const { + auto it = mStates->lower_bound(id); + + if (it == mStates->end() || it->first != id) { + std::optional result = _tryLookupAlteredStateCollection(id, data); + if (result.has_value()) { + return static_cast(result.value()); + } else { + return T{}; + } + } + + return it->second.get(data); + } + + template + T getState(BlockState const& stateType, ushort data) const { + return getState(stateType.mID, data); + } + + template + Block const* trySetState(uint64 id, T val, ushort data) { + auto it = mStates->lower_bound(id); + + if (it != mStates->end() && it->first == id) { + auto& stateInstance = it->second; + + if (static_cast(val) < stateInstance.mVariationCount) { + ushort maskedData = (data & ~stateInstance.mMask) + | (static_cast(val) << (stateInstance.mEndBit - stateInstance.mNumBits + 1)); + + if (maskedData < mBlockPermutations->size()) { + return mBlockPermutations->at(maskedData).get(); + } + return nullptr; + } + } + + Block const* alteredStateBlock = _trySetStateFromAlteredStateCollection(id, static_cast(val), data); + if (alteredStateBlock) { + return alteredStateBlock; + } + + if (mReturnDefaultBlockOnUnidentifiedBlockState) { + return &getDefaultState(); + } + + return nullptr; + } + + template + Block const* trySetState(BlockState const& stateType, T val, ushort data) { + return trySetState(stateType.mID, val, data); + } + public: // member variables // NOLINTBEGIN diff --git a/src/mc/world/level/block/states/BlockStateInstance.h b/src/mc/world/level/block/states/BlockStateInstance.h index a4fc777f1d..af857943bb 100644 --- a/src/mc/world/level/block/states/BlockStateInstance.h +++ b/src/mc/world/level/block/states/BlockStateInstance.h @@ -11,19 +11,20 @@ class BlockStateInstance { public: // member variables // NOLINTBEGIN - ::ll::UntypedStorage<4, 4> mUnkeee94f; - ::ll::UntypedStorage<4, 4> mUnk58db0e; - ::ll::UntypedStorage<4, 4> mUnk3e3d8a; - ::ll::UntypedStorage<4, 4> mUnk787411; - ::ll::UntypedStorage<1, 1> mUnk163307; - ::ll::UntypedStorage<8, 8> mUnkd127d6; + ::ll::TypedStorage<4, 4, uint> mEndBit; + ::ll::TypedStorage<4, 4, uint> mNumBits; + ::ll::TypedStorage<4, 4, uint> mVariationCount; + ::ll::TypedStorage<4, 4, uint> mMask; + ::ll::TypedStorage<1, 1, bool> mInitialized; + ::ll::TypedStorage<8, 8, ::BlockState const*> mState; // NOLINTEND public: - // prevent constructor by default - BlockStateInstance& operator=(BlockStateInstance const&); - BlockStateInstance(BlockStateInstance const&); - BlockStateInstance(); + template + T get(ushort data) const { + if (sizeof(T) * 8 < mNumBits) return T{}; + return static_cast((data >> (mEndBit - mNumBits + 1)) & ((1 << mNumBits) - 1)); + } public: // member functions