Cuberite
A lightweight, fast and extensible game server for Minecraft
ObserverHandler.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "../../Blocks/BlockObserver.h"
5 
6 
7 
8 
9 
10 namespace ObserverHandler
11 {
12  static bool IsOn(NIBBLETYPE a_Meta)
13  {
14  return (a_Meta & 0x8) == 0x8;
15  }
16 
17  static bool ShouldPowerOn(cChunk & Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData & a_Data)
18  {
20  NIBBLETYPE BlockMeta;
21  if (!Chunk.UnboundedRelGetBlock(a_Position + cBlockObserverHandler::GetObservingFaceOffset(a_Meta), BlockType, BlockMeta))
22  {
23  return false;
24  }
25 
26  auto & ObserverCache = a_Data.ObserverCache;
27  const auto FindResult = ObserverCache.find(a_Position);
28  const auto Observed = std::make_pair(BlockType, BlockMeta);
29 
30  if (FindResult == ObserverCache.end())
31  {
32  // Cache the last seen block for this position:
33  ObserverCache.emplace(a_Position, Observed);
34 
35  // Definitely should signal update:
36  return true;
37  }
38 
39  // The block this observer previously saw.
40  const auto Previous = FindResult->second;
41 
42  // Update the last seen block:
43  FindResult->second = Observed;
44 
45  // Determine if to signal an update based on the block previously observed changed
46  return Previous != Observed;
47  }
48 
49  static PowerLevel GetPowerDeliveredToPosition(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
50  {
51  const auto Meta = a_Chunk.GetMeta(a_Position);
52  return (IsOn(Meta) && (a_QueryPosition == (a_Position + cBlockObserverHandler::GetSignalOutputOffset(Meta)))) ? 15 : 0;
53  }
54 
55  static void Update(cChunk & a_Chunk, cChunk & CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
56  {
57  // LOGD("Evaluating Lenny the observer (%i %i %i)", a_Position.x, a_Position.y, a_Position.z);
58 
59  auto & Data = DataForChunk(a_Chunk);
60  auto DelayInfo = Data.GetMechanismDelayInfo(a_Position);
61 
62  if (DelayInfo == nullptr)
63  {
64  if (!ShouldPowerOn(a_Chunk, a_Position, a_Meta, Data))
65  {
66  return;
67  }
68 
69  // From rest, we've determined there was a block update
70  // Schedule power-on 1 tick in the future
71  Data.m_MechanismDelays[a_Position] = std::make_pair(1, true);
72 
73  return;
74  }
75 
76  int DelayTicks;
77  bool ShouldPowerOn;
78  std::tie(DelayTicks, ShouldPowerOn) = *DelayInfo;
79 
80  if (DelayTicks != 0)
81  {
82  return;
83  }
84 
85  if (ShouldPowerOn)
86  {
87  // Remain on for 1 tick before resetting
88  *DelayInfo = std::make_pair(1, false);
89  a_Chunk.SetMeta(a_Position, a_Meta | 0x8);
90  }
91  else
92  {
93  // We've reset. Erase delay data in preparation for detecting further updates
94  Data.m_MechanismDelays.erase(a_Position);
95  a_Chunk.SetMeta(a_Position, a_Meta & ~0x8);
96  }
97 
98  UpdateAdjustedRelative(a_Chunk, CurrentlyTicking, a_Position, cBlockObserverHandler::GetSignalOutputOffset(a_Meta));
99  }
100 
101  static void ForValidSourcePositions(const cChunk & a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback & Callback)
102  {
103  UNUSED(a_Chunk);
104  UNUSED(a_Position);
105  UNUSED(a_BlockType);
106  UNUSED(a_BlockType);
107  }
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
#define UNUSED
Definition: Globals.h:72
BlockType
Definition: BlockTypes.h:4
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 void Update(cChunk &a_Chunk, cChunk &CurrentlyTicking, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, const PowerLevel Power)
static void ForValidSourcePositions(const cChunk &a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta, ForEachSourceCallback &Callback)
static PowerLevel GetPowerDeliveredToPosition(const cChunk &a_Chunk, Vector3i a_Position, BLOCKTYPE a_BlockType, Vector3i a_QueryPosition, BLOCKTYPE a_QueryBlockType, bool IsLinked)
static bool IsOn(NIBBLETYPE a_Meta)
static bool ShouldPowerOn(cChunk &Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta, cIncrementalRedstoneSimulatorChunkData &a_Data)
static Vector3i GetObservingFaceOffset(NIBBLETYPE a_Meta)
Definition: BlockObserver.h:17
static Vector3i GetSignalOutputOffset(NIBBLETYPE a_Meta)
Definition: BlockObserver.h:22
Definition: Chunk.h:36
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:279
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
void SetMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_Meta)
Definition: Chunk.h:286
std::unordered_map< Vector3i, std::pair< BLOCKTYPE, NIBBLETYPE >, VectorHasher< int > > ObserverCache
Structure storing an observer's last seen block.