3 Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "util/numeric.h"
25 ObjDefManager::ObjDefManager(IGameDef
*gamedef
, ObjDefType type
)
28 m_ndef
= gamedef
? gamedef
->getNodeDefManager() : NULL
;
32 ObjDefManager::~ObjDefManager()
34 for (size_t i
= 0; i
!= m_objects
.size(); i
++)
39 ObjDefHandle
ObjDefManager::add(ObjDef
*obj
)
43 if (obj
->name
.length() && getByName(obj
->name
))
44 return OBJDEF_INVALID_HANDLE
;
46 u32 index
= addRaw(obj
);
47 if (index
== OBJDEF_INVALID_INDEX
)
48 return OBJDEF_INVALID_HANDLE
;
50 obj
->handle
= createHandle(index
, m_objtype
, obj
->uid
);
55 ObjDef
*ObjDefManager::get(ObjDefHandle handle
) const
57 u32 index
= validateHandle(handle
);
58 return (index
!= OBJDEF_INVALID_INDEX
) ? getRaw(index
) : NULL
;
62 ObjDef
*ObjDefManager::set(ObjDefHandle handle
, ObjDef
*obj
)
64 u32 index
= validateHandle(handle
);
65 if (index
== OBJDEF_INVALID_INDEX
)
68 ObjDef
*oldobj
= setRaw(index
, obj
);
70 obj
->uid
= oldobj
->uid
;
71 obj
->index
= oldobj
->index
;
72 obj
->handle
= oldobj
->handle
;
78 u32
ObjDefManager::addRaw(ObjDef
*obj
)
80 size_t nobjects
= m_objects
.size();
81 if (nobjects
>= OBJDEF_MAX_ITEMS
)
84 obj
->index
= nobjects
;
86 // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE
87 // is not possible. The slight randomness bias isn't very significant.
88 obj
->uid
= myrand() & OBJDEF_UID_MASK
;
92 m_objects
.push_back(obj
);
94 infostream
<< "ObjDefManager: added " << getObjectTitle()
95 << ": name=\"" << obj
->name
96 << "\" index=" << obj
->index
97 << " uid=" << obj
->uid
104 ObjDef
*ObjDefManager::getRaw(u32 index
) const
106 return m_objects
[index
];
110 ObjDef
*ObjDefManager::setRaw(u32 index
, ObjDef
*obj
)
112 ObjDef
*old_obj
= m_objects
[index
];
113 m_objects
[index
] = obj
;
118 ObjDef
*ObjDefManager::getByName(const std::string
&name
) const
120 for (size_t i
= 0; i
!= m_objects
.size(); i
++) {
121 ObjDef
*obj
= m_objects
[i
];
122 if (obj
&& !strcasecmp(name
.c_str(), obj
->name
.c_str()))
130 void ObjDefManager::clear()
132 for (size_t i
= 0; i
!= m_objects
.size(); i
++)
139 u32
ObjDefManager::validateHandle(ObjDefHandle handle
) const
146 (handle
!= OBJDEF_INVALID_HANDLE
) &&
147 decodeHandle(handle
, &index
, &type
, &uid
) &&
148 (type
== m_objtype
) &&
149 (index
< m_objects
.size()) &&
150 (m_objects
[index
]->uid
== uid
);
152 return is_valid
? index
: -1;
156 ObjDefHandle
ObjDefManager::createHandle(u32 index
, ObjDefType type
, u32 uid
)
158 ObjDefHandle handle
= 0;
159 set_bits(&handle
, 0, 18, index
);
160 set_bits(&handle
, 18, 6, type
);
161 set_bits(&handle
, 24, 7, uid
);
163 u32 parity
= calc_parity(handle
);
164 set_bits(&handle
, 31, 1, parity
);
166 return handle
^ OBJDEF_HANDLE_SALT
;
170 bool ObjDefManager::decodeHandle(ObjDefHandle handle
, u32
*index
,
171 ObjDefType
*type
, u32
*uid
)
173 handle
^= OBJDEF_HANDLE_SALT
;
175 u32 parity
= get_bits(handle
, 31, 1);
176 set_bits(&handle
, 31, 1, 0);
177 if (parity
!= calc_parity(handle
))
180 *index
= get_bits(handle
, 0, 18);
181 *type
= (ObjDefType
)get_bits(handle
, 18, 6);
182 *uid
= get_bits(handle
, 24, 7);