Use more smart pointers and modern language constructs

This commit is contained in:
yvt 2017-12-15 23:05:08 +09:00
parent 13995e3c63
commit 49cc61c573
13 changed files with 110 additions and 143 deletions

View File

@ -523,8 +523,8 @@ namespace spades {
size_t len = bytes.size();
size_t pos = 0;
GameMap *map = new GameMap();
try {
Handle<GameMap> map{new GameMap(), false};
for (int y = 0; y < 512; y++) {
for (int x = 0; x < 512; x++) {
map->solidMap[x][y] = 0xffffffffffffffffULL;
@ -589,11 +589,7 @@ namespace spades {
}
}
return map;
} catch (...) {
delete map;
throw;
}
return map.Unmanage();
}
}
}

View File

@ -23,38 +23,35 @@
#include <set>
#include <vector>
#include "GameMap.h"
#include "GameMapWrapper.h"
#include <Core/Debug.h>
#include <Core/Debug.h>
#include <Core/Deque.h>
#include <Core/Stopwatch.h>
#include "GameMap.h"
#include "GameMapWrapper.h"
namespace spades {
namespace client {
GameMapWrapper::GameMapWrapper(GameMap *mp) : map(mp) {
GameMapWrapper::GameMapWrapper(GameMap &mp) : map(mp) {
SPADES_MARK_FUNCTION();
width = mp->Width();
height = mp->Height();
depth = mp->Depth();
linkMap = new uint8_t[width * height * depth];
memset(linkMap, 0, width * height * depth);
width = mp.Width();
height = mp.Height();
depth = mp.Depth();
linkMap.reset(new uint8_t[width * height * depth]);
memset(linkMap.get(), 0, width * height * depth);
}
GameMapWrapper::~GameMapWrapper() {
SPADES_MARK_FUNCTION();
delete[] linkMap;
}
GameMapWrapper::~GameMapWrapper() { SPADES_MARK_FUNCTION(); }
void GameMapWrapper::Rebuild() {
SPADES_MARK_FUNCTION();
Stopwatch stopwatch;
GameMap *m = map;
memset(linkMap, 0, width * height * depth);
GameMap &m = map;
memset(linkMap.get(), 0, width * height * depth);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
@ -64,7 +61,7 @@ namespace spades {
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
if (m->IsSolid(x, y, depth - 2)) {
if (m.IsSolid(x, y, depth - 2)) {
SetLink(x, y, depth - 2, PositiveZ);
queue.Push(CellPos(x, y, depth - 2));
}
@ -75,28 +72,27 @@ namespace spades {
int x = p.x, y = p.y, z = p.z;
if (p.x > 0 && m->IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid) {
if (p.x > 0 && m.IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid) {
SetLink(x - 1, y, z, PositiveX);
queue.Push(CellPos(x - 1, y, z));
}
if (p.x < width - 1 && m->IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid) {
if (p.x < width - 1 && m.IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid) {
SetLink(x + 1, y, z, NegativeX);
queue.Push(CellPos(x + 1, y, z));
}
if (p.y > 0 && m->IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid) {
if (p.y > 0 && m.IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid) {
SetLink(x, y - 1, z, PositiveY);
queue.Push(CellPos(x, y - 1, z));
}
if (p.y < height - 1 && m->IsSolid(x, y + 1, z) &&
GetLink(x, y + 1, z) == Invalid) {
if (p.y < height - 1 && m.IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) == Invalid) {
SetLink(x, y + 1, z, NegativeY);
queue.Push(CellPos(x, y + 1, z));
}
if (p.z > 0 && m->IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid) {
if (p.z > 0 && m.IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid) {
SetLink(x, y, z - 1, PositiveZ);
queue.Push(CellPos(x, y, z - 1));
}
if (p.z < depth - 1 && m->IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid) {
if (p.z < depth - 1 && m.IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid) {
SetLink(x, y, z + 1, NegativeZ);
queue.Push(CellPos(x, y, z + 1));
}
@ -108,41 +104,41 @@ namespace spades {
void GameMapWrapper::AddBlock(int x, int y, int z, uint32_t color) {
SPADES_MARK_FUNCTION();
GameMap *m = map;
GameMap &m = map;
if (GetLink(x, y, z) != Invalid) {
SPAssert(m->IsSolid(x, y, z));
SPAssert(m.IsSolid(x, y, z));
return;
}
m->Set(x, y, z, true, color);
m.Set(x, y, z, true, color);
if (GetLink(x, y, z) != Invalid) {
return;
}
LinkType l = Invalid;
if (x > 0 && m->IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) != Invalid) {
if (x > 0 && m.IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) != Invalid) {
l = NegativeX;
SPAssert(GetLink(x - 1, y, z) != PositiveX);
}
if (x < width - 1 && m->IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) != Invalid) {
if (x < width - 1 && m.IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) != Invalid) {
l = PositiveX;
SPAssert(GetLink(x + 1, y, z) != NegativeX);
}
if (y > 0 && m->IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) != Invalid) {
if (y > 0 && m.IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) != Invalid) {
l = NegativeY;
SPAssert(GetLink(x, y - 1, z) != PositiveY);
}
if (y < height - 1 && m->IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) != Invalid) {
if (y < height - 1 && m.IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) != Invalid) {
l = PositiveY;
SPAssert(GetLink(x, y + 1, z) != NegativeY);
}
if (z > 0 && m->IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) != Invalid) {
if (z > 0 && m.IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) != Invalid) {
l = NegativeZ;
SPAssert(GetLink(x, y, z - 1) != PositiveZ);
}
if (z < depth - 1 && m->IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) != Invalid) {
if (z < depth - 1 && m.IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) != Invalid) {
l = PositiveZ;
SPAssert(GetLink(x, y, z + 1) != NegativeZ);
}
@ -159,36 +155,36 @@ namespace spades {
queue.Shift();
int x = p.x, y = p.y, z = p.z;
SPAssert(m->IsSolid(x, y, z));
SPAssert(m.IsSolid(x, y, z));
LinkType thisLink = GetLink(x, y, z);
if (p.x > 0 && m->IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid &&
if (p.x > 0 && m.IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid &&
thisLink != NegativeX) {
SetLink(x - 1, y, z, PositiveX);
queue.Push(CellPos(x - 1, y, z));
}
if (p.x < width - 1 && m->IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid &&
if (p.x < width - 1 && m.IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid &&
thisLink != PositiveX) {
SetLink(x + 1, y, z, NegativeX);
queue.Push(CellPos(x + 1, y, z));
}
if (p.y > 0 && m->IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid &&
if (p.y > 0 && m.IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid &&
thisLink != NegativeY) {
SetLink(x, y - 1, z, PositiveY);
queue.Push(CellPos(x, y - 1, z));
}
if (p.y < height - 1 && m->IsSolid(x, y + 1, z) &&
GetLink(x, y + 1, z) == Invalid && thisLink != PositiveY) {
if (p.y < height - 1 && m.IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) == Invalid &&
thisLink != PositiveY) {
SetLink(x, y + 1, z, NegativeY);
queue.Push(CellPos(x, y + 1, z));
}
if (p.z > 0 && m->IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid &&
if (p.z > 0 && m.IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid &&
thisLink != NegativeZ) {
SetLink(x, y, z - 1, PositiveZ);
queue.Push(CellPos(x, y, z - 1));
}
if (p.z < depth - 1 && m->IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid &&
if (p.z < depth - 1 && m.IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid &&
thisLink != PositiveZ) {
SetLink(x, y, z + 1, NegativeZ);
queue.Push(CellPos(x, y, z + 1));
@ -206,7 +202,7 @@ namespace spades {
if (cells.empty())
return std::vector<CellPos>();
GameMap *m = map;
GameMap &m = map;
// solid, but unlinked cells
std::vector<CellPos> unlinkedCells;
@ -215,7 +211,7 @@ namespace spades {
// unlink children
for (size_t i = 0; i < cells.size(); i++) {
CellPos pos = cells[i];
m->Set(pos.x, pos.y, pos.z, false, 0);
m.Set(pos.x, pos.y, pos.z, false, 0);
// if(GetLink(pos.x, pos.y, pos.z) == Invalid){
// this block is already disconnected.
// }
@ -232,38 +228,38 @@ namespace spades {
pos = queue.Front();
queue.Shift();
if (m->IsSolid(pos.x, pos.y, pos.z))
if (m.IsSolid(pos.x, pos.y, pos.z))
unlinkedCells.push_back(pos);
// don't "continue;" when non-solid
int x = pos.x, y = pos.y, z = pos.z;
if (x > 0 && EqualTwoCond(GetLink(x - 1, y, z), PositiveX, Invalid,
m->IsSolid(x - 1, y, z))) {
m.IsSolid(x - 1, y, z))) {
SetLink(x - 1, y, z, Marked);
queue.Push(CellPos(x - 1, y, z));
}
if (x < width - 1 && EqualTwoCond(GetLink(x + 1, y, z), NegativeX, Invalid,
m->IsSolid(x + 1, y, z))) {
m.IsSolid(x + 1, y, z))) {
SetLink(x + 1, y, z, Marked);
queue.Push(CellPos(x + 1, y, z));
}
if (y > 0 && EqualTwoCond(GetLink(x, y - 1, z), PositiveY, Invalid,
m->IsSolid(x, y - 1, z))) {
m.IsSolid(x, y - 1, z))) {
SetLink(x, y - 1, z, Marked);
queue.Push(CellPos(x, y - 1, z));
}
if (y < height - 1 && EqualTwoCond(GetLink(x, y + 1, z), NegativeY, Invalid,
m->IsSolid(x, y + 1, z))) {
m.IsSolid(x, y + 1, z))) {
SetLink(x, y + 1, z, Marked);
queue.Push(CellPos(x, y + 1, z));
}
if (z > 0 && EqualTwoCond(GetLink(x, y, z - 1), PositiveZ, Invalid,
m->IsSolid(x, y, z - 1))) {
m.IsSolid(x, y, z - 1))) {
SetLink(x, y, z - 1, Marked);
queue.Push(CellPos(x, y, z - 1));
}
if (z < depth - 1 && EqualTwoCond(GetLink(x, y, z + 1), NegativeZ, Invalid,
m->IsSolid(x, y, z + 1))) {
m.IsSolid(x, y, z + 1))) {
SetLink(x, y, z + 1, Marked);
queue.Push(CellPos(x, y, z + 1));
}
@ -283,7 +279,7 @@ namespace spades {
for (size_t i = 0; i < unlinkedCells.size(); i++) {
const CellPos &pos = unlinkedCells[i];
int x = pos.x, y = pos.y, z = pos.z;
if (!m->IsSolid(x, y, z)) {
if (!m.IsSolid(x, y, z)) {
// notice: (x,y,z) may be air, so
// don't use SPAssert()
continue;
@ -317,32 +313,32 @@ namespace spades {
int x = p.x, y = p.y, z = p.z;
LinkType thisLink = GetLink(x, y, z);
if (p.x > 0 && m->IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid &&
if (p.x > 0 && m.IsSolid(x - 1, y, z) && GetLink(x - 1, y, z) == Invalid &&
thisLink != NegativeX) {
SetLink(x - 1, y, z, PositiveX);
queue.Push(CellPos(x - 1, y, z));
}
if (p.x < width - 1 && m->IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid &&
if (p.x < width - 1 && m.IsSolid(x + 1, y, z) && GetLink(x + 1, y, z) == Invalid &&
thisLink != PositiveX) {
SetLink(x + 1, y, z, NegativeX);
queue.Push(CellPos(x + 1, y, z));
}
if (p.y > 0 && m->IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid &&
if (p.y > 0 && m.IsSolid(x, y - 1, z) && GetLink(x, y - 1, z) == Invalid &&
thisLink != NegativeY) {
SetLink(x, y - 1, z, PositiveY);
queue.Push(CellPos(x, y - 1, z));
}
if (p.y < height - 1 && m->IsSolid(x, y + 1, z) &&
GetLink(x, y + 1, z) == Invalid && thisLink != PositiveY) {
if (p.y < height - 1 && m.IsSolid(x, y + 1, z) && GetLink(x, y + 1, z) == Invalid &&
thisLink != PositiveY) {
SetLink(x, y + 1, z, NegativeY);
queue.Push(CellPos(x, y + 1, z));
}
if (p.z > 0 && m->IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid &&
if (p.z > 0 && m.IsSolid(x, y, z - 1) && GetLink(x, y, z - 1) == Invalid &&
thisLink != NegativeZ) {
SetLink(x, y, z - 1, PositiveZ);
queue.Push(CellPos(x, y, z - 1));
}
if (p.z < depth - 1 && m->IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid &&
if (p.z < depth - 1 && m.IsSolid(x, y, z + 1) && GetLink(x, y, z + 1) == Invalid &&
thisLink != PositiveZ) {
SetLink(x, y, z + 1, NegativeZ);
queue.Push(CellPos(x, y, z + 1));
@ -354,7 +350,7 @@ namespace spades {
for (size_t i = 0; i < unlinkedCells.size(); i++) {
const CellPos &p = unlinkedCells[i];
if (!m->IsSolid(p.x, p.y, p.z))
if (!m.IsSolid(p.x, p.y, p.z))
continue;
if (GetLink(p.x, p.y, p.z) == Invalid) {
floatingBlocks.push_back(p);

View File

@ -22,6 +22,7 @@
#include <cstdint>
#include <vector>
#include <memory>
namespace spades {
namespace client {
@ -72,10 +73,10 @@ namespace spades {
friend class Client; // FIXME: for debug
public:
private:
GameMap *map;
GameMap &map;
/** Each element represents where this cell is connected from. */
uint8_t *linkMap;
std::unique_ptr<uint8_t[]> linkMap;
enum LinkType {
Invalid = 0,
@ -100,7 +101,7 @@ namespace spades {
}
public:
GameMapWrapper(GameMap *);
GameMapWrapper(GameMap &);
~GameMapWrapper();
/** Addes a new block. */

View File

@ -145,7 +145,7 @@ namespace spades {
map = newMap;
if (map) {
map->AddRef();
mapWrapper = new GameMapWrapper(map);
mapWrapper = new GameMapWrapper(*map);
mapWrapper->Rebuild();
}
}

View File

@ -17,6 +17,7 @@
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory>
#include "GLModelManager.h"
#include <Core/Debug.h>
@ -61,24 +62,10 @@ namespace spades {
GLModel *GLModelManager::CreateModel(const char *name) {
SPADES_MARK_FUNCTION();
VoxelModel *bmp;
IStream *stream = FileManager::OpenForReading(name);
try {
bmp = VoxelModel::LoadKV6(stream);
delete stream;
} catch (...) {
delete stream;
throw;
}
try {
GLModel *model = static_cast<GLModel *>(
renderer->CreateModelOptimized(bmp)); // new GLVoxelModel(bmp, renderer);
bmp->Release();
return model;
} catch (...) {
bmp->Release();
throw;
}
std::unique_ptr<IStream> stream{FileManager::OpenForReading(name)};
Handle<VoxelModel> voxelModel{VoxelModel::LoadKV6(stream.get()), false};
return static_cast<GLModel *>(renderer->CreateModelOptimized(voxelModel));
}
}
}

View File

@ -118,20 +118,18 @@ namespace spades {
SWModel *SWModelManager::RegisterModel(const std::string &name) {
auto it = models.find(name);
if (it == models.end()) {
auto *str = FileManager::OpenForReading(name.c_str());
std::unique_ptr<IStream> stream{FileManager::OpenForReading(name.c_str())};
Handle<VoxelModel> vm;
try {
vm.Set(VoxelModel::LoadKV6(str), false);
auto *m = CreateModel(vm);
models.insert(std::make_pair(name, m));
m->AddRef();
return m;
} catch (...) {
delete str;
throw;
}
vm.Set(VoxelModel::LoadKV6(stream.get()), false);
SWModel *model = CreateModel(vm);
models.insert(std::make_pair(name, model));
model->AddRef();
return model;
} else {
auto *model = it->second;
SWModel *model = it->second;
model->AddRef();
return model;
}

View File

@ -22,6 +22,7 @@
#include <algorithm>
#include <cctype>
#include <memory>
#include <curl/curl.h>
#include <json/json.h>
@ -119,34 +120,29 @@ namespace spades {
return size;
}
void ReturnResult(MainScreenServerList *list) {
void ReturnResult(std::unique_ptr<MainScreenServerList> list) {
AutoLocker lock(&(owner->newResultArrayLock));
delete owner->newResult;
owner->newResult = list;
owner->newResult = std::move(list);
owner = NULL; // release owner
}
void ProcessResponse() {
Json::Reader reader;
Json::Value root;
MainScreenServerList *resp = new MainScreenServerList();
try {
std::unique_ptr<MainScreenServerList> resp{new MainScreenServerList()};
if (reader.parse(buffer, root, false)) {
for (Json::Value::iterator it = root.begin(); it != root.end(); ++it) {
Json::Value &obj = *it;
Serveritem *srv = Serveritem::create(obj);
std::unique_ptr<Serveritem> srv{Serveritem::create(obj)};
if (srv) {
resp->list.push_back(new MainScreenServerItem(
srv, owner->favorites.count(srv->Ip()) >= 1));
delete srv;
srv.get(), owner->favorites.count(srv->Ip()) >= 1));
}
}
}
ReturnResult(resp);
} catch (...) {
delete resp;
throw;
}
ReturnResult(std::move(resp));
}
public:
@ -178,19 +174,19 @@ namespace spades {
SPRaise("Failed to create cURL object.");
}
} catch (std::exception &ex) {
MainScreenServerList *lst = new MainScreenServerList();
std::unique_ptr<MainScreenServerList> lst{new MainScreenServerList()};
lst->message = ex.what();
ReturnResult(lst);
ReturnResult(std::move(lst));
} catch (...) {
MainScreenServerList *lst = new MainScreenServerList();
std::unique_ptr<MainScreenServerList> lst{new MainScreenServerList()};
lst->message = "Unknown error.";
ReturnResult(lst);
ReturnResult(std::move(lst));
}
}
};
MainScreenHelper::MainScreenHelper(MainScreen *scr)
: mainScreen(scr), result(NULL), newResult(NULL), query(NULL) {
: mainScreen(scr), query(NULL) {
SPADES_MARK_FUNCTION();
LoadFavorites();
}
@ -200,8 +196,6 @@ namespace spades {
if (query) {
query->MarkForAutoDeletion();
}
delete result;
delete newResult;
}
void MainScreenHelper::MainScreenDestroyed() {
@ -261,9 +255,9 @@ namespace spades {
SPADES_MARK_FUNCTION();
AutoLocker lock(&newResultArrayLock);
if (newResult) {
delete result;
result = newResult;
newResult = NULL;
// Move `newResult` to `result`
result = std::move(newResult);
SPAssert(!newResult);
query->MarkForAutoDeletion();
query = NULL;
return true;

View File

@ -22,6 +22,7 @@
#include <unordered_set>
#include <vector>
#include <memory>
#include <Core/Mutex.h>
#include <Core/RefCountedObject.h>
@ -78,8 +79,8 @@ namespace spades {
class ServerListQuery;
MainScreen *mainScreen;
MainScreenServerList *result;
MainScreenServerList *newResult;
std::unique_ptr<MainScreenServerList> result;
std::unique_ptr<MainScreenServerList> newResult;
Mutex newResultArrayLock;
ServerListQuery *query;
std::string errorMessage;

View File

@ -32,7 +32,7 @@ namespace spades {
return Bitmap::Load(str);
}catch(const std::exception& ex) {
ScriptContextUtils().SetNativeException(ex);
return NULL;
return nullptr;
}
}

View File

@ -17,7 +17,7 @@
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory>
#include <Client/GameMap.h>
#include "ScriptManager.h"
#include <Core/IStream.h>
@ -32,26 +32,23 @@ namespace spades {
h != GameMap::DefaultHeight ||
d != GameMap::DefaultDepth) {
asGetActiveContext()->SetException("Currently, non-default GameMap dimensions aren't supported.");
return NULL;
return nullptr;
}
try{
return new GameMap();
}catch(const std::exception& ex){
ScriptContextUtils().SetNativeException(ex);
return NULL;
return nullptr;
}
}
static GameMap *LoadFactory(const std::string& fn){
spades::IStream *stream = NULL;
try{
stream = FileManager::OpenForReading(fn.c_str());
GameMap *ret = GameMap::Load(stream);
delete stream;
std::unique_ptr<spades::IStream> stream{FileManager::OpenForReading(fn.c_str())};
GameMap *ret = GameMap::Load(stream.get());
return ret;
}catch(const std::exception& ex) {
ScriptContextUtils().SetNativeException(ex);
if(stream) delete stream;
return NULL;
return nullptr;
}
}

View File

@ -38,7 +38,7 @@ namespace spades {
return c;
}catch(const std::exception& ex) {
ScriptContextUtils().SetNativeException(ex);
return NULL;
return nullptr;
}
}
public:

View File

@ -47,7 +47,7 @@ namespace spades {
return im;
}catch(const std::exception& ex) {
ScriptContextUtils().SetNativeException(ex);
return NULL;
return nullptr;
}
}
static void AddDebugLine(const Vector3& a, const Vector3& b,

View File

@ -17,7 +17,7 @@
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory>
#include <Core/VoxelModel.h>
#include "ScriptManager.h"
#include <Core/FileManager.h>
@ -31,20 +31,17 @@ namespace spades {
return new VoxelModel(w, h, d);
}catch(const std::exception& ex){
ScriptContextUtils().SetNativeException(ex);
return NULL;
return nullptr;
}
}
static VoxelModel *LoadFactory(const std::string& fn){
spades::IStream *stream = NULL;
try{
stream = FileManager::OpenForReading(fn.c_str());
VoxelModel *ret = VoxelModel::LoadKV6(stream);
delete stream;
std::unique_ptr<spades::IStream> stream{FileManager::OpenForReading(fn.c_str())};
VoxelModel *ret = VoxelModel::LoadKV6(stream.get());
return ret;
}catch(const std::exception& ex) {
ScriptContextUtils().SetNativeException(ex);
if(stream) delete stream;
return NULL;
return nullptr;
}
}
static uint64_t GetSolidBits(int x, int y,