Cuberite
A lightweight, fast and extensible game server for Minecraft
RedstoneRepeaterHandler.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "../../Blocks/BlockRedstoneRepeater.h"
5 
6 
7 
8 
9 
11 {
12  static bool IsOn(BLOCKTYPE a_Block)
13  {
14  return (a_Block == E_BLOCK_REDSTONE_REPEATER_ON);
15  }
16 
19  static std::pair<bool, NIBBLETYPE> IsOnRepeater(cChunk & Chunk, const Vector3i a_Position)
20  {
22  NIBBLETYPE Meta;
23 
24  if (!Chunk.UnboundedRelGetBlock(a_Position, Type, Meta))
25  {
26  return std::make_pair(false, static_cast<NIBBLETYPE>(0));
27  }
28 
29  return std::make_pair(IsOn(Type), Meta);
30  }
31 
35  static bool DoesLhsLockMe(NIBBLETYPE a_MetaLhs, NIBBLETYPE a_MyMeta)
36  {
37  // Get the direction bits
40 
41  /*
42  Check for a valid locking configuration, where they are perpendicular and one snuggles into the other.
43 
44  Order of comparisons:
45  XP >^ ZM
46  ZP |_ XP
47  XM <| ZP
48  ZP ^< xM
49 
50  Key:
51  ^ Facing up
52  _ Facing right
53  | Facing down
54  < Facing left
55  */
56  return
61  ;
62  }
63 
67  static bool IsLocked(cChunk & Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta)
68  {
69  // The left hand side offset. Will be negated to get the rhs offset
70  const auto LhsOffset = cBlockRedstoneRepeaterHandler::GetLeftCoordinateOffset(a_Meta);
71 
72  // Test the block to the left of us
73  const auto Lhs = IsOnRepeater(Chunk, LhsOffset + a_Position);
74  if (Lhs.first && DoesLhsLockMe(Lhs.second, a_Meta))
75  {
76  return true;
77  }
78 
79  // Test the right side, flipping the argument order to DoesLhsLockMe
80  const auto Rhs = IsOnRepeater(Chunk, -LhsOffset + a_Position);
81  return Rhs.first && DoesLhsLockMe(a_Meta, Rhs.second);
82  }
83 
84  static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
85  {
86  if (!IsOn(a_BlockType))
87  {
88  return 0;
89  }
90 
91  const auto FrontOffset = cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Chunk.GetMeta(a_Position));
92  const auto FrontPosition = a_Position + FrontOffset;
93  if (a_QueryPosition == FrontPosition)
94  {
95  return 15;
96  }
97 
98  return 0;
99  }
100 
101  static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
102  {
103  // LOGD("Evaluating loopy the repeater (%d %d %d)", a_Position.x, a_Position.y, a_Position.z);
104 
105  auto & Data = DataForChunk(a_Chunk);
106  const auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
107 
108  // If the repeater is locked by another, ignore and forget all power changes:
109  if (IsLocked(a_Chunk, a_Position, a_Meta))
110  {
111  if (DelayInfo != nullptr)
112  {
113  Data.m_MechanismDelays.erase(a_Position);
114  }
115 
116  return;
117  }
118 
119  if (DelayInfo == nullptr)
120  {
121  bool ShouldBeOn = (Power != 0);
122  if (ShouldBeOn != IsOn(a_BlockType))
123  {
124  Data.m_MechanismDelays[a_Position] = std::make_pair((((a_Meta & 0xC) >> 0x2) + 1), ShouldBeOn);
125  }
126 
127  return;
128  }
129 
130  int DelayTicks;
131  bool ShouldPowerOn;
132  std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
133 
134  if (DelayTicks != 0)
135  {
136  return;
137  }
138 
140  a_Chunk.FastSetBlock(a_Position, NewType, a_Meta);
141  Data.m_MechanismDelays.erase(a_Position);
142 
143  // While sleeping, we ignore any power changes and apply our saved ShouldBeOn when sleep expires
144  // Now, we need to recalculate to be aware of any new changes that may e.g. cause a new output change
145  // FastSetBlock doesn't wake simulators, so manually update ourselves:
146  Update(a_Chunk, CurrentlyTicking, a_Position, NewType, a_Meta, Power);
147 
148  UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockRedstoneRepeaterHandler::GetFrontCoordinateOffset(a_Meta));
149  }
150 
151  static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback)
152  {
153  Callback(cBlockRedstoneRepeaterHandler::GetRearCoordinateOffset(a_Meta) + a_Position);
154  }
155 };
@ E_META_REDSTONE_REPEATER_FACING_XP
Definition: BlockType.h:799
@ E_META_REDSTONE_REPEATER_FACING_ZP
Definition: BlockType.h:800
@ E_META_REDSTONE_REPEATER_FACING_MASK
Definition: BlockType.h:802
@ E_META_REDSTONE_REPEATER_FACING_ZM
Definition: BlockType.h:798
@ E_META_REDSTONE_REPEATER_FACING_XM
Definition: BlockType.h:801
@ E_BLOCK_REDSTONE_REPEATER_ON
Definition: BlockType.h:109
@ E_BLOCK_REDSTONE_REPEATER_OFF
Definition: BlockType.h:108
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
auto & DataForChunk(const cChunk &a_Chunk)
void UpdateAdjustedRelative(const cChunk &a_Chunk, const cChunk &a_TickingChunk, const Vector3i a_Position, const Vector3i a_Offset)
unsigned char PowerLevel
unsigned char Power(const BlockState Block)
static bool ShouldPowerOn(cChunk &Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData &a_Data)
static void ForValidSourcePositions(const cChunk &a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback &Callback)
static void Update(cChunk &a_Chunk, cChunk &CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
static bool IsLocked(cChunk &Chunk, const Vector3i a_Position, const NIBBLETYPE a_Meta)
Determine if a repeater is locked.
static PowerLevel GetPowerDeliveredToPosition(const cChunk &a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
static std::pair< bool, NIBBLETYPE > IsOnRepeater(cChunk &Chunk, const Vector3i a_Position)
Returns a pair with first element indicating if the block at the given position is an activated repea...
static bool DoesLhsLockMe(NIBBLETYPE a_MetaLhs, NIBBLETYPE a_MyMeta)
Determine, from the metadata of a repeater on our left side, if they lock us.
static bool IsOn(BLOCKTYPE a_Block)
static Vector3i GetLeftCoordinateOffset(NIBBLETYPE a_Meta)
static Vector3i GetFrontCoordinateOffset(NIBBLETYPE a_Meta)
static Vector3i GetRearCoordinateOffset(NIBBLETYPE a_Meta)
Definition: Chunk.h:36
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:279
void FastSetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, BLOCKTYPE a_BlockMeta)
Definition: Chunk.cpp:1296
bool UnboundedRelGetBlock(Vector3i a_RelCoords, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Same as GetBlock(), but relative coords needn't be in this chunk (uses m_Neighbor-s or m_ChunkMap in ...
Definition: Chunk.cpp:1008