From 221cc4ec5cb6301743e947eaabed3fecedba796f Mon Sep 17 00:00:00 2001 From: Mattes D Date: Wed, 16 Oct 2019 10:06:34 +0200 Subject: Refactored block-to-pickup conversion. (#4417) --- src/Blocks/Mixins.h | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/Blocks/Mixins.h (limited to 'src/Blocks/Mixins.h') diff --git a/src/Blocks/Mixins.h b/src/Blocks/Mixins.h new file mode 100644 index 000000000..a65fe7b06 --- /dev/null +++ b/src/Blocks/Mixins.h @@ -0,0 +1,166 @@ +// Mixins.h + +// Provides various mixins for easier cBlockHandler descendant implementations + +/* The general use case is to derive a handler from these mixins, providing a suitable base to them: +class cBlockAir: public cBlockWithNoDrops; +class cBlockLadder: public cMetaRotator +*/ + +#pragma once + +#include "../Item.h" + + + + + +// MSVC generates warnings for the templated AssertIfNotMatched parameter conditions, so disable it: +#ifdef _MSC_VER + #pragma warning(disable: 4127) // Conditional expression is constant +#endif + + + + + +template +class cBlockWithNoDrops: + public Base +{ +public: + + cBlockWithNoDrops(BLOCKTYPE a_BlockType): + Base(a_BlockType) + { + } + + + + + + virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override + { + // Don't drop anything: + return {}; + } +}; + + + + + +/** Mixin to clear the block's meta value when converting to a pickup. */ +template +class cClearMetaOnDrop: + public Base +{ +public: + + cClearMetaOnDrop(BLOCKTYPE a_BlockType): + Base(a_BlockType) + { + } + + + + + + virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, cBlockEntity * a_BlockEntity, const cEntity * a_Digger, const cItem * a_Tool) override + { + // Reset the meta to zero: + return cItem(this->m_BlockType); + } +}; + + + + + +/** Mixin for rotations and reflections following the standard pattern of "apply mask, then use a switch". +Inherit from this class providing your base class as Base, the BitMask for the direction bits in bitmask and the masked value for the directions in North, East, South, West. +There is also an aptional parameter AssertIfNotMatched, set this if it is invalid for a block to exist in any other state. */ +template +class cMetaRotator: + public Base +{ +public: + + cMetaRotator(BLOCKTYPE a_BlockType): + Base(a_BlockType) + {} + + + + + + virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) override + { + NIBBLETYPE OtherMeta = a_Meta & (~BitMask); + switch (a_Meta & BitMask) + { + case South: return East | OtherMeta; + case East: return North | OtherMeta; + case North: return West | OtherMeta; + case West: return South | OtherMeta; + } + if (AssertIfNotMatched) + { + ASSERT(!"Invalid Meta value"); + } + return a_Meta; + } + + + + + + virtual NIBBLETYPE MetaRotateCW(NIBBLETYPE a_Meta) override + { + NIBBLETYPE OtherMeta = a_Meta & (~BitMask); + switch (a_Meta & BitMask) + { + case South: return West | OtherMeta; + case West: return North | OtherMeta; + case North: return East | OtherMeta; + case East: return South | OtherMeta; + } + if (AssertIfNotMatched) + { + ASSERT(!"Invalid Meta value"); + } + return a_Meta; + } + + + + + + virtual NIBBLETYPE MetaMirrorXY(NIBBLETYPE a_Meta) override + { + NIBBLETYPE OtherMeta = a_Meta & (~BitMask); + switch (a_Meta & BitMask) + { + case South: return North | OtherMeta; + case North: return South | OtherMeta; + } + // Not Facing North or South; No change. + return a_Meta; + } + + + + + + virtual NIBBLETYPE MetaMirrorYZ(NIBBLETYPE a_Meta) override + { + NIBBLETYPE OtherMeta = a_Meta & (~BitMask); + switch (a_Meta & BitMask) + { + case West: return East | OtherMeta; + case East: return West | OtherMeta; + } + // Not Facing East or West; No change. + return a_Meta; + } +}; -- cgit v1.2.3