├── .gitignore ├── main.cpp ├── CircuitSystem.h ├── components ├── PulseCapacitor.cpp ├── ProducerComponent.cpp ├── ComponentType.h ├── PistonConsumer.cpp ├── CapacitorComponent.h ├── BaseRailTransporter.h ├── PistonConsumer.h ├── TransporterComponent.h ├── ConsumerComponent.h ├── ProducerComponent.h ├── PulseCapacitor.h ├── PoweredBlockComponent.h ├── ComparatorCapacitor.h ├── PoweredBlockComponent.cpp ├── BaseRailTransporter.cpp ├── RedstoneTorchCapacitor.h ├── RepeaterCapacitor.cpp ├── ConsumerComponent.cpp ├── BaseCircuitComponent.h ├── ComparatorCapacitor.cpp ├── RepeaterCapacitor.h ├── BaseCircuitComponent.cpp ├── TransporterComponent.cpp └── RedstoneTorchCapacitor.cpp ├── CircuitSceneGraph.cpp ├── Facing.h ├── CircuitTrackingInfo.cpp ├── CircuitTrackingInfo.h ├── BlockPos.h ├── CMakeLists.txt ├── CircuitSceneGraph.h └── CircuitComponentList.h /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | cmake-build-debug/ 3 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << "Hello, World!" << std::endl; 5 | return 0; 6 | } -------------------------------------------------------------------------------- /CircuitSystem.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_CIRCUITSYSTEM_H 6 | #define REDSTONE_SYSTEM_CIRCUITSYSTEM_H 7 | 8 | class CircuitSystem; 9 | 10 | #endif //REDSTONE_SYSTEM_CIRCUITSYSTEM_H 11 | -------------------------------------------------------------------------------- /components/PulseCapacitor.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "PulseCapacitor.h" 6 | 7 | bool PulseCapacitor::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) { 8 | return trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[getDirection()]; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /components/ProducerComponent.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "ProducerComponent.h" 6 | 7 | bool ProducerComponent::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) { 8 | return field_40 || trackingInfo->entry0.mComponent->getBaseType() != TYPE_POWERED_BLOCK; 9 | } 10 | 11 | bool ProducerComponent::evaluate(CircuitSystem *system, const BlockPos *pos) { 12 | mStrength = field_3C; 13 | return false; 14 | } 15 | -------------------------------------------------------------------------------- /CircuitSceneGraph.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 13/12/18. 3 | // 4 | 5 | #include "components/BaseCircuitComponent.h" 6 | #include "CircuitSceneGraph.h" 7 | 8 | BaseCircuitComponent* CircuitSceneGraph::getComponent(const BlockPos *pos, ComponentType type) { 9 | auto it = find(*pos); 10 | if (it == end()) 11 | return nullptr; 12 | 13 | BaseCircuitComponent *component = it->second.get(); 14 | if (component->getBaseType() == type || component->getInstanceType() == type) 15 | return component; 16 | else 17 | return nullptr; 18 | } 19 | -------------------------------------------------------------------------------- /Facing.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_FACING_H 6 | #define REDSTONE_SYSTEM_FACING_H 7 | 8 | #include "BlockPos.h" 9 | 10 | namespace Facing { 11 | enum Facing { 12 | DOWN, UP, NORTH, SOUTH, WEST, EAST, NONE // TODO: assuming same as Java edition 13 | }; 14 | const Facing OPPOSITE_FACING[7] = {UP, DOWN, SOUTH, NORTH, EAST, WEST, NONE}; 15 | const BlockPos DIRECTION[7] = {{0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}, {-1, 0, 0}, {1, 0, 0}, {0, 0, 0}}; 16 | } 17 | 18 | #endif //REDSTONE_SYSTEM_FACING_H 19 | -------------------------------------------------------------------------------- /components/ComponentType.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 11/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_COMPONENTTYPE_H 6 | #define REDSTONE_SYSTEM_COMPONENTTYPE_H 7 | 8 | enum ComponentType { 9 | TYPE_NULL = 0LL, 10 | TYPE_BASE = 1129534275LL, 11 | TYPE_RAIL_TRANSPORTER = 1296257106LL, 12 | TYPE_CONSUMER = 1129530179LL, 13 | TYPE_PRODUCER = 1129533507LL, 14 | TYPE_POWERED_BLOCK = 1129533506LL, 15 | TYPE_TRANSPORTER = 1129534546LL, 16 | TYPE_PISTON = 1296257097LL, 17 | TYPE_CAPACITOR = 1129530177LL, 18 | TYPE_PULSE_CAPACITOR = 1296257091LL, 19 | TYPE_COMPARATOR = 1296253778LL, 20 | TYPE_REPEATER = 1296257618LL, 21 | TYPE_REDSTONE_TORCH = 1296258115LL, 22 | }; 23 | 24 | #endif //REDSTONE_SYSTEM_COMPONENTTYPE_H 25 | -------------------------------------------------------------------------------- /CircuitTrackingInfo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "components/BaseCircuitComponent.h" 6 | #include "CircuitTrackingInfo.h" 7 | 8 | CircuitTrackingInfo::CircuitTrackingInfo(BaseCircuitComponent *component, BlockPos *pos, unsigned int a4) { 9 | field_84 = true; 10 | field_88 = 0; 11 | entry0.mPos = entry1.mPos = entry2.mPos = entry3.mPos = *pos; 12 | entry0.mComponent = entry1.mComponent = entry2.mComponent = entry3.mComponent = component; 13 | entry0.mComponentType = entry1.mComponentType = entry2.mComponentType = entry3.mComponentType = component->getInstanceType(); 14 | entry0.mDirection = entry1.mDirection = entry2.mDirection = entry3.mDirection = component->getDirection(); 15 | field_80 = a4; 16 | field_84 = true; 17 | field_88 = 0; 18 | } 19 | -------------------------------------------------------------------------------- /components/PistonConsumer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "PistonConsumer.h" 6 | 7 | bool PistonConsumer::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) { 8 | if (field_3F != trackingInfo->entry0.mDirection) { 9 | ComponentType componentType = trackingInfo->entry2.mComponentType; 10 | if (componentType == TYPE_CAPACITOR) { 11 | if (trackingInfo->entry0.mDirection == trackingInfo->entry2.mComponent->getDirection()) 12 | return false; 13 | } else if (componentType == TYPE_POWERED_BLOCK && !*a5) { 14 | return false; 15 | } 16 | trackPowerSource(trackingInfo, *a4, *a5, trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[getDirection()]); 17 | } 18 | return false; 19 | } 20 | -------------------------------------------------------------------------------- /components/CapacitorComponent.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_CAPACITORCOMPONENT_H 6 | #define REDSTONE_SYSTEM_CAPACITORCOMPONENT_H 7 | 8 | #include "ProducerComponent.h" 9 | 10 | class CapacitorComponent : public ProducerComponent { 11 | public: 12 | CapacitorComponent() = default; 13 | 14 | // VTABLE #1 15 | ~CapacitorComponent() override { 16 | // TODO: impl 17 | } 18 | 19 | // VTABLE #10 20 | ComponentType getBaseType() const override { 21 | return TYPE_CAPACITOR; 22 | } 23 | 24 | // VTABLE #11 25 | ComponentType getInstanceType() const override { 26 | return TYPE_CAPACITOR; 27 | } 28 | 29 | // VTABLE #24 30 | virtual Facing::Facing getPoweroutDirection() { 31 | return Facing::NONE; 32 | } 33 | }; 34 | 35 | #endif //REDSTONE_SYSTEM_CAPACITORCOMPONENT_H 36 | -------------------------------------------------------------------------------- /CircuitTrackingInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_CIRCUITTRACKINGINFO_H 6 | #define REDSTONE_SYSTEM_CIRCUITTRACKINGINFO_H 7 | 8 | class BaseCircuitComponent; 9 | 10 | #include "BlockPos.h" 11 | #include "Facing.h" 12 | #include "components/ComponentType.h" 13 | 14 | class CircuitTrackingInfo { 15 | public: 16 | struct Entry { 17 | BaseCircuitComponent *mComponent; // off = 0x0 18 | BlockPos mPos; // off = 0x8 19 | Facing::Facing mDirection; // off = 0x14 20 | ComponentType mComponentType; // off = 0x18 21 | }; 22 | 23 | Entry entry0; // off = 0x0 24 | Entry entry1; // off = 0x20 25 | Entry entry2; // off = 0x40 26 | Entry entry3; // off = 0x60 27 | int field_80; 28 | bool field_84; 29 | int field_88; 30 | 31 | CircuitTrackingInfo(BaseCircuitComponent *component, BlockPos *pos, unsigned int a4); 32 | }; 33 | 34 | #endif //REDSTONE_SYSTEM_CIRCUITTRACKINGINFO_H 35 | -------------------------------------------------------------------------------- /components/BaseRailTransporter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_BASERAILTRANSPORTER_H 6 | #define REDSTONE_SYSTEM_BASERAILTRANSPORTER_H 7 | 8 | #include "BaseCircuitComponent.h" 9 | 10 | class BaseRailTransporter : public BaseCircuitComponent { 11 | private: 12 | bool mRailType; // off = 0x3C 13 | public: 14 | BaseRailTransporter() { 15 | mRailType = false; 16 | } 17 | 18 | // VTABLE #1 19 | ~BaseRailTransporter() override { 20 | // TODO: impl 21 | } 22 | 23 | // VTABLE #10 24 | ComponentType getBaseType() const override { 25 | return TYPE_RAIL_TRANSPORTER; 26 | } 27 | 28 | // VTABLE #11 29 | ComponentType getInstanceType() const override { 30 | return TYPE_RAIL_TRANSPORTER; 31 | } 32 | 33 | // VTABLE #13 34 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 35 | 36 | // VTABLE #14 37 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 38 | 39 | // VTABLE #16 40 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override; 41 | 42 | private: 43 | bool sub_1F60A40(const CircuitTrackingInfo *trackingInfo, int a3, int a4); 44 | }; 45 | 46 | #endif //REDSTONE_SYSTEM_BASERAILTRANSPORTER_H 47 | -------------------------------------------------------------------------------- /components/PistonConsumer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_PISTONCONSUMER_H 6 | #define REDSTONE_SYSTEM_PISTONCONSUMER_H 7 | 8 | #include "ConsumerComponent.h" 9 | 10 | class PistonConsumer : public ConsumerComponent { 11 | private: 12 | Facing::Facing field_3F; 13 | public: 14 | PistonConsumer() { 15 | field_3F = Facing::NONE; 16 | } 17 | 18 | // VTABLE #1 19 | ~PistonConsumer() override { 20 | // TODO: impl 21 | } 22 | 23 | // VTABLE #6 24 | bool consumePowerAnyDirection() override { 25 | return true; 26 | } 27 | 28 | // VTABLE #11 29 | ComponentType getInstanceType() const override { 30 | return TYPE_PISTON; 31 | } 32 | 33 | // VTABLE #13 34 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 35 | 36 | // VTABLE #14 37 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override { 38 | return true; 39 | } 40 | 41 | void setBlockPowerFace(Facing::Facing face) { 42 | if (face == Facing::DOWN) { 43 | field_3F = Facing::UP; 44 | } else if (face == Facing::UP) { 45 | field_3F = Facing::DOWN; 46 | } else { 47 | field_3F = face; 48 | } 49 | } 50 | }; 51 | 52 | #endif //REDSTONE_SYSTEM_PISTONCONSUMER_H 53 | -------------------------------------------------------------------------------- /BlockPos.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_BLOCKPOS_H 6 | #define REDSTONE_SYSTEM_BLOCKPOS_H 7 | 8 | #include 9 | 10 | class BlockPos { 11 | public: 12 | int x, y, z; 13 | public: 14 | BlockPos() : x(0), y(0), z(0) {} 15 | BlockPos(int x, int y, int z) { 16 | this->x = x; 17 | this->y = y; 18 | this->z = z; 19 | } 20 | explicit BlockPos(BlockPos *other) { 21 | this->x = other->x; 22 | this->y = other->y; 23 | this->z = other->z; 24 | } 25 | bool operator==(const BlockPos &other) const noexcept { 26 | return x == other.x && y == other.y && z == other.z; 27 | } 28 | bool operator!=(const BlockPos &other) const noexcept { 29 | return !(*this == other); 30 | } 31 | BlockPos operator+(const BlockPos &pos) const noexcept { 32 | return {x + pos.x, y + pos.y, z + pos.z}; 33 | } 34 | BlockPos operator-(const BlockPos &pos) const noexcept { 35 | return {x - pos.x, y - pos.y, z - pos.z}; 36 | } 37 | BlockPos & operator=(const BlockPos &pos) noexcept = default; 38 | }; 39 | namespace std { 40 | template<> 41 | struct hash { 42 | size_t operator()(BlockPos const &pos) const noexcept { 43 | return static_cast(pos.z + 981131 * pos.y + 8976890 * pos.x); 44 | } 45 | }; 46 | } 47 | 48 | #endif //REDSTONE_SYSTEM_BLOCKPOS_H 49 | -------------------------------------------------------------------------------- /components/TransporterComponent.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_TRANSPORTERCOMPONENT_H 6 | #define REDSTONE_SYSTEM_TRANSPORTERCOMPONENT_H 7 | 8 | #include "BaseCircuitComponent.h" 9 | 10 | class TransporterComponent : public BaseCircuitComponent { 11 | private: 12 | int field_3C; 13 | public: 14 | TransporterComponent() { 15 | field_3C = 0; 16 | } 17 | 18 | // VTABLE #1 19 | ~TransporterComponent() override { 20 | // TODO: impl 21 | } 22 | 23 | // VTABLE #7 24 | bool canConsumePower() override { 25 | return true; 26 | } 27 | 28 | // VTABLE #10 29 | ComponentType getBaseType() const override { 30 | return TYPE_TRANSPORTER; 31 | } 32 | 33 | // VTABLE #11 34 | ComponentType getInstanceType() const override { 35 | return TYPE_TRANSPORTER; 36 | } 37 | 38 | // VTABLE #13 39 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 40 | 41 | // VTABLE #14 42 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 43 | 44 | // VTABLE #16 45 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override; 46 | 47 | // VTABLE #17 48 | void cacheValues(CircuitSystem *system, const BlockPos *pos) override; 49 | }; 50 | 51 | #endif //REDSTONE_SYSTEM_TRANSPORTERCOMPONENT_H 52 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | project(redstone_system) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(redstone_system 7 | BlockPos.h 8 | CircuitComponentList.h 9 | CircuitSceneGraph.h 10 | CircuitSystem.h 11 | CircuitTrackingInfo.cpp 12 | CircuitTrackingInfo.h 13 | components/BaseCircuitComponent.cpp 14 | components/BaseCircuitComponent.h 15 | components/BaseRailTransporter.cpp 16 | components/BaseRailTransporter.h 17 | components/CapacitorComponent.h 18 | components/ComparatorCapacitor.cpp 19 | components/ComparatorCapacitor.h 20 | components/ConsumerComponent.cpp 21 | components/ConsumerComponent.h 22 | components/PistonConsumer.cpp 23 | components/PistonConsumer.h 24 | components/PoweredBlockComponent.cpp 25 | components/PoweredBlockComponent.h 26 | components/ProducerComponent.cpp 27 | components/ProducerComponent.h 28 | components/PulseCapacitor.cpp 29 | components/PulseCapacitor.h 30 | components/RedstoneTorchCapacitor.cpp 31 | components/RedstoneTorchCapacitor.h 32 | components/RepeaterCapacitor.cpp 33 | components/RepeaterCapacitor.h 34 | components/TransporterComponent.cpp 35 | components/TransporterComponent.h 36 | Facing.h 37 | main.cpp components/ComponentType.h CircuitSceneGraph.cpp) -------------------------------------------------------------------------------- /CircuitSceneGraph.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_CIRCUITSCENEGRAPH_H 6 | #define REDSTONE_SYSTEM_CIRCUITSCENEGRAPH_H 7 | 8 | #include 9 | #include 10 | #include "BlockPos.h" 11 | #include "components/ComponentType.h" 12 | #include "CircuitComponentList.h" 13 | 14 | class BaseCircuitComponent; 15 | 16 | class CircuitSceneGraph : public std::unordered_map> { 17 | private: 18 | class PendingEntry { 19 | 20 | }; 21 | 22 | CircuitComponentList *field_38; 23 | std::unordered_map field_50; 24 | std::unordered_map field_88; 25 | std::unordered_map field_C0; 26 | std::unordered_map field_F8; 27 | std::unordered_map> field_130; 28 | std::vector field_168; 29 | public: 30 | CircuitSceneGraph() : 31 | field_38(), 32 | field_50(), 33 | field_88(), 34 | field_C0(), 35 | field_F8(), 36 | field_130(), 37 | field_168() { 38 | } 39 | 40 | BaseCircuitComponent *getBaseComponent(const BlockPos *pos) { 41 | auto it = find(*pos); 42 | if (it == end()) 43 | return nullptr; 44 | return it->second.get(); 45 | } 46 | BaseCircuitComponent *getComponent(const BlockPos *pos, ComponentType type); 47 | }; 48 | 49 | #endif //REDSTONE_SYSTEM_CIRCUITSCENEGRAPH_H 50 | -------------------------------------------------------------------------------- /components/ConsumerComponent.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_CONSUMERCOMPONENT_H 6 | #define REDSTONE_SYSTEM_CONSUMERCOMPONENT_H 7 | 8 | #include "BaseCircuitComponent.h" 9 | 10 | class ConsumerComponent : public BaseCircuitComponent { 11 | private: 12 | bool mSecondaryPowered; // off = 0x3B 13 | bool field_3C; 14 | bool field_3D; 15 | bool field_3E; 16 | public: 17 | ConsumerComponent() { 18 | mSecondaryPowered = false; 19 | field_3C = false; 20 | field_3D = false; 21 | field_3E = false; 22 | } 23 | 24 | // VTABLE #1 25 | ~ConsumerComponent() override { 26 | // TODO: impl 27 | } 28 | 29 | // VTABLE #7 30 | bool canConsumePower() override { 31 | return true; 32 | } 33 | 34 | // VTABLE #10 35 | ComponentType getBaseType() const override { 36 | return TYPE_CONSUMER; 37 | } 38 | 39 | // VTABLE #11 40 | ComponentType getInstanceType() const override { 41 | return TYPE_CONSUMER; 42 | } 43 | 44 | // VTABLE #13 45 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 46 | 47 | // VTABLE #14 48 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 49 | 50 | // VTABLE #16 51 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override; 52 | 53 | // VTABLE #23 54 | bool isSecondaryPowered() override { 55 | return mSecondaryPowered; 56 | } 57 | 58 | bool isPromotedToProducer() { 59 | // TODO: impl 60 | } 61 | }; 62 | 63 | #endif //REDSTONE_SYSTEM_CONSUMERCOMPONENT_H 64 | -------------------------------------------------------------------------------- /components/ProducerComponent.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_PRODUCERCOMPONENT_H 6 | #define REDSTONE_SYSTEM_PRODUCERCOMPONENT_H 7 | 8 | #include "BaseCircuitComponent.h" 9 | 10 | class ProducerComponent : public BaseCircuitComponent { 11 | protected: 12 | int field_3C; 13 | bool field_40; 14 | bool field_41; 15 | public: 16 | ProducerComponent() { 17 | field_3C = 0; 18 | field_41 = false; 19 | field_40 = false; 20 | } 21 | 22 | // VTABLE #1 23 | ~ProducerComponent() override { 24 | // TODO: impl 25 | } 26 | 27 | // VTABLE #4 28 | void setStrength(int strength) override { 29 | field_3C = strength; 30 | if (field_21) { 31 | mStrength = strength; 32 | } 33 | } 34 | 35 | // VTABLE #8 36 | bool canStopPower() override { 37 | return field_41; 38 | } 39 | 40 | // VTABLE #9 41 | void setStopPower(bool stopPower) override { 42 | field_41 = stopPower; 43 | } 44 | 45 | // VTABLE #10 46 | ComponentType getBaseType() const override { 47 | return TYPE_PRODUCER; 48 | } 49 | 50 | // VTABLE #11 51 | ComponentType getInstanceType() const override { 52 | return TYPE_PRODUCER; 53 | } 54 | 55 | // VTABLE #14 56 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 57 | 58 | // VTABLE #16 59 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override; 60 | 61 | void allowAttachments(bool allowAttachments) { 62 | field_40 = allowAttachments; 63 | } 64 | 65 | bool doesAllowAttachments() { 66 | return field_40; 67 | } 68 | }; 69 | 70 | #endif //REDSTONE_SYSTEM_PRODUCERCOMPONENT_H 71 | -------------------------------------------------------------------------------- /components/PulseCapacitor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_PULSECAPACITOR_H 6 | #define REDSTONE_SYSTEM_PULSECAPACITOR_H 7 | 8 | #include "CapacitorComponent.h" 9 | #include "../Facing.h" 10 | 11 | class PulseCapacitor : public CapacitorComponent { 12 | private: 13 | bool field_42; 14 | bool field_43; 15 | public: 16 | PulseCapacitor() { 17 | field_42 = false; 18 | field_43 = false; 19 | } 20 | 21 | // VTABLE #1 22 | ~PulseCapacitor() override { 23 | // TODO: impl 24 | } 25 | 26 | // VTABLE #2 27 | int getStrength() override { 28 | return mStrength; 29 | } 30 | 31 | // VTABLE #4 32 | void setStrength(int strength) override { 33 | field_3C = strength; 34 | field_43 = strength != 0; 35 | } 36 | 37 | // VTABLE #6 38 | bool consumePowerAnyDirection() override { 39 | return false; 40 | } 41 | 42 | // VTABLE #7 43 | bool canConsumePower() override { 44 | return false; 45 | } 46 | 47 | // VTABLE #11 48 | ComponentType getInstanceType() const override { 49 | return TYPE_PULSE_CAPACITOR; 50 | } 51 | 52 | // VTABLE #14 53 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 54 | 55 | // VTABLE #16 56 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override { 57 | ProducerComponent::evaluate(system, pos); 58 | field_42 = field_43; 59 | field_43 = false; 60 | field_3C = 0; 61 | return field_42; 62 | } 63 | 64 | // VTABLE #24 65 | Facing::Facing getPoweroutDirection() override { 66 | return Facing::OPPOSITE_FACING[getDirection()]; 67 | } 68 | }; 69 | 70 | #endif //REDSTONE_SYSTEM_PULSECAPACITOR_H 71 | -------------------------------------------------------------------------------- /components/PoweredBlockComponent.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_POWEREDBLOCKCOMPONENT_H 6 | #define REDSTONE_SYSTEM_POWEREDBLOCKCOMPONENT_H 7 | 8 | #include "BaseCircuitComponent.h" 9 | 10 | // Seems to be e.g. stone powered by a repeater. Not a redstone block. 11 | class PoweredBlockComponent : public BaseCircuitComponent { 12 | private: 13 | bool mPromotedToProducer; // off = 0x3B 14 | bool field_3C; 15 | public: 16 | PoweredBlockComponent() { 17 | mPromotedToProducer = false; 18 | field_3C = true; 19 | field_21 = false; 20 | } 21 | 22 | // VTABLE #1 23 | ~PoweredBlockComponent() override { 24 | // TODO: impl 25 | } 26 | 27 | // VTABLE #2 28 | int getStrength() override; 29 | 30 | // VTABLE #7 31 | bool canConsumePower() override { 32 | return true; 33 | } 34 | 35 | // VTABLE #10 36 | ComponentType getBaseType() const override { 37 | return TYPE_POWERED_BLOCK; 38 | } 39 | 40 | // VTABLE #11 41 | ComponentType getInstanceType() const override { 42 | return TYPE_POWERED_BLOCK; 43 | } 44 | 45 | // VTABLE #13 46 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 47 | 48 | // VTABLE #14 49 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 50 | 51 | // VTABLE #16 52 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override { 53 | return false; 54 | } 55 | 56 | // VTABLE #22 57 | bool hasChildrenSource() override { 58 | return true; 59 | } 60 | 61 | bool isPromotedToProducer() { 62 | return mPromotedToProducer; 63 | } 64 | }; 65 | 66 | #endif //REDSTONE_SYSTEM_POWEREDBLOCKCOMPONENT_H 67 | -------------------------------------------------------------------------------- /components/ComparatorCapacitor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_COMPARATORCAPACITOR_H 6 | #define REDSTONE_SYSTEM_COMPARATORCAPACITOR_H 7 | 8 | #include "CapacitorComponent.h" 9 | #include "../Facing.h" 10 | 11 | class ComparatorCapacitor : public CapacitorComponent { 12 | private: 13 | int field_44; 14 | int field_48; 15 | int field_4C; 16 | int field_50; 17 | bool mSubtractMode; // off = 0x54 18 | int mCachedRearStrength; // off = 0x58 19 | int mCachedSideStrength; // off = 0x5C 20 | int field_60; 21 | CircuitComponentList *mSideDependencies; // off = 0x64 22 | public: 23 | ComparatorCapacitor(); 24 | 25 | // VTABLE #1 26 | ~ComparatorCapacitor() override { 27 | delete mSideDependencies; 28 | } 29 | 30 | // VTABLE #6 31 | bool consumePowerAnyDirection() override { 32 | return true; 33 | } 34 | 35 | // VTABLE #7 36 | bool canConsumePower() override { 37 | return true; 38 | } 39 | 40 | // VTABLE #11 41 | ComponentType getInstanceType() const override { 42 | return TYPE_COMPARATOR; 43 | } 44 | 45 | // VTABLE #12 46 | bool removeSource(const BlockPos *pos, const BaseCircuitComponent *component) override; 47 | 48 | // VTABLE #13 49 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 50 | 51 | // VTABLE #14 52 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 53 | 54 | // VTABLE #17 55 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override; 56 | 57 | // VTABLE #18 58 | void cacheValues(CircuitSystem *system, const BlockPos *pos) override; 59 | 60 | // VTABLE #19 61 | void updateDependencies(CircuitSceneGraph *graph, const BlockPos *pos) override; 62 | 63 | // VTABLE #24 64 | Facing::Facing getPoweroutDirection() override { 65 | return Facing::OPPOSITE_FACING[getDirection()]; 66 | } 67 | 68 | private: 69 | int GetRearStrength() { 70 | if (field_44 == -1) 71 | return mCachedRearStrength; 72 | else 73 | return field_44; 74 | } 75 | 76 | int GetSideStrength() { 77 | if (field_48 == -1) 78 | return mCachedSideStrength; 79 | else 80 | return std::max(field_48, field_4C); 81 | } 82 | }; 83 | 84 | #endif //REDSTONE_SYSTEM_COMPARATORCAPACITOR_H 85 | -------------------------------------------------------------------------------- /CircuitComponentList.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_CIRCUITCOMPONENTLIST_H 6 | #define REDSTONE_SYSTEM_CIRCUITCOMPONENTLIST_H 7 | 8 | #include 9 | #include "BlockPos.h" 10 | #include "Facing.h" 11 | 12 | class BaseCircuitComponent; 13 | 14 | class CircuitComponentList { 15 | public: 16 | class Item { 17 | public: 18 | BaseCircuitComponent *mComponent; // off = 0x0 19 | int field_8; 20 | BlockPos mPos; // off = 0xC 21 | Facing::Facing mDirection; // off = 0x18 22 | bool field_19; 23 | int field_1C; 24 | 25 | Item() : 26 | mComponent(nullptr), 27 | field_8(0), 28 | mPos(), 29 | mDirection(Facing::NONE), 30 | field_19(false), 31 | field_1C(0) { 32 | } 33 | Item(BaseCircuitComponent *component, int i, BlockPos *pos) : 34 | mComponent(component), 35 | field_8(i), 36 | mPos(pos), 37 | mDirection(Facing::NONE), 38 | field_19(false), 39 | field_1C(0) { 40 | } 41 | explicit Item(Item* other) : 42 | mComponent(other->mComponent), 43 | field_8(other->field_8), 44 | mPos(other->mPos), 45 | mDirection(other->mDirection), 46 | field_19(other->field_19), 47 | field_1C(other->field_1C) { 48 | } 49 | }; 50 | 51 | typedef std::vector::iterator iterator; 52 | 53 | private: 54 | std::vector items; 55 | 56 | public: 57 | void add(BaseCircuitComponent *component, int i, BlockPos *pos) { 58 | items.push_back(Item(component, i, pos)); 59 | } 60 | 61 | iterator begin() { 62 | return items.begin(); 63 | } 64 | 65 | iterator end() { 66 | return items.end(); 67 | } 68 | 69 | iterator erase(iterator item) { 70 | return items.erase(item); 71 | } 72 | 73 | auto push_back(Item *item) { 74 | return items.push_back(Item(item)); 75 | } 76 | 77 | auto at(size_t index) { 78 | return items.at(index); 79 | } 80 | 81 | bool removeSource(const BlockPos *a2, const BaseCircuitComponent *a3) { 82 | bool erasedAny = false; 83 | for (auto it = items.begin(); it != items.end();) { 84 | if (it->mPos == *a2) { 85 | it = items.erase(it); 86 | erasedAny = true; 87 | } else { 88 | ++it; 89 | } 90 | } 91 | return erasedAny; 92 | } 93 | 94 | auto size() { 95 | return items.size(); 96 | } 97 | }; 98 | 99 | #endif //REDSTONE_SYSTEM_CIRCUITCOMPONENTLIST_H 100 | -------------------------------------------------------------------------------- /components/PoweredBlockComponent.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "PoweredBlockComponent.h" 6 | #include "ProducerComponent.h" 7 | #include "CapacitorComponent.h" 8 | 9 | int PoweredBlockComponent::getStrength() { 10 | int maxStrength = 0; 11 | for (size_t i = 0; i < mDependencies->size(); i++) { 12 | CircuitComponentList::Item item = mDependencies->at(i); 13 | int strength = item.mComponent->getStrength() - item.field_8; 14 | if (strength < 0) 15 | strength = 0; 16 | if (maxStrength < strength) 17 | maxStrength = strength; 18 | } 19 | return maxStrength; 20 | } 21 | 22 | bool PoweredBlockComponent::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, 23 | bool *a5) { 24 | if (!field_3C) 25 | return false; 26 | 27 | ComponentType componentType = trackingInfo->entry2.mComponentType; 28 | 29 | if (mAllowPowerUp) 30 | return false; 31 | 32 | mPromotedToProducer = false; 33 | 34 | if (componentType == TYPE_CONSUMER || componentType == TYPE_POWERED_BLOCK) { 35 | *a5 = false; 36 | return false; 37 | } 38 | 39 | switch (componentType) { 40 | case TYPE_PRODUCER: { 41 | auto *producer = dynamic_cast(trackingInfo->entry2.mComponent); 42 | bool powered = producer->doesAllowAttachments() && trackingInfo->entry0.mDirection == producer->getDirection(); 43 | *a5 = powered; 44 | mPromotedToProducer = powered; 45 | break; 46 | } 47 | case TYPE_CAPACITOR: { 48 | auto *capacitor = dynamic_cast(trackingInfo->entry2.mComponent); 49 | bool powered = trackingInfo->entry0.mDirection == capacitor->getPoweroutDirection(); 50 | *a5 = powered; 51 | mPromotedToProducer = powered; 52 | if (!mPromotedToProducer && capacitor->getInstanceType() == TYPE_REDSTONE_TORCH) { 53 | return false; 54 | } 55 | break; 56 | } 57 | case TYPE_TRANSPORTER: { 58 | *a5 |= trackingInfo->entry2.mDirection == trackingInfo->entry0.mDirection 59 | && trackingInfo->entry2.mPos.y == trackingInfo->entry0.mPos.y; 60 | *a5 |= trackingInfo->entry0.mDirection == Facing::DOWN; 61 | break; 62 | } 63 | default: { 64 | break; 65 | } 66 | } 67 | return trackPowerSource(trackingInfo, *a4, *a5, false); 68 | } 69 | 70 | bool PoweredBlockComponent::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, 71 | bool *a4) { 72 | if (trackingInfo->entry0.mComponentType == TYPE_TRANSPORTER) 73 | return mPromotedToProducer; 74 | else 75 | return trackingInfo->entry0.mComponentType != TYPE_POWERED_BLOCK; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /components/BaseRailTransporter.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "BaseRailTransporter.h" 6 | #include "../Facing.h" 7 | 8 | bool BaseRailTransporter::sub_1F60A40(const CircuitTrackingInfo *trackingInfo, int a3, int a4) { 9 | for (auto &item : *mDependencies) { 10 | if (item.mPos == trackingInfo->entry1.mPos) { 11 | return false; 12 | } 13 | } 14 | 15 | CircuitComponentList::Item item; 16 | item.field_8 = a3 - 1 < 0 ? 0 : a3 - 1; 17 | item.mPos = trackingInfo->entry1.mPos; 18 | item.mDirection = trackingInfo->entry0.mDirection; 19 | item.field_19 = true; 20 | item.mComponent = trackingInfo->entry1.mComponent; 21 | item.field_1C = a4 - 1 < 0 ? 0 : a4 - 1; 22 | mDependencies->push_back(&item); 23 | return true; 24 | } 25 | 26 | bool BaseRailTransporter::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, 27 | bool *a5) { 28 | if (!*a5) 29 | return false; 30 | 31 | const BaseCircuitComponent *component = trackingInfo->entry2.mComponent; 32 | auto oldSize = mDependencies->size(); 33 | int v13 = 0; 34 | bool v19 = *a5; 35 | *a5 = true; 36 | switch (component->getInstanceType()) { 37 | case TYPE_RAIL_TRANSPORTER: { 38 | CircuitTrackingInfo trackingInfo1 = *trackingInfo; 39 | for (auto &item : *component->mDependencies) { 40 | if (item.field_1C - 1 > 0) { 41 | BlockPos pos = item.mPos; // TODO: wat 42 | int v18 = item.field_1C; 43 | sub_1F60A40(&trackingInfo1, item.field_8 + 1, v18); 44 | if (v18 > v13) 45 | v13 = v18; 46 | } 47 | } 48 | return mDependencies->size() != oldSize; 49 | } 50 | case TYPE_POWERED_BLOCK: { 51 | return v19 && sub_1F60A40(trackingInfo, *a4, 10); 52 | } 53 | case TYPE_TRANSPORTER: 54 | default: { 55 | return sub_1F60A40(trackingInfo, *a4, 10); 56 | } 57 | } 58 | } 59 | 60 | bool BaseRailTransporter::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, 61 | bool *a4) { 62 | if (trackingInfo->entry0.mComponent->getInstanceType() != TYPE_RAIL_TRANSPORTER 63 | || mRailType != dynamic_cast(trackingInfo->entry0.mComponent)->mRailType) { 64 | return false; 65 | } 66 | 67 | if (trackingInfo->entry0.mComponent->getDirection() != mDirection) { 68 | return false; 69 | } 70 | 71 | if (trackingInfo->entry0.mDirection == mDirection) { 72 | return true; 73 | } 74 | 75 | return Facing::OPPOSITE_FACING[mDirection] == trackingInfo->entry0.mDirection; 76 | } 77 | 78 | bool BaseRailTransporter::evaluate(CircuitSystem *system, const BlockPos *pos) { 79 | int oldVal = mStrength; 80 | 81 | for (auto &item : *mDependencies) { 82 | int v4 = item.field_1C; 83 | if (v4 > mStrength && item.mComponent && item.mComponent->getStrength() - item.field_8 > 0) { 84 | mStrength = v4; 85 | } 86 | } 87 | 88 | return mStrength != oldVal; 89 | } 90 | -------------------------------------------------------------------------------- /components/RedstoneTorchCapacitor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_RESTONETORCHCAPACITOR_H 6 | #define REDSTONE_SYSTEM_RESTONETORCHCAPACITOR_H 7 | 8 | #include "CapacitorComponent.h" 9 | #include "../Facing.h" 10 | 11 | class RedstoneTorchCapacitor : public CapacitorComponent { 12 | private: 13 | RedstoneTorchCapacitor *mNextInQueue; // off = 0x48 14 | int mSelfPowerCount; // off = 0x50 15 | bool field_54; 16 | bool mHalfPulse; // off = 0x55 17 | bool field_56; 18 | bool field_57; 19 | bool field_58; 20 | bool field_59; 21 | bool field_5A; 22 | public: 23 | RedstoneTorchCapacitor() { 24 | mNextInQueue = nullptr; 25 | mSelfPowerCount = 0; 26 | field_5A = false; 27 | field_58 = false; 28 | mHalfPulse = false; 29 | field_57 = false; 30 | field_54 = false; 31 | setAllowPowerUp(true); 32 | } 33 | 34 | // VTABLE #1 35 | ~RedstoneTorchCapacitor() override { 36 | // TODO: impl 37 | } 38 | 39 | // VTABLE #2 40 | int getStrength() override { 41 | return field_54 ? 15 : 0; 42 | } 43 | 44 | // VTABLE #11 45 | ComponentType getInstanceType() const override { 46 | return TYPE_REDSTONE_TORCH; 47 | } 48 | 49 | // VTABLE #12 50 | bool removeSource(const BlockPos *pos, const BaseCircuitComponent *component) override { 51 | bool result = BaseCircuitComponent::removeSource(pos, component); 52 | if (mNextInQueue == component && mNextInQueue) { 53 | mNextInQueue = mNextInQueue->mNextInQueue; 54 | return true; 55 | } else { 56 | return result; 57 | } 58 | } 59 | 60 | // VTABLE #13 61 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 62 | 63 | // VTABLE #14 64 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 65 | 66 | // VTABLE #16 67 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override { 68 | field_54 = field_57; 69 | field_56 = field_59; 70 | if (mNextInQueue && _canIncrementSelfPower()) { 71 | mSelfPowerCount++; 72 | } 73 | return field_56; 74 | } 75 | 76 | // VTABLE #17 77 | void cacheValues(CircuitSystem *system, const BlockPos *pos) override; 78 | 79 | // VTABLE #18 80 | void updateDependencies(CircuitSceneGraph *graph, const BlockPos *pos) override; 81 | 82 | // VTABLE #20 83 | bool isHalfPulse() override { 84 | return mHalfPulse; 85 | } 86 | 87 | // VTABLE #24 88 | Facing::Facing getPoweroutDirection() override { 89 | return Facing::UP; 90 | } 91 | 92 | void setSelfPowerCount(int selfPowerCount) { 93 | mSelfPowerCount = selfPowerCount; 94 | } 95 | 96 | void setNextInQueue(RedstoneTorchCapacitor *torch) { 97 | mNextInQueue = torch; 98 | } 99 | 100 | private: 101 | bool _canIncrementSelfPower() { 102 | return !field_5A && mSelfPowerCount <= 32; 103 | } 104 | 105 | int FindStrongestStrength(const BlockPos *pos, CircuitSystem *system, bool *a4); 106 | }; 107 | 108 | #endif //REDSTONE_SYSTEM_RESTONETORCHCAPACITOR_H 109 | -------------------------------------------------------------------------------- /components/RepeaterCapacitor.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "RepeaterCapacitor.h" 6 | 7 | RepeaterCapacitor::RepeaterCapacitor() { 8 | field_58 = 0; 9 | mOn = false; 10 | field_5D = false; 11 | field_5E = true; 12 | field_60 = 0; 13 | field_64 = false; 14 | field_65 = false; 15 | field_68 = new CircuitComponentList; 16 | for (int i = 0; i < 4; i++) 17 | field_44[i] = 2; 18 | } 19 | 20 | bool RepeaterCapacitor::removeSource(const BlockPos *pos, const BaseCircuitComponent *component) { 21 | bool baseRemoved = BaseCircuitComponent::removeSource(pos, component); 22 | bool repeaterRemoved = field_68->removeSource(pos, component); 23 | return baseRemoved || repeaterRemoved; 24 | } 25 | 26 | bool RepeaterCapacitor::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, 27 | bool *a5) { 28 | bool sameDir = trackingInfo->entry0.mDirection == getDirection(); 29 | bool oppositeDir = trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[getDirection()]; 30 | if ((trackingInfo->entry2.mComponentType != TYPE_POWERED_BLOCK || (trackingInfo->entry2.mComponent->hasDirectPower() && *a5)) && !sameDir) { 31 | ComponentType componentType = trackingInfo->entry2.mComponent->getInstanceType(); 32 | if (oppositeDir || componentType == TYPE_REPEATER || componentType == TYPE_COMPARATOR) 33 | trackPowerSource(trackingInfo, *a4, *a5, oppositeDir); 34 | } 35 | return false; 36 | } 37 | 38 | bool RepeaterCapacitor::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) { 39 | return trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[getDirection()]; 40 | } 41 | 42 | void RepeaterCapacitor::checkLock() { 43 | field_5E = false; 44 | for (auto &item : *field_68) { 45 | int v10 = item.mComponent->getStrength() - item.field_8; 46 | v10 = std::max(v10, 0); 47 | if (v10 > 0) { 48 | field_5E = true; 49 | for (int i = 1; i < 4; i++) { 50 | field_44[i] = field_44[0]; 51 | } 52 | return; 53 | } 54 | } 55 | } 56 | 57 | bool RepeaterCapacitor::evaluate(CircuitSystem *system, const BlockPos *pos) { 58 | bool oldVal = mOn; 59 | if (!field_5E) { 60 | delayPulse(field_5D); 61 | if (field_58 > 0) { 62 | if (field_60 > field_58 && !(field_64 && field_60 == 2)) { 63 | alternatePulse(); 64 | } else { 65 | extendPulse(); 66 | } 67 | } 68 | mOn = field_44[0] == 1 || field_44[0] == 3; 69 | } 70 | return oldVal != mOn; 71 | } 72 | 73 | void RepeaterCapacitor::cacheValues(CircuitSystem *system, const BlockPos *pos) { 74 | field_5D = false; 75 | for (auto &item : *mDependencies) { 76 | int v9 = item.mComponent->getStrength() - item.field_8; 77 | v9 = std::max(v9, 0); 78 | if (v9 > 0) { 79 | field_5D = true; 80 | break; 81 | } 82 | } 83 | 84 | if (!field_5E) { 85 | if (field_64 == field_5D) { 86 | field_60 = 0; 87 | } else { 88 | field_60++; 89 | if (field_60 == 1) { 90 | field_65 = !field_64; 91 | } 92 | field_64 = !field_64; 93 | } 94 | } 95 | } 96 | 97 | void RepeaterCapacitor::updateDependencies(CircuitSceneGraph *graph, const BlockPos *pos) { 98 | for (auto it = mDependencies->begin(); it != mDependencies->end();) { 99 | if (it->field_1C == 1) { 100 | ++it; 101 | } else { 102 | BlockPos tmp = it->mPos; 103 | field_68->add(it->mComponent, it->field_8, &tmp); 104 | it = mDependencies->erase(it); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /components/ConsumerComponent.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "ConsumerComponent.h" 6 | #include "ProducerComponent.h" 7 | #include "../Facing.h" 8 | #include "CapacitorComponent.h" 9 | 10 | bool ConsumerComponent::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, 11 | bool *a5) { 12 | bool v15 = *a5; 13 | *a5 = false; 14 | field_3D = false; 15 | 16 | long componentType = trackingInfo->entry2.mComponentType; 17 | if (componentType == TYPE_POWERED_BLOCK && !v15) 18 | return false; 19 | 20 | if (field_3C) { 21 | switch (componentType) { 22 | case TYPE_PRODUCER: { 23 | auto *producer = dynamic_cast(trackingInfo->entry2.mComponent); 24 | bool attached = producer->doesAllowAttachments() 25 | && trackingInfo->entry0.mDirection == producer->getDirection(); 26 | *a5 = attached; 27 | field_3D = attached; 28 | break; 29 | } 30 | case TYPE_CAPACITOR: { 31 | *a5 = trackingInfo->entry0.mDirection == Facing::UP; 32 | Facing::Facing v13 = trackingInfo->entry2.mComponent->getDirection(); 33 | if (v13 != Facing::NONE) { 34 | auto *capacitor = dynamic_cast(trackingInfo->entry2.mComponent); 35 | if (capacitor->getPoweroutDirection() != Facing::NONE) { 36 | v13 = capacitor->getPoweroutDirection(); 37 | } 38 | bool attached = trackingInfo->entry0.mDirection == v13; 39 | *a5 = attached; 40 | field_3D = attached; 41 | } 42 | if (trackingInfo->entry0.mDirection == trackingInfo->entry2.mComponent->getDirection()) 43 | return false; 44 | break; 45 | } 46 | case TYPE_TRANSPORTER: { 47 | *a5 = true; 48 | break; 49 | } 50 | default: { 51 | break; 52 | } 53 | } 54 | } 55 | 56 | bool result = false; 57 | if (trackPowerSource(trackingInfo, *a4, *a5, componentType == TYPE_CONSUMER)) 58 | result = *a5; 59 | return result; 60 | } 61 | 62 | bool ConsumerComponent::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) { 63 | long componentType = trackingInfo->entry0.mComponentType; 64 | if (componentType != TYPE_CAPACITOR) { 65 | if (componentType == TYPE_TRANSPORTER && field_3C) { 66 | return field_3D; 67 | } else { 68 | return trackingInfo->field_84; 69 | } 70 | } 71 | 72 | auto *capacitor = dynamic_cast(trackingInfo->entry0.mComponent); 73 | Facing::Facing dir = capacitor->getPoweroutDirection(); 74 | if (dir == Facing::NONE) { 75 | if (trackingInfo->entry0.mDirection != Facing::UP) { 76 | return false; 77 | } else { 78 | return trackingInfo->field_84; 79 | } 80 | } 81 | if (trackingInfo->entry0.mDirection == dir) { 82 | return trackingInfo->field_84; 83 | } else { 84 | return false; 85 | } 86 | } 87 | 88 | bool ConsumerComponent::evaluate(CircuitSystem *system, const BlockPos *pos) { 89 | mSecondaryPowered = false; 90 | 91 | int v11 = 0; 92 | for (auto &it : *mDependencies) { 93 | int v6 = it.mComponent->getStrength() - it.field_8; 94 | if (it.mComponent->isHalfPulse() && !field_3E) { 95 | v6 = 15 - it.field_8; 96 | } 97 | if (v6 < 0) { 98 | v6 = 0; 99 | } 100 | if (v11 < v6) { 101 | mSecondaryPowered = it.field_1C == 1; 102 | v11 = v6; 103 | } 104 | } 105 | 106 | bool v3 = mStrength != v11; 107 | mStrength = v11; 108 | return v3 || field_21; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /components/BaseCircuitComponent.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_BASECIRCUITCOMPONENT_H 6 | #define REDSTONE_SYSTEM_BASECIRCUITCOMPONENT_H 7 | 8 | #include "ComponentType.h" 9 | #include "../BlockPos.h" 10 | #include "../CircuitComponentList.h" 11 | #include "../CircuitTrackingInfo.h" 12 | #include "../CircuitSceneGraph.h" 13 | #include "../CircuitSystem.h" 14 | #include "../Facing.h" 15 | 16 | class BaseCircuitComponent { 17 | public: 18 | CircuitComponentList *mDependencies; // off = 0x8 19 | bool field_20; 20 | bool field_21; 21 | bool field_22; 22 | BlockPos field_24; 23 | bool field_30; 24 | int mStrength; // off = 0x34 25 | Facing::Facing mDirection; // off = 0x38 26 | bool mAllowPowerUp; // off = 0x39 27 | bool mAllowPowerDown; // off = 0x3A 28 | public: 29 | BaseCircuitComponent(); 30 | 31 | // VTABLE #1 32 | virtual ~BaseCircuitComponent(); 33 | 34 | // VTABLE #2 35 | virtual int getStrength() { 36 | return mStrength; 37 | } 38 | 39 | // VTABLE #3 40 | virtual Facing::Facing getDirection() { 41 | return mDirection; 42 | } 43 | 44 | // VTABLE #4 45 | virtual void setStrength(int strength) { 46 | mStrength = strength; 47 | } 48 | 49 | // VTABLE #5 50 | virtual void setDirection(Facing::Facing dir) { 51 | mDirection = dir; 52 | } 53 | 54 | // VTABLE #6 55 | virtual bool consumePowerAnyDirection() { 56 | return false; 57 | } 58 | 59 | // VTABLE #7 60 | virtual bool canConsumePower() { 61 | return false; 62 | } 63 | 64 | // VTABLE #8 65 | virtual bool canStopPower() { 66 | return false; 67 | } 68 | 69 | // VTABLE #9 70 | virtual void setStopPower(bool stopPower) { 71 | } 72 | 73 | // VTABLE #10 74 | virtual ComponentType getBaseType() const { 75 | return TYPE_BASE; 76 | } 77 | 78 | // VTABLE #11 79 | virtual ComponentType getInstanceType() const { 80 | return TYPE_BASE; 81 | } 82 | 83 | // VTABLE #12 84 | virtual bool removeSource(const BlockPos *pos, const BaseCircuitComponent *component); 85 | 86 | // VTABLE #13 87 | virtual bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) { 88 | return false; 89 | } 90 | 91 | // VTABLE #14 92 | virtual bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) { 93 | return true; 94 | } 95 | 96 | // VTABLE #15 97 | virtual void checkLock() { 98 | } 99 | 100 | // VTABLE #16 101 | virtual bool evaluate(CircuitSystem *system, const BlockPos *pos) { 102 | return false; 103 | } 104 | 105 | // VTABLE #17 106 | virtual void cacheValues(CircuitSystem *system, const BlockPos *pos) { 107 | } 108 | 109 | // VTABLE #18 110 | virtual void updateDependencies(CircuitSceneGraph *graph, const BlockPos *pos) { 111 | } 112 | 113 | // VTABLE #19 114 | virtual bool allowIndirect() { 115 | return false; 116 | } 117 | 118 | // VTABLE #20 119 | virtual bool isHalfPulse() { 120 | return false; 121 | } 122 | 123 | // VTABLE #21 124 | virtual bool hasSource(BaseCircuitComponent *component); 125 | 126 | // VTABLE #22 127 | virtual bool hasChildrenSource() { 128 | return false; 129 | } 130 | 131 | // VTABLE #23 132 | virtual bool isSecondaryPowered() { 133 | return false; 134 | } 135 | 136 | void setAllowPowerUp(bool allowPowerUp) { 137 | mAllowPowerUp = allowPowerUp; 138 | } 139 | 140 | bool canAllowPowerUp() { 141 | return mAllowPowerUp; 142 | } 143 | 144 | bool canAllowPowerDown() { 145 | return mAllowPowerDown; 146 | } 147 | 148 | bool trackPowerSource(const CircuitTrackingInfo *trackingInfo, int a3, bool a4, bool a5); 149 | 150 | bool trackPowerSourceDuplicates(const CircuitTrackingInfo *trackingInfo, int a3, bool a4); 151 | 152 | bool hasDirectPower(); 153 | }; 154 | 155 | #endif //REDSTONE_SYSTEM_BASECIRCUITCOMPONENT_H 156 | -------------------------------------------------------------------------------- /components/ComparatorCapacitor.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "ComparatorCapacitor.h" 6 | 7 | ComparatorCapacitor::ComparatorCapacitor() { 8 | field_44 = -1; 9 | field_48 = -1; 10 | field_4C = -1; 11 | field_50 = 0; 12 | mSubtractMode = false; 13 | mCachedRearStrength = 0; 14 | mCachedSideStrength = 0; 15 | field_60 = 0; 16 | mSideDependencies = new CircuitComponentList; 17 | } 18 | 19 | bool ComparatorCapacitor::removeSource(const BlockPos *pos, const BaseCircuitComponent *component) { 20 | bool baseRemoved = BaseCircuitComponent::removeSource(pos, component); 21 | bool comparatorRemoved = mSideDependencies->removeSource(pos, component); 22 | return baseRemoved || comparatorRemoved; 23 | } 24 | 25 | bool ComparatorCapacitor::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, 26 | bool *a5) { 27 | if (trackingInfo->entry0.mDirection != Facing::DOWN && trackingInfo->entry0.mDirection != Facing::UP) { 28 | if (trackingInfo->entry0.mDirection != getDirection()) { 29 | bool connected; 30 | if (trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[getDirection()]) { 31 | connected = true; 32 | } else { 33 | ComponentType componentType = trackingInfo->entry2.mComponent->getInstanceType(); 34 | connected = componentType == TYPE_TRANSPORTER || componentType == TYPE_REPEATER || componentType == TYPE_COMPARATOR; 35 | } 36 | if (connected) { 37 | if (trackingInfo->entry2.mComponentType != TYPE_POWERED_BLOCK || trackingInfo->entry2.mComponent->hasDirectPower()) { 38 | trackPowerSourceDuplicates(trackingInfo, *a4, *a5); 39 | } 40 | } 41 | } 42 | } 43 | return false; 44 | } 45 | 46 | bool ComparatorCapacitor::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, 47 | bool *a4) { 48 | return trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[getDirection()]; 49 | } 50 | 51 | bool ComparatorCapacitor::evaluate(CircuitSystem *system, const BlockPos *pos) { 52 | field_50 = mStrength; 53 | if (mSubtractMode) { 54 | mStrength = std::max(GetRearStrength() - GetSideStrength(), 0); 55 | } else { 56 | mStrength = GetRearStrength(); 57 | if (GetSideStrength() > mStrength) { 58 | mStrength = 0; 59 | } 60 | } 61 | mStrength = std::min(mStrength, 15); 62 | return field_50 != mStrength; 63 | } 64 | 65 | void ComparatorCapacitor::cacheValues(CircuitSystem *system, const BlockPos *pos) { 66 | if (!field_60) 67 | return; 68 | 69 | mCachedRearStrength = 0; 70 | mCachedSideStrength = 0; 71 | 72 | for (auto &item : *mDependencies) { 73 | if (item.field_19) { 74 | int strength = item.mComponent->getStrength() - item.field_8; 75 | strength = std::max(strength, 0); 76 | if (strength > mCachedRearStrength) 77 | mCachedRearStrength = strength; 78 | } 79 | } 80 | 81 | for (auto &item : *mSideDependencies) { 82 | int strength = item.mComponent->getStrength() - item.field_8; 83 | strength = std::max(strength, 0); 84 | if (strength > mCachedSideStrength) 85 | mCachedSideStrength = strength; 86 | } 87 | } 88 | 89 | void ComparatorCapacitor::updateDependencies(CircuitSceneGraph *graph, const BlockPos *pos) { 90 | for (auto it = mDependencies->begin(); it != mDependencies->end();) { 91 | if (it->mComponent->canStopPower()) { 92 | it = mDependencies->erase(it); 93 | } else { 94 | if (it->mComponent->getDirection() == Facing::OPPOSITE_FACING[getDirection()]) { 95 | ++it; 96 | } else { 97 | BlockPos tmp = it->mPos; 98 | mSideDependencies->add(it->mComponent, it->field_8, &tmp); 99 | it = mDependencies->erase(it); 100 | } 101 | } 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /components/RepeaterCapacitor.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #ifndef REDSTONE_SYSTEM_REPEATERCAPACITOR_H 6 | #define REDSTONE_SYSTEM_REPEATERCAPACITOR_H 7 | 8 | #include "CapacitorComponent.h" 9 | #include "../Facing.h" 10 | 11 | class RepeaterCapacitor : public CapacitorComponent { 12 | private: 13 | int field_44[5]; 14 | int field_58; 15 | bool mOn; // off = 0x5C 16 | bool field_5D; // TODO: what type should this be? delayPulse() suggests it's not a bool, but alignment suggests it's not an int 17 | bool field_5E; 18 | int field_60; 19 | bool field_64; // TODO: this is compared to field_5D, probably the same type 20 | bool field_65; 21 | CircuitComponentList *field_68; 22 | public: 23 | RepeaterCapacitor(); 24 | 25 | // VTABLE #1 26 | ~RepeaterCapacitor() override { 27 | delete field_68; 28 | } 29 | 30 | // VTABLE #2 31 | int getStrength() override { 32 | return mOn ? 15 : 0; 33 | } 34 | 35 | // VTABLE #4 36 | void setStrength(int strength) override { 37 | mOn = strength != 0; 38 | for (int i = 0; i < field_58 + 1; i++) { 39 | field_44[i] = mOn ? 3 : 2; 40 | } 41 | for (int i = field_58 + 1; i <= 4; i++) { 42 | field_44[i] = 0; 43 | } 44 | } 45 | 46 | // VTABLE #6 47 | bool consumePowerAnyDirection() override { 48 | return true; 49 | } 50 | 51 | // VTABLE #7 52 | bool canConsumePower() override { 53 | return true; 54 | } 55 | 56 | // VTABLE #11 57 | ComponentType getInstanceType() const override { 58 | return TYPE_REPEATER; 59 | } 60 | 61 | // VTABLE #12 62 | bool removeSource(const BlockPos *pos, const BaseCircuitComponent *component) override; 63 | 64 | // VTABLE #13 65 | bool addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, bool *a5) override; 66 | 67 | // VTABLE #14 68 | bool allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, bool *a4) override; 69 | 70 | // VTABLE #15 71 | void checkLock() override; 72 | 73 | // VTABLE #16 74 | bool evaluate(CircuitSystem *system, const BlockPos *pos) override; 75 | 76 | // VTABLE #17 77 | void cacheValues(CircuitSystem *system, const BlockPos *pos) override; 78 | 79 | // VTABLE #18 80 | void updateDependencies(CircuitSceneGraph *graph, const BlockPos *pos) override; 81 | 82 | // VTABLE #24 83 | Facing::Facing getPoweroutDirection() override { 84 | return Facing::OPPOSITE_FACING[getDirection()]; 85 | } 86 | 87 | void delayPulse(int a2) { 88 | for (int i = 1; i <= field_58; i++) { 89 | field_44[i - 1] = field_44[i]; 90 | } 91 | for (int i = field_58; i < 4; i++) { 92 | field_44[i] = a2; 93 | } 94 | } 95 | 96 | void alternatePulse() { 97 | if (field_58 > 0) { 98 | if (field_44[0] == 0 || field_44[0] == 1) { 99 | int v1 = field_65 ? 3 : 2; 100 | field_65 = !field_65; 101 | for (int i = 0; i < field_58 + 1; i++) { 102 | field_44[i] = v1; 103 | } 104 | } 105 | } 106 | } 107 | 108 | void extendPulse() { 109 | if (field_58 > 0) { 110 | if (field_44[0] == 2 && field_44[1] == 0) { 111 | field_44[1] = 2; 112 | } else if (field_44[0] == 3 && field_44[1] == 1) { 113 | field_44[1] = 3; 114 | } 115 | if (field_44[0] == 0 || field_44[0] == 1) { 116 | int v5 = 0; 117 | for (int i = 0; i <= field_58; i++) { 118 | if (field_44[i] == field_44[0]) 119 | v5++; 120 | } 121 | int v3; 122 | if (field_44[0] != 0) { 123 | v3 = 3; 124 | } else { 125 | v3 = v5 <= field_58 ? 3 : 2; 126 | } 127 | for (int i = 0; i <= field_58; i++) { 128 | field_44[i] = v3; 129 | } 130 | } 131 | } 132 | } 133 | }; 134 | 135 | #endif //REDSTONE_SYSTEM_REPEATERCAPACITOR_H 136 | -------------------------------------------------------------------------------- /components/BaseCircuitComponent.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "BaseCircuitComponent.h" 6 | 7 | BaseCircuitComponent::BaseCircuitComponent() { 8 | mDependencies = new CircuitComponentList; 9 | field_20 = false; 10 | field_21 = true; 11 | field_22 = false; 12 | // field_24 13 | field_30 = true; 14 | mStrength = 0; 15 | mDirection = Facing::NONE; 16 | mAllowPowerUp = false; 17 | mAllowPowerDown = true; 18 | } 19 | 20 | BaseCircuitComponent::~BaseCircuitComponent() { 21 | delete mDependencies; 22 | } 23 | 24 | bool BaseCircuitComponent::removeSource(const BlockPos *pos, const BaseCircuitComponent *component) { 25 | bool removedAny = false; 26 | for (auto it = mDependencies->begin(); it != mDependencies->end();) { 27 | if (it->mPos == *pos) { 28 | it = mDependencies->erase(it); 29 | removedAny = true; 30 | } else { 31 | ++it; 32 | } 33 | } 34 | return removedAny; 35 | } 36 | 37 | bool BaseCircuitComponent::hasSource(BaseCircuitComponent *component) { 38 | if (mDependencies->size() <= 0) 39 | return false; 40 | 41 | for (auto &item : *mDependencies) { 42 | BaseCircuitComponent *comp = item.mComponent; 43 | if (comp) { 44 | if (comp == component) { 45 | return true; 46 | } 47 | if (comp->hasChildrenSource()) { 48 | //e = component; FIXME 49 | if (comp->hasSource(component)) { 50 | return true; 51 | } 52 | } 53 | } 54 | } 55 | 56 | return false; 57 | } 58 | 59 | bool BaseCircuitComponent::trackPowerSource(const CircuitTrackingInfo *trackingInfo, int a3, bool a4, bool a5) { 60 | for (auto &item : *mDependencies) { 61 | if (item.mPos == trackingInfo->entry1.mPos) { 62 | if (item.field_19 || a4) { 63 | if (item.field_8 - 1 <= trackingInfo->field_80 - 1) { 64 | return false; 65 | } else { 66 | if (trackingInfo->field_80 - 1 >= 0) { 67 | item.field_8 = trackingInfo->field_80 - 1; 68 | } else { 69 | item.field_8 = 0; 70 | } 71 | return true; 72 | } 73 | } else { 74 | item.field_19 = true; 75 | if (trackingInfo->entry1.mComponent && trackingInfo->entry1.mComponent->getStrength() - (trackingInfo->field_80 - 1) <= 0) { 76 | item.field_8 = std::max(std::min(item.field_8, trackingInfo->field_80 - 1), 0); 77 | return true; 78 | } else { 79 | if (trackingInfo->field_80 - 1 >= 0) { 80 | item.field_8 = trackingInfo->field_80 - 1; 81 | } else { 82 | item.field_8 = 0; 83 | } 84 | return true; 85 | } 86 | } 87 | } 88 | } 89 | 90 | CircuitComponentList::Item item; 91 | item.field_8 = a3 - 1 >= 0 ? a3 - 1 : 0; 92 | item.mPos = trackingInfo->entry1.mPos; 93 | item.mDirection = trackingInfo->entry1.mDirection; 94 | item.field_19 = a4; 95 | item.mComponent = trackingInfo->entry1.mComponent; 96 | item.field_1C = a5 ? 1 : 0; // TODO: this correct? 97 | mDependencies->push_back(&item); 98 | return true; 99 | } 100 | 101 | bool BaseCircuitComponent::trackPowerSourceDuplicates(const CircuitTrackingInfo *trackingInfo, int a3, bool a4) { 102 | for (auto &item : *mDependencies) { 103 | if (item.mPos == trackingInfo->entry1.mPos) { 104 | if (item.field_19 || a4) { 105 | if (item.field_8 - 1 <= trackingInfo->field_80 - 1) { 106 | return false; 107 | } else { 108 | if (trackingInfo->field_80 - 1 >= 0) { 109 | item.field_8 = trackingInfo->field_80 - 1; 110 | } else { 111 | item.field_8 = 0; 112 | } 113 | return true; 114 | } 115 | } else { 116 | item.field_19 = true; 117 | if (trackingInfo->field_80 - 1 >= 0) { 118 | item.field_8 = trackingInfo->field_80 - 1; 119 | } else { 120 | item.field_8 = 0; 121 | } 122 | return true; 123 | } 124 | } 125 | } 126 | 127 | CircuitComponentList::Item item; 128 | item.field_8 = a3 - 1 >= 0 ? a3 - 1 : 0; 129 | item.mPos = trackingInfo->entry1.mPos; 130 | item.mDirection = trackingInfo->entry1.mDirection; 131 | item.field_19 = a4; 132 | item.mComponent = trackingInfo->entry1.mComponent; 133 | mDependencies->push_back(&item); 134 | return true; 135 | } 136 | 137 | bool BaseCircuitComponent::hasDirectPower() { 138 | for (auto &item : *mDependencies) { 139 | if (item.field_19) { 140 | return true; 141 | } 142 | } 143 | return false; 144 | } 145 | -------------------------------------------------------------------------------- /components/TransporterComponent.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include "TransporterComponent.h" 6 | #include "RepeaterCapacitor.h" 7 | #include "PulseCapacitor.h" 8 | #include "PoweredBlockComponent.h" 9 | #include "ConsumerComponent.h" 10 | 11 | 12 | bool sub_1F61EE0(CircuitSceneGraph *graph, const BlockPos *pos, Facing::Facing facing, bool a4) { 13 | ComponentType baseType = TYPE_NULL; 14 | BaseCircuitComponent *component = graph->getBaseComponent(pos); 15 | if (component) { 16 | baseType = component->getBaseType(); 17 | if (component->getInstanceType() == TYPE_REPEATER) { 18 | auto *repeater = dynamic_cast(component); 19 | Facing::Facing poweroutDir = repeater->getPoweroutDirection(); 20 | return (poweroutDir == facing || facing == Facing::OPPOSITE_FACING[poweroutDir]) && a4; 21 | } 22 | if (component->getInstanceType() == TYPE_PULSE_CAPACITOR) { 23 | auto *pulseCapacitor = dynamic_cast(component); 24 | return facing == Facing::OPPOSITE_FACING[pulseCapacitor->getPoweroutDirection()] && a4; 25 | } 26 | } 27 | 28 | if (baseType == TYPE_TRANSPORTER) 29 | return true; 30 | 31 | return (baseType == TYPE_PRODUCER || baseType == TYPE_CAPACITOR || baseType == TYPE_PISTON) && a4; 32 | } 33 | 34 | bool sub_1F61B00(CircuitSceneGraph *graph, const BlockPos *pos) { 35 | BlockPos above = *pos + Facing::DIRECTION[Facing::UP]; 36 | BaseCircuitComponent *component = graph->getBaseComponent(&above); 37 | return component && component->canAllowPowerUp(); 38 | } 39 | 40 | bool sub_1F61B80(CircuitSceneGraph *graph, const BlockPos *pos) { 41 | BlockPos below = *pos + Facing::DIRECTION[Facing::DOWN]; 42 | BaseCircuitComponent *component = graph->getBaseComponent(&below); 43 | return component && component->canAllowPowerDown(); 44 | } 45 | 46 | bool sub_1F61760(CircuitSceneGraph *graph, const BlockPos *pos, Facing::Facing facing) { 47 | BlockPos off = *pos + Facing::DIRECTION[facing]; 48 | BlockPos offAbove = off + Facing::DIRECTION[Facing::UP]; 49 | BlockPos offBelow = off + Facing::DIRECTION[Facing::DOWN]; 50 | 51 | bool v6 = sub_1F61EE0(graph, &offBelow, facing, false); 52 | if (v6 && sub_1F61B00(graph, &offBelow)) 53 | v6 = false; 54 | bool v5 = sub_1F61EE0(graph, &offAbove, facing, false); 55 | if (v5 && sub_1F61B00(graph, pos)) 56 | v5 = false; 57 | 58 | return sub_1F61EE0(graph, &off, facing, true) || v5 || v6; 59 | } 60 | 61 | bool sub_1F618B0(CircuitSceneGraph *graph, const BlockPos *a2, const BlockPos *a3) { 62 | int v7 = 0; 63 | int v8 = 0; 64 | int v9 = 0; 65 | if (sub_1F61760(graph, a2, Facing::NORTH)) { 66 | if (a3->z != 0) 67 | v8++; 68 | v9++; 69 | } 70 | if (sub_1F61760(graph, a2, Facing::SOUTH)) { 71 | if (a3->z != 0) 72 | v8++; 73 | v9++; 74 | } 75 | if (sub_1F61760(graph, a2, Facing::EAST)) { 76 | if (a3->x != 0) 77 | v7++; 78 | v9++; 79 | } 80 | if (sub_1F61760(graph, a2, Facing::WEST)) { 81 | if (a3->x != 0) 82 | v7++; 83 | v9++; 84 | } 85 | 86 | return v9 == 1 && (v8 == 1 || v7 == 1); 87 | 88 | } 89 | 90 | bool sub_1F61A30(const CircuitTrackingInfo *trackingInfo) { 91 | switch (trackingInfo->entry3.mComponentType) { 92 | case TYPE_POWERED_BLOCK: { 93 | return dynamic_cast(trackingInfo->entry3.mComponent)->isPromotedToProducer(); 94 | } 95 | case TYPE_CONSUMER: { 96 | return dynamic_cast(trackingInfo->entry3.mComponent)->isPromotedToProducer(); 97 | } 98 | case TYPE_PRODUCER: { 99 | return true; 100 | } 101 | default: { 102 | return trackingInfo->entry3.mComponent->getInstanceType() == TYPE_REDSTONE_TORCH; 103 | } 104 | } 105 | } 106 | 107 | bool TransporterComponent::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, 108 | bool *a5) { 109 | ComponentType componentType = trackingInfo->entry2.mComponentType; 110 | if (componentType != TYPE_POWERED_BLOCK && componentType != TYPE_TRANSPORTER && componentType != TYPE_CONSUMER) { 111 | if (trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[trackingInfo->entry0.mComponent->getDirection()]) { 112 | trackPowerSource(trackingInfo, *a4, *a5, false); 113 | } 114 | } 115 | return false; 116 | } 117 | 118 | bool TransporterComponent::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, 119 | bool *a4) { 120 | if (trackingInfo->entry0.mDirection == Facing::UP) { 121 | return false; 122 | } 123 | if (trackingInfo->entry0.mDirection == Facing::DOWN) { 124 | return true; 125 | } 126 | if (trackingInfo->entry0.mComponent->consumePowerAnyDirection()) { 127 | return true; 128 | } 129 | 130 | ComponentType componentType = trackingInfo->entry0.mComponentType; 131 | if (componentType == TYPE_TRANSPORTER) { 132 | BlockPos pos = trackingInfo->entry0.mPos - trackingInfo->entry2.mPos; 133 | if (pos.y >= 0) { 134 | if (pos.y > 0 && sub_1F61B00(graph, &trackingInfo->entry2.mPos)) { 135 | return false; 136 | } 137 | } else { 138 | if (sub_1F61B00(graph, &trackingInfo->entry0.mPos)) { 139 | return false; 140 | } 141 | if (sub_1F61B80(graph, &trackingInfo->entry2.mPos)) { 142 | return false; 143 | } 144 | } 145 | return true; 146 | } 147 | 148 | BlockPos pos = trackingInfo->entry3.mPos - trackingInfo->entry0.mPos; 149 | const BlockPos *v15 = &trackingInfo->entry2.mPos; 150 | if (pos.z == -2 || pos.z == 2) { 151 | bool v14 = !sub_1F61760(graph, v15, Facing::EAST) 152 | && !sub_1F61760(graph, v15, Facing::WEST); 153 | return v14; 154 | } else if (pos.x == -2 || pos.x == 2) { 155 | bool v14 = !sub_1F61760(graph, v15, Facing::NORTH) 156 | && !sub_1F61760(graph, v15, Facing::SOUTH); 157 | return v14; 158 | } else { 159 | if ((pos.y == 1 || pos.y == -1) && (pos.x != 0 || pos.z != 0)) { 160 | BlockPos tmp = trackingInfo->entry2.mPos - trackingInfo->entry0.mPos; 161 | *a4 = sub_1F618B0(graph, v15, &tmp); 162 | return *a4; 163 | } 164 | if ((trackingInfo->entry0.mComponentType == TYPE_POWERED_BLOCK || 165 | trackingInfo->entry0.mComponentType == TYPE_CONSUMER) 166 | && pos.y == 0 && pos.x != 0 && pos.z != 0) { 167 | BlockPos tmp = trackingInfo->entry2.mPos - trackingInfo->entry0.mPos; 168 | *a4 = sub_1F618B0(graph, v15, &tmp); 169 | return *a4; 170 | } 171 | if (sub_1F61A30(trackingInfo)) { 172 | bool v14 = !sub_1F61760(graph, v15, Facing::NORTH) 173 | && !sub_1F61760(graph, v15, Facing::SOUTH) 174 | && !sub_1F61760(graph, v15, Facing::EAST) 175 | && !sub_1F61760(graph, v15, Facing::WEST); 176 | if (v14) { 177 | *a4 = true; 178 | } 179 | return v14; 180 | } 181 | } 182 | 183 | return true; 184 | } 185 | 186 | bool TransporterComponent::evaluate(CircuitSystem *system, const BlockPos *pos) { 187 | bool ret = mStrength != field_3C; 188 | mStrength = field_3C; 189 | return ret; 190 | } 191 | 192 | void TransporterComponent::cacheValues(CircuitSystem *system, const BlockPos *pos) { 193 | int v10 = 0; 194 | for (auto &item : *mDependencies) { 195 | int v6 = item.mComponent->getStrength() - item.field_8; 196 | if (v6 < 0) 197 | v6 = 0; 198 | if (v10 < v6) 199 | v10 = v6; 200 | } 201 | field_3C = v10; 202 | } 203 | 204 | -------------------------------------------------------------------------------- /components/RedstoneTorchCapacitor.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Earthcomputer on 10/12/18. 3 | // 4 | 5 | #include 6 | #include 7 | #include "RedstoneTorchCapacitor.h" 8 | 9 | void PushCircularReference(std::unordered_map &posToTorchMap, const BlockPos &pos, std::queue &torchQueue) { 10 | auto it = posToTorchMap.find(pos); 11 | if (it != posToTorchMap.end()) { 12 | torchQueue.push(it->second); 13 | } 14 | } 15 | 16 | bool sub_1F62CA0(CircuitComponentList *componentList) { 17 | if (componentList->size() <= 0) 18 | return false; 19 | 20 | for (auto &item : *componentList) { 21 | if (item.mComponent) { 22 | ComponentType baseType = item.mComponent->getBaseType(); 23 | if (baseType == TYPE_POWERED_BLOCK || baseType == TYPE_CONSUMER) { 24 | CircuitComponentList *childList = item.mComponent->mDependencies; 25 | for (auto &childItem : *childList) { 26 | if (childItem.field_19) { 27 | BaseCircuitComponent *child = childItem.mComponent; 28 | if (child && child->getInstanceType() != TYPE_REDSTONE_TORCH) { 29 | int v6 = child->getStrength() - childItem.field_8; 30 | v6 = std::max(v6, 0); 31 | if (v6 != 0) 32 | return true; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } 39 | 40 | return false; 41 | } 42 | 43 | bool sub_1F63000(CircuitComponentList *componentList, CircuitSceneGraph *graph) { 44 | bool v42 = false; 45 | std::unordered_map posToTorchMap; 46 | for (auto &item : *componentList) { 47 | BaseCircuitComponent *v37 = item.mComponent; 48 | if (v37) { 49 | BlockPos posAbove = item.mPos + Facing::DIRECTION[Facing::UP]; 50 | BaseCircuitComponent *v34 = graph->getComponent(&posAbove, TYPE_TRANSPORTER); 51 | if (v34) { 52 | ComponentType baseType = v37->getBaseType(); 53 | if (baseType == TYPE_POWERED_BLOCK || baseType == TYPE_CONSUMER) { 54 | BlockPos v32 = item.mPos; 55 | CircuitComponentList *componentList1 = v37->mDependencies; 56 | for (auto &v27 : *componentList1) { 57 | if (v27.field_19) { 58 | BaseCircuitComponent *v26 = v27.mComponent; 59 | BlockPos v25 = v27.mPos + Facing::DIRECTION[v26->getDirection()]; 60 | if (v26 && v25 == v32 && v26->getInstanceType() == TYPE_REDSTONE_TORCH) { 61 | BlockPos v24 = v27.mPos + Facing::DIRECTION[Facing::UP]; 62 | BaseCircuitComponent *v22 = graph->getComponent(&v24, TYPE_POWERED_BLOCK); 63 | BaseCircuitComponent *v21 = graph->getComponent(&v24, TYPE_CONSUMER); 64 | if (v22 || v21) { 65 | if (v26->getDirection() != Facing::DOWN) { 66 | posToTorchMap.insert(std::make_pair(v27.mPos, dynamic_cast(v26))); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | if (posToTorchMap.size() > 1) { 73 | std::queue torchQueue; 74 | PushCircularReference(posToTorchMap, item.mPos + Facing::DIRECTION[Facing::NORTH], torchQueue); 75 | PushCircularReference(posToTorchMap, item.mPos + Facing::DIRECTION[Facing::WEST], torchQueue); 76 | PushCircularReference(posToTorchMap, item.mPos + Facing::DIRECTION[Facing::SOUTH], torchQueue); 77 | PushCircularReference(posToTorchMap, item.mPos + Facing::DIRECTION[Facing::EAST], torchQueue); 78 | if (!torchQueue.empty()) { 79 | RedstoneTorchCapacitor *firstTorch = torchQueue.front(); 80 | firstTorch->setSelfPowerCount(0); 81 | RedstoneTorchCapacitor *lastTorch = torchQueue.back(); 82 | lastTorch->setNextInQueue(firstTorch); 83 | lastTorch->setSelfPowerCount(0); 84 | while (torchQueue.size() > 1) { 85 | RedstoneTorchCapacitor *torchA = torchQueue.front(); 86 | torchQueue.pop(); 87 | RedstoneTorchCapacitor *torchB = torchQueue.front(); 88 | torchA->setNextInQueue(torchB); 89 | lastTorch->setSelfPowerCount(16); 90 | } 91 | } 92 | v42 = true; 93 | } 94 | } 95 | } 96 | } 97 | } 98 | return v42; 99 | } 100 | 101 | bool RedstoneTorchCapacitor::addSource(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, int *a4, 102 | bool *a5) { 103 | ComponentType componentType = trackingInfo->entry2.mComponentType; 104 | if (componentType != TYPE_POWERED_BLOCK && componentType != TYPE_TRANSPORTER && componentType != TYPE_CONSUMER) { 105 | if (trackingInfo->entry0.mDirection == Facing::OPPOSITE_FACING[trackingInfo->entry0.mComponent->getDirection()]) { 106 | trackPowerSource(trackingInfo, *a4, *a5, false); 107 | } 108 | } 109 | return false; 110 | } 111 | 112 | bool RedstoneTorchCapacitor::allowConnection(CircuitSceneGraph *graph, const CircuitTrackingInfo *trackingInfo, 113 | bool *a4) { 114 | bool providesPower = trackingInfo->entry0.mComponentType == TYPE_POWERED_BLOCK || trackingInfo->entry0.mComponentType == TYPE_PRODUCER; 115 | bool flag2 = providesPower && trackingInfo->entry0.mDirection == trackingInfo->entry2.mDirection; 116 | bool flag3 = trackingInfo->entry0.mComponentType == TYPE_CONSUMER && getDirection() == trackingInfo->entry0.mDirection; 117 | if (flag2 || flag3) { 118 | const CircuitTrackingInfo trackingInfo1(*trackingInfo); 119 | trackPowerSource(&trackingInfo1, trackingInfo->field_80, trackingInfo->field_84, false); 120 | if (trackingInfo->entry0.mComponentType == TYPE_POWERED_BLOCK) { 121 | return false; 122 | } 123 | } 124 | 125 | return mDirection != Facing::DOWN || trackingInfo->entry0.mDirection != Facing::DOWN; 126 | } 127 | 128 | void RedstoneTorchCapacitor::cacheValues(CircuitSystem *system, const BlockPos *pos) { 129 | if (mNextInQueue) { 130 | if (sub_1F62CA0(mDependencies)) { 131 | field_58 = false; 132 | field_57 = true; 133 | field_59 = !field_54; 134 | mSelfPowerCount = -1; 135 | } else if (mSelfPowerCount != 0) { 136 | field_58 = false; 137 | field_57 = false; 138 | field_59 = field_54; 139 | } else { 140 | field_58 = false; 141 | field_57 = true; 142 | field_59 = !field_54; 143 | if (mNextInQueue) { 144 | mNextInQueue->mSelfPowerCount = -1; 145 | RedstoneTorchCapacitor *torch = mNextInQueue->mNextInQueue; 146 | for (int i = 0; i < 4 && torch && torch != this; i++) { 147 | torch->mSelfPowerCount = 1; 148 | torch = torch->mNextInQueue; 149 | } 150 | } 151 | } 152 | } else { 153 | bool v11 = false; 154 | int strongestStrength = FindStrongestStrength(pos, system, &v11); 155 | bool v9, v8; 156 | if (v11) { 157 | if (_canIncrementSelfPower()) 158 | mSelfPowerCount++; 159 | if (mSelfPowerCount >= 16) { 160 | if (mSelfPowerCount == 16) { 161 | v9 = false; 162 | v8 = true; 163 | } else { 164 | v9 = false; 165 | v8 = false; 166 | } 167 | } else { 168 | v9 = !field_54; 169 | v8 = true; 170 | } 171 | } else { 172 | mSelfPowerCount = 0; 173 | field_5A = false; 174 | v9 = strongestStrength <= 0; 175 | v8 = false; 176 | } 177 | field_58 = v8; 178 | field_57 = v9; 179 | field_59 = v9 != field_54; 180 | if (mSelfPowerCount > 32) { 181 | field_5A = true; 182 | } 183 | } 184 | } 185 | 186 | void RedstoneTorchCapacitor::updateDependencies(CircuitSceneGraph *graph, const BlockPos *pos) { 187 | if (!sub_1F63000(mDependencies, graph)) { 188 | mNextInQueue = nullptr; 189 | } 190 | } 191 | 192 | int RedstoneTorchCapacitor::FindStrongestStrength(const BlockPos *pos, CircuitSystem *system, bool *a4) { 193 | if (mDependencies->size() <= 0) 194 | return 0; 195 | 196 | int v27 = 0; 197 | CircuitComponentList::Item *v26 = nullptr, *v25 = nullptr, *v24 = nullptr; 198 | 199 | for (auto v22 = mDependencies->begin(); v22 != mDependencies->end(); ++v22) { 200 | CircuitComponentList::Item *v20 = v22.base(); 201 | BaseCircuitComponent *component = v20->mComponent; 202 | if (component) { 203 | ComponentType v18 = component->getBaseType(); 204 | if (v18 != TYPE_PRODUCER && (v18 != TYPE_CAPACITOR || component->mDependencies->size() != 0)) { 205 | int v16 = 0; 206 | int v15 = 0; 207 | CircuitComponentList *v14 = component->mDependencies; 208 | for (auto v13 = v14->begin(), v12 = v14->end(); v13 != v12; ++v13) { 209 | if (v13->field_19) { 210 | BaseCircuitComponent *v10 = v13->mComponent; 211 | if (v10) { 212 | v16 = v10->getStrength() - v13->field_8; 213 | v16 = std::max(v16, 0); 214 | if (v16 >= v27 && v16 != 0) { 215 | v27 = v16; 216 | v26 = v13.base(); 217 | if (*pos != v13->mPos) { 218 | v24 = v13.base(); 219 | } 220 | } 221 | if (*pos == v13->mPos) { 222 | v25 = v13.base(); 223 | v15 = v16; 224 | } 225 | } 226 | } 227 | } 228 | if (v16 == v15 && v24) { 229 | v26 = v24; 230 | v25 = nullptr; 231 | } 232 | if (!v27 && v25) { 233 | v26 = v25; 234 | } 235 | *a4 = v26 == v25 && v25; 236 | } else { 237 | int v17 = component->getStrength(); 238 | if (v17 >= v27 && v17 != 0) { 239 | v26 = v20; 240 | v27 = v17; 241 | } 242 | } 243 | } 244 | } 245 | 246 | return v27; 247 | } 248 | 249 | --------------------------------------------------------------------------------