Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockTypeRegistry.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h"
3 #include "BlockTypeRegistry.h"
4 
5 
6 
7 
9 // BlockInfo:
10 
12  const AString & aPluginName,
13  const AString & aBlockTypeName,
14  std::shared_ptr<cBlockHandler> aHandler,
15  const std::map<AString, AString> & aHints,
16  const std::map<AString, BlockInfo::HintCallback> & aHintCallbacks
17 ):
18  m_PluginName(aPluginName),
19  m_BlockTypeName(aBlockTypeName),
20  m_Handler(std::move(aHandler)),
21  m_Hints(aHints),
22  m_HintCallbacks(aHintCallbacks)
23 {
24 }
25 
26 
27 
28 
29 
31  const AString & aHintName,
32  const BlockState & aBlockState
33 )
34 {
35  // Search the hint callbacks first:
36  auto itrC = m_HintCallbacks.find(aHintName);
37  if (itrC != m_HintCallbacks.end())
38  {
39  // Hint callback found, use it:
40  return itrC->second(m_BlockTypeName, aBlockState);
41  }
42 
43  // Search the static hints:
44  auto itr = m_Hints.find(aHintName);
45  if (itr != m_Hints.end())
46  {
47  // Hint found, use it:
48  return itr->second;
49  }
50 
51  // Nothing found, return empty string:
52  return AString();
53 }
54 
55 
56 
57 
58 
59 void BlockInfo::setHint(const AString & aHintKey, const AString & aHintValue)
60 {
61  m_Hints[aHintKey] = aHintValue;
62 
63  // Warn if the hint is already provided by a callback (aHintValue will be ignored when evaluating the hint):
64  auto itrC = m_HintCallbacks.find(aHintKey);
65  if (itrC != m_HintCallbacks.end())
66  {
67  LOGINFO("Setting a static hint %s for block type %s, but there's already a callback for that hint. The static hint will be ignored.",
68  aHintKey.c_str(), m_BlockTypeName.c_str()
69  );
70  }
71 }
72 
73 
74 
75 
76 
77 void BlockInfo::removeHint(const AString & aHintKey)
78 {
79  m_Hints.erase(aHintKey);
80 }
81 
82 
83 
84 
85 
87 // BlockTypeRegistry:
88 
90  const AString & aPluginName,
91  const AString & aBlockTypeName,
92  std::shared_ptr<cBlockHandler> aHandler,
93  const std::map<AString, AString> & aHints,
94  const std::map<AString, BlockInfo::HintCallback> & aHintCallbacks
95 )
96 {
97  auto blockInfo = std::make_shared<BlockInfo>(
98  aPluginName, aBlockTypeName, std::move(aHandler), aHints, aHintCallbacks
99  );
100 
101  // Check previous registrations:
102  cCSLock lock(m_CSRegistry);
103  auto itr = m_Registry.find(aBlockTypeName);
104  if (itr != m_Registry.end())
105  {
106  if (itr->second->pluginName() != aPluginName)
107  {
108  throw AlreadyRegisteredException(itr->second, blockInfo);
109  }
110  }
111 
112  // Store the registration:
113  m_Registry[aBlockTypeName] = blockInfo;
114 }
115 
116 
117 
118 
119 
120 std::shared_ptr<BlockInfo> BlockTypeRegistry::blockInfo(const AString & aBlockTypeName)
121 {
122  cCSLock lock(m_CSRegistry);
123  auto itr = m_Registry.find(aBlockTypeName);
124  if (itr == m_Registry.end())
125  {
126  return nullptr;
127  }
128  return itr->second;
129 }
130 
131 
132 
133 
134 
136 {
137  cCSLock lock(m_CSRegistry);
138  for (auto itr = m_Registry.begin(); itr != m_Registry.end();)
139  {
140  if (itr->second->pluginName() == aPluginName)
141  {
142  itr = m_Registry.erase(itr);
143  }
144  else
145  {
146  ++itr;
147  }
148  }
149 }
150 
151 
152 
153 
154 
156  const AString & aBlockTypeName,
157  const AString & aHintKey,
158  const AString & aHintValue
159 )
160 {
161  cCSLock lock(m_CSRegistry);
162  auto blockInfo = m_Registry.find(aBlockTypeName);
163  if (blockInfo == m_Registry.end())
164  {
165  throw NotRegisteredException(aBlockTypeName, aHintKey, aHintValue);
166  }
167  blockInfo->second->setHint(aHintKey, aHintValue);
168 }
169 
170 
171 
172 
173 
175  const AString & aBlockTypeName,
176  const AString & aHintKey
177 )
178 {
179  cCSLock lock(m_CSRegistry);
180  auto blockInfo = m_Registry.find(aBlockTypeName);
181  if (blockInfo == m_Registry.end())
182  {
183  return;
184  }
185  blockInfo->second->removeHint(aHintKey);
186 }
187 
188 
189 
190 
191 
193 // BlockTypeRegistry::AlreadyRegisteredException:
194 
196  const std::shared_ptr<BlockInfo> & aPreviousRegistration,
197  const std::shared_ptr<BlockInfo> & aNewRegistration
198 ) :
199  Super(message(aPreviousRegistration, aNewRegistration)),
200  m_PreviousRegistration(aPreviousRegistration),
201  m_NewRegistration(aNewRegistration)
202 {
203 }
204 
205 
206 
207 
208 
210  const std::shared_ptr<BlockInfo> & aPreviousRegistration,
211  const std::shared_ptr<BlockInfo> & aNewRegistration
212 )
213 {
214  return fmt::format(
215  FMT_STRING("Attempting to register BlockTypeName {} from plugin {}, while it is already registered in plugin {}"),
216  aNewRegistration->blockTypeName(),
217  aNewRegistration->pluginName(),
218  aPreviousRegistration->pluginName()
219  );
220 }
221 
222 
223 
224 
225 
227 // BlockTypeRegistry::NotRegisteredException:
228 
230  const AString & aBlockTypeName,
231  const AString & aHintKey,
232  const AString & aHintValue
233 ):
234  Super(fmt::format(
235  FMT_STRING("Attempting to set a hint of nonexistent BlockTypeName.\n\tBlockTypeName = {}\n\tHintKey = {}\n\tHintValue = {}"),
236  aBlockTypeName,
237  aHintKey,
238  aHintValue
239  ))
240 {
241 }
void LOGINFO(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:61
std::string AString
Definition: StringUtils.h:11
Implements custom fmtlib formatting for cChunkCoords.
Definition: ChunkDef.h:104
Definition: FastNBT.h:132
Represents the state of a single block (previously known as "block meta").
Definition: BlockState.h:20
AString hintValue(const AString &aHintName, const BlockState &aBlockState)
Retrieves the value associated with the specified hint for this specific BlockTypeName and BlockState...
BlockInfo(const AString &aPluginName, const AString &aBlockTypeName, std::shared_ptr< cBlockHandler > aHandler, const std::map< AString, AString > &aHints=std::map< AString, AString >(), const std::map< AString, HintCallback > &aHintCallbacks=std::map< AString, HintCallback >())
Creates a new instance with the specified BlockTypeName and handler / hints / callbacks.
void setHint(const AString &aHintKey, const AString &aHintValue)
Sets (creates or updates) a static hint.
std::map< AString, AString > m_Hints
Optional static hints for any subsystem to use, such as "IsSnowable" -> "1".
std::map< AString, HintCallback > m_HintCallbacks
The callbacks for dynamic evaluation of hints, such as "LightValue" -> function(BlockTypeName,...
AString m_BlockTypeName
The name of the block type, such as "minecraft:redstone_lamp".
void removeHint(const AString &aHintKey)
Removes a hint.
void setBlockTypeHint(const AString &aBlockTypeName, const AString &aHintKey, const AString &aHintValue)
Sets (adds or overwrites) a single Hint value for a BlockType.
cCriticalSection m_CSRegistry
The CS that protects m_Registry against multithreaded access.
void removeAllByPlugin(const AString &aPluginName)
Removes all registrations done by the specified plugin.
std::map< AString, std::shared_ptr< BlockInfo > > m_Registry
The actual block type registry.
std::shared_ptr< BlockInfo > blockInfo(const AString &aBlockTypeName)
Returns the registration information for the specified BlockTypeName.
void registerBlockType(const AString &aPluginName, const AString &aBlockTypeName, std::shared_ptr< cBlockHandler > aHandler, const std::map< AString, AString > &aHints=std::map< AString, AString >(), const std::map< AString, BlockInfo::HintCallback > &aHintCallbacks=std::map< AString, BlockInfo::HintCallback >())
Registers the specified block type.
void removeBlockTypeHint(const AString &aBlockTypeName, const AString &aHintKey)
Removes a previously registered single Hint value for a BlockType.
The exception thrown from BlockTypeRegistry::registerBlockType() if the same block type is being regi...
AlreadyRegisteredException(const std::shared_ptr< BlockInfo > &aPreviousRegistration, const std::shared_ptr< BlockInfo > &aNewRegistration)
Creates a new instance of the exception that provides info on both the original registration and the ...
static AString message(const std::shared_ptr< BlockInfo > &aPreviousRegistration, const std::shared_ptr< BlockInfo > &aNewRegistration)
Returns the general exception message formatted by the two registrations.
The exception thrown from BlockTypeRegistry::setBlockTypeHint() if the block type has not been regist...
NotRegisteredException(const AString &aBlockTypeName, const AString &aHintKey, const AString &aHintValue)
Creates a new instance of the exception that provides info on both the original registration and the ...
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.