<commit_before>#include <cli/Session.h>
#include <cli/CommandLine.h>
#include <cli/PosixStreams.h>
#include <cli/Tokenizer.h>

#include <mtp/make_function.h>

#include <stdio.h>

namespace cli
{

	Session::Session(const mtp::DevicePtr &device):
		_device(device),
		_session(_device->OpenSession(1)),
		_gdi(_session->GetDeviceInfo()),
		_cd(mtp::Session::Root),
		_running(true)
	{
		using namespace mtp;
		using namespace std::placeholders;

		printf("%s\n", _gdi.VendorExtensionDesc.c_str());
		printf("%s ", _gdi.Manufacturer.c_str());
		printf("%s ", _gdi.Model.c_str());
		printf("%s ", _gdi.DeviceVersion.c_str());
		//printf("%s", _gdi.SerialNumber.c_str());
		printf("\n");
		printf("supported op codes: ");
		for(OperationCode code : _gdi.OperationsSupported)
		{
			printf("%04x ", (unsigned)code);
		}
		printf("\n");
		printf("supported properties: ");
		for(u16 code : _gdi.DevicePropertiesSupported)
		{
			printf("%04x ", (unsigned)code);
		}
		printf("\n");

		AddCommand("help",			make_function([this]() -> void { Help(); }));

		AddCommand("ls",			make_function([this]() -> void { List(); }));
		AddCommand("list",			make_function([this]() -> void { List(); }));
		AddCommand("list", 			make_function([this](mtp::u32 parent) -> void { List(parent); }));

		AddCommand("quit", 			make_function([this]() -> void { Quit(); }));
		AddCommand("exit", 			make_function([this]() -> void { Quit(); }));

		AddCommand("cd", 			make_function([this](const Path &path) -> void { ChangeDirectory(path); }));
		AddCommand("rm", 			make_function([this](const LocalPath &path) -> void { Delete(path); }));
		AddCommand("get", 			make_function([this](const LocalPath &path) -> void { Get(path); }));

		AddCommand("storages", make_function([this]() -> void { ListStorages(); }));
		AddCommand("device-properties", make_function([this]() -> void { ListDeviceProperties(); }));
	}

	char ** Session::CompletionCallback(const char *text, int start, int end)
	{
		if (start == 0)
		{
			char **comp = static_cast<char **>(calloc(sizeof(char *), _commands.size() + 1));
			auto it = _commands.begin();
			size_t i = 0, n = _commands.size();
			for(; n--; ++it)
			{
				if (end != 0 && it->first.compare(0, end, text) != 0)
					continue;

				comp[i++] = strdup(it->first.c_str());
			}
			if (i == 0) //readline silently dereference matches[0]
			{
				free(comp);
				comp = NULL;
			};
			return comp;
		}
		return NULL;
	}

	void Session::InteractiveInput()
	{
		using namespace mtp;
		std::string prompt(_gdi.Manufacturer + " " + _gdi.Model + "> "), input;
		cli::CommandLine::Get().SetCallback([this](const char *text, int start, int end) -> char ** { return CompletionCallback(text, start, end); });

		while (_running && cli::CommandLine::Get().ReadLine(prompt, input))
		{
			try
			{
				Tokens tokens;
				Tokenizer(input, tokens);
				if (tokens.empty())
					continue;

				std::string cmdName = tokens.front();
				tokens.pop_front();
				auto cmd = _commands.find(cmdName);
				if (cmd == _commands.end())
					throw std::runtime_error("invalid command " + cmdName);

				cmd->second->Execute(tokens);
			}
			catch(const std::exception &ex)
			{ printf("error: %s\n", ex.what()); }
		}
	}

	mtp::u32 Session::Resolve(const Path &path)
	{
		mtp::u32 id = _cd;
		for(size_t p = 0; p < path.size(); )
		{
			size_t next = path.find('/', p);
			if (next == path.npos)
				next = path.size();

			std::string entity(path.substr(p, next - p));
			auto objectList = _session->GetObjectHandles(mtp::Session::AllStorages, mtp::Session::AllFormats, id);
			bool found = false;
			for(auto object : objectList.ObjectHandles)
			{
				std::string name = _session->GetObjectStringProperty(object, mtp::ObjectProperty::ObjectFilename);
				if (name == entity)
				{
					id = object;
					found = true;
					break;
				}
			}
			if (!found)
				throw std::runtime_error("could not find " + entity + " in path " + path.substr(0, p));
			p = next + 1;
		}
		return id;
	}

	void Session::List(mtp::u32 parent)
	{
		using namespace mtp;
		msg::ObjectHandles handles = _session->GetObjectHandles(mtp::Session::AllStorages, mtp::Session::AllFormats, parent);

		for(u32 objectId : handles.ObjectHandles)
		{
			try
			{
				msg::ObjectInfo info = _session->GetObjectInfo(objectId);
				printf("%-10u %04hx %s %u %ux%u, %s\n", objectId, info.ObjectFormat, info.Filename.c_str(), info.ObjectCompressedSize, info.ImagePixWidth, info.ImagePixHeight, info.CaptureDate.c_str());
			}
			catch(const std::exception &ex)
			{
				printf("error: %s\n", ex.what());
			}
		}

	}

	void Session::ListStorages()
	{
		using namespace mtp;
		msg::StorageIDs list = _session->GetStorageIDs();
		for(size_t i = 0; i < list.StorageIDs.size(); ++i)
		{
			msg::StorageInfo si = _session->GetStorageInfo(list.StorageIDs[i]);
			printf("%08d volume: %s, description: %s\n", list.StorageIDs[i], si.VolumeLabel.c_str(), si.StorageDescription.c_str());
		}
	}

	void Session::Help()
	{
		printf("Available commands are:\n");
		for(auto i : _commands)
		{
			printf("\t%s\n", i.first.c_str());
		}
	}

	void Session::Get(const LocalPath &dst, mtp::u32 srcId)
	{
		_session->GetObject(srcId, std::make_shared<ObjectOutputStream>(dst));
	}

	void Session::Get(mtp::u32 srcId)
	{
		auto info = _session->GetObjectInfo(srcId);
		printf("filename = %s\n", info.Filename.c_str());
		Get(LocalPath(info.Filename), srcId);
	}

	void Session::Put(mtp::u32 parentId, const LocalPath &src)
	{
		using namespace mtp;
		msg::ObjectInfo oi;
		oi.Filename = src;
		oi.ObjectFormat = ObjectFormatFromFilename(src);

		std::shared_ptr<ObjectInputStream> objectInput(new ObjectInputStream(src));
		oi.SetSize(objectInput->GetSize());

		auto noi = _session->SendObjectInfo(oi, 0, parentId);
		printf("new object id = %u\n", noi.ObjectId);
		_session->SendObject(objectInput);
		printf("done\n");
	}

	void Session::MakeDirectory(mtp::u32 parentId, const std::string & name)
	{
		using namespace mtp;
		msg::ObjectInfo oi;
		oi.Filename = name;
		oi.ObjectFormat = ObjectFormat::Association;
		_session->SendObjectInfo(oi, 0, parentId);
	}

	void Session::Delete(mtp::u32 id)
	{
		_session->DeleteObject(id);
	}

	void Session::ListProperties(mtp::u32 id)
	{
		auto ops = _session->GetObjectPropsSupported(id);
		printf("properties supported: ");
		for(mtp::u16 prop: ops.ObjectPropCodes)
		{
			printf("%02x ", prop);
		}
		printf("\n");
	}

	void Session::ListDeviceProperties()
	{
		using namespace mtp;
		for(u16 code : _gdi.DevicePropertiesSupported)
		{
			if ((code & 0xff00) != 0x5000 )
				continue;
			printf("property code: %04x\n", (unsigned)code);
			ByteArray data = _session->GetDeviceProperty((mtp::DeviceProperty)code);
			HexDump("value", data);
		}
	}

}
<commit_msg>put newline only for ctrl-d exit<commit_after>#include <cli/Session.h>
#include <cli/CommandLine.h>
#include <cli/PosixStreams.h>
#include <cli/Tokenizer.h>

#include <mtp/make_function.h>

#include <stdio.h>

namespace cli
{

	Session::Session(const mtp::DevicePtr &device):
		_device(device),
		_session(_device->OpenSession(1)),
		_gdi(_session->GetDeviceInfo()),
		_cd(mtp::Session::Root),
		_running(true)
	{
		using namespace mtp;
		using namespace std::placeholders;

		printf("%s\n", _gdi.VendorExtensionDesc.c_str());
		printf("%s ", _gdi.Manufacturer.c_str());
		printf("%s ", _gdi.Model.c_str());
		printf("%s ", _gdi.DeviceVersion.c_str());
		//printf("%s", _gdi.SerialNumber.c_str());
		printf("\n");
		printf("supported op codes: ");
		for(OperationCode code : _gdi.OperationsSupported)
		{
			printf("%04x ", (unsigned)code);
		}
		printf("\n");
		printf("supported properties: ");
		for(u16 code : _gdi.DevicePropertiesSupported)
		{
			printf("%04x ", (unsigned)code);
		}
		printf("\n");

		AddCommand("help",			make_function([this]() -> void { Help(); }));

		AddCommand("ls",			make_function([this]() -> void { List(); }));
		AddCommand("list",			make_function([this]() -> void { List(); }));
		AddCommand("list", 			make_function([this](mtp::u32 parent) -> void { List(parent); }));

		AddCommand("quit", 			make_function([this]() -> void { Quit(); }));
		AddCommand("exit", 			make_function([this]() -> void { Quit(); }));

		AddCommand("cd", 			make_function([this](const Path &path) -> void { ChangeDirectory(path); }));
		AddCommand("rm", 			make_function([this](const LocalPath &path) -> void { Delete(path); }));
		AddCommand("get", 			make_function([this](const LocalPath &path) -> void { Get(path); }));

		AddCommand("storages", make_function([this]() -> void { ListStorages(); }));
		AddCommand("device-properties", make_function([this]() -> void { ListDeviceProperties(); }));
	}

	char ** Session::CompletionCallback(const char *text, int start, int end)
	{
		if (start == 0)
		{
			char **comp = static_cast<char **>(calloc(sizeof(char *), _commands.size() + 1));
			auto it = _commands.begin();
			size_t i = 0, n = _commands.size();
			for(; n--; ++it)
			{
				if (end != 0 && it->first.compare(0, end, text) != 0)
					continue;

				comp[i++] = strdup(it->first.c_str());
			}
			if (i == 0) //readline silently dereference matches[0]
			{
				free(comp);
				comp = NULL;
			};
			return comp;
		}
		return NULL;
	}

	void Session::InteractiveInput()
	{
		using namespace mtp;
		std::string prompt(_gdi.Manufacturer + " " + _gdi.Model + "> "), input;
		cli::CommandLine::Get().SetCallback([this](const char *text, int start, int end) -> char ** { return CompletionCallback(text, start, end); });

		while (cli::CommandLine::Get().ReadLine(prompt, input))
		{
			try
			{
				Tokens tokens;
				Tokenizer(input, tokens);
				if (tokens.empty())
					continue;

				std::string cmdName = tokens.front();
				tokens.pop_front();
				auto cmd = _commands.find(cmdName);
				if (cmd == _commands.end())
					throw std::runtime_error("invalid command " + cmdName);

				cmd->second->Execute(tokens);
				if (!_running) //do not put newline
					return;
			}
			catch(const std::exception &ex)
			{ printf("error: %s\n", ex.what()); }
		}
		printf("\n");
	}

	mtp::u32 Session::Resolve(const Path &path)
	{
		mtp::u32 id = _cd;
		for(size_t p = 0; p < path.size(); )
		{
			size_t next = path.find('/', p);
			if (next == path.npos)
				next = path.size();

			std::string entity(path.substr(p, next - p));
			auto objectList = _session->GetObjectHandles(mtp::Session::AllStorages, mtp::Session::AllFormats, id);
			bool found = false;
			for(auto object : objectList.ObjectHandles)
			{
				std::string name = _session->GetObjectStringProperty(object, mtp::ObjectProperty::ObjectFilename);
				if (name == entity)
				{
					id = object;
					found = true;
					break;
				}
			}
			if (!found)
				throw std::runtime_error("could not find " + entity + " in path " + path.substr(0, p));
			p = next + 1;
		}
		return id;
	}

	void Session::List(mtp::u32 parent)
	{
		using namespace mtp;
		msg::ObjectHandles handles = _session->GetObjectHandles(mtp::Session::AllStorages, mtp::Session::AllFormats, parent);

		for(u32 objectId : handles.ObjectHandles)
		{
			try
			{
				msg::ObjectInfo info = _session->GetObjectInfo(objectId);
				printf("%-10u %04hx %s %u %ux%u, %s\n", objectId, info.ObjectFormat, info.Filename.c_str(), info.ObjectCompressedSize, info.ImagePixWidth, info.ImagePixHeight, info.CaptureDate.c_str());
			}
			catch(const std::exception &ex)
			{
				printf("error: %s\n", ex.what());
			}
		}

	}

	void Session::ListStorages()
	{
		using namespace mtp;
		msg::StorageIDs list = _session->GetStorageIDs();
		for(size_t i = 0; i < list.StorageIDs.size(); ++i)
		{
			msg::StorageInfo si = _session->GetStorageInfo(list.StorageIDs[i]);
			printf("%08d volume: %s, description: %s\n", list.StorageIDs[i], si.VolumeLabel.c_str(), si.StorageDescription.c_str());
		}
	}

	void Session::Help()
	{
		printf("Available commands are:\n");
		for(auto i : _commands)
		{
			printf("\t%s\n", i.first.c_str());
		}
	}

	void Session::Get(const LocalPath &dst, mtp::u32 srcId)
	{
		_session->GetObject(srcId, std::make_shared<ObjectOutputStream>(dst));
	}

	void Session::Get(mtp::u32 srcId)
	{
		auto info = _session->GetObjectInfo(srcId);
		printf("filename = %s\n", info.Filename.c_str());
		Get(LocalPath(info.Filename), srcId);
	}

	void Session::Put(mtp::u32 parentId, const LocalPath &src)
	{
		using namespace mtp;
		msg::ObjectInfo oi;
		oi.Filename = src;
		oi.ObjectFormat = ObjectFormatFromFilename(src);

		std::shared_ptr<ObjectInputStream> objectInput(new ObjectInputStream(src));
		oi.SetSize(objectInput->GetSize());

		auto noi = _session->SendObjectInfo(oi, 0, parentId);
		printf("new object id = %u\n", noi.ObjectId);
		_session->SendObject(objectInput);
		printf("done\n");
	}

	void Session::MakeDirectory(mtp::u32 parentId, const std::string & name)
	{
		using namespace mtp;
		msg::ObjectInfo oi;
		oi.Filename = name;
		oi.ObjectFormat = ObjectFormat::Association;
		_session->SendObjectInfo(oi, 0, parentId);
	}

	void Session::Delete(mtp::u32 id)
	{
		_session->DeleteObject(id);
	}

	void Session::ListProperties(mtp::u32 id)
	{
		auto ops = _session->GetObjectPropsSupported(id);
		printf("properties supported: ");
		for(mtp::u16 prop: ops.ObjectPropCodes)
		{
			printf("%02x ", prop);
		}
		printf("\n");
	}

	void Session::ListDeviceProperties()
	{
		using namespace mtp;
		for(u16 code : _gdi.DevicePropertiesSupported)
		{
			if ((code & 0xff00) != 0x5000 )
				continue;
			printf("property code: %04x\n", (unsigned)code);
			ByteArray data = _session->GetDeviceProperty((mtp::DeviceProperty)code);
			HexDump("value", data);
		}
	}

}
<|endoftext|>


<commit_before>#include "cmainwindow.h"
#include "ui_cmainwindow.h"

#include <QCameraInfo>
#include <QImageReader>
#include <QPainter>
#include <QTime>
#include <QTimer>

inline bool analyzeFrame(const QImage& frame, unsigned int threshold)
{
	if (frame.depth() != 32)
		return true;

	const int w = frame.width(), h = frame.height();
	const int sampleSquareSize = 20;
	const int sampleStrideW = w / sampleSquareSize, sampleStrideH = h / sampleSquareSize;
	uint64_t pixelsValueSum = 0;
	for (int y = 0; y < h; y += sampleStrideH)
	{
		const uint32_t* scanLine = (const uint32_t*) frame.scanLine(y);
		for (int x = 0; x < w; x += sampleStrideW)
		{
			// TODO: support non-32 bpp images
			// TODO: vectorization
			const uint32_t pixel = scanLine[y];
			pixelsValueSum += ((pixel & 0x00FF0000) >> 16) + ((pixel & 0x0000FF00) >> 8) + (pixel & 0x000000FF);
		}
	}

	const auto avgValue = pixelsValueSum / ((uint64_t) w / sampleStrideW * (uint64_t) h / sampleStrideH * 3ull);
	qDebug() << "Frame metric:" << avgValue;
	return avgValue >= threshold;
}

CMainWindow::CMainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::CMainWindow)
{
	ui->setupUi(this);

	ui->_displayWidget->installEventFilter(this);

	connect(&_frameGrabber, &ProxyVideoSurface::frameReceived, [this](QImage frame) {
		if (!frame.isNull() && ui->_btnEnableProbing->isChecked())
		{
			// This is the first frame upon connecting to the camera
			if (_frame.isNull())
			{
				if (!analyzeFrame(frame, ui->_threshold->value()))
				{
					// Disconnect and schedule re-check
					stopCamera();
					QTimer::singleShot(10000, [this](){
						startCamera();
					});
				}
			}
			else // Not the first frame - apparently, we're streaming a live picture
				 // Avoid checking every single frame
			{
				static uint32_t frameCounter = 0;
				++frameCounter;

				if (frameCounter > 30)
				{
					frameCounter = 0;
					if (!analyzeFrame(frame, ui->_threshold->value()))
					{
						// Diisconnect and schedule re-check
						stopCamera();
						QTimer::singleShot(10000, [this](){
							startCamera();
						});
					}
				}
			}
		}

		_frame = frame;
		ui->_displayWidget->update();
	});

	connect(ui->_btnConnect, &QPushButton::clicked, [this](bool connect){
		ui->_btnConnect->setChecked(!connect);
		if (connect)
			startCamera();
		else
			stopCamera();
	});

	startCamera();
}

CMainWindow::~CMainWindow()
{
	stopCamera();
	delete ui;
}

bool CMainWindow::eventFilter(QObject* /*object*/, QEvent* event)
{
	if (event->type() == QEvent::Paint)
	{
		QWidget * widget = ui->_displayWidget;
		QPainter painter(widget);
		if (!_frame.isNull())
			painter.drawImage(widget->geometry(), _frame);
		else
			painter.fillRect(widget->geometry(), Qt::darkGray);
		painter.end();

		return true;
	}

	return false;
}

void CMainWindow::startCamera()
{
	if (!_camera)
	{
		const auto cameras = QCameraInfo::availableCameras();
		if (cameras.empty())
			return;

		const auto& cameraInfo = cameras.front();
		if (cameraInfo.isNull())
			return;

		qDebug() << "Creating the camera" << cameraInfo.description();
		_camera = std::make_shared<QCamera>(cameraInfo);
		_camera->setViewfinder(&_frameGrabber);

		qDebug() << "Connecting to the camera";
		connect(_camera.get(), &QCamera::stateChanged, [this](const QCamera::State state){
			if (state == QCamera::ActiveState)
			{
				ui->_btnConnect->setChecked(true);
				setWindowTitle("Connected");
			}
			else
			{
				ui->_btnConnect->setChecked(false);
				setWindowTitle("Not Connected");
			}
		});
	}

	_camera->load();
	_camera->start();
}

void CMainWindow::stopCamera()
{
	if (_camera)
	{
		_camera->stop();
		_camera->unload();
		_frame = QImage();
	}

	setWindowTitle("Not Connected");
}
<commit_msg>Minor fixes<commit_after>#include "cmainwindow.h"
#include "ui_cmainwindow.h"

#include <QCameraInfo>
#include <QImageReader>
#include <QPainter>
#include <QTime>
#include <QTimer>

inline bool analyzeFrame(const QImage& frame, unsigned int threshold)
{
	if (frame.depth() != 32)
		return true;

	const int w = frame.width(), h = frame.height();
	const int sampleSquareSize = 20;
	const int sampleStrideW = w / sampleSquareSize, sampleStrideH = h / sampleSquareSize;
	uint64_t pixelsValueSum = 0;
	for (int y = 0; y < h; y += sampleStrideH)
	{
		const uint32_t* scanLine = (const uint32_t*) frame.scanLine(y);
		for (int x = 0; x < w; x += sampleStrideW)
		{
			// TODO: support non-32 bpp images
			// TODO: vectorization
			const uint32_t pixel = scanLine[y];
			pixelsValueSum += ((pixel & 0x00FF0000) >> 16) + ((pixel & 0x0000FF00) >> 8) + (pixel & 0x000000FF);
		}
	}

	const auto avgValue = pixelsValueSum / ((uint64_t) w / sampleStrideW * (uint64_t) h / sampleStrideH * 3ull);
	qDebug() << "Frame metric:" << avgValue;
	return avgValue >= threshold;
}

CMainWindow::CMainWindow(QWidget *parent) :
	QMainWindow(parent),
	ui(new Ui::CMainWindow)
{
	ui->setupUi(this);

	ui->_displayWidget->installEventFilter(this);

	connect(&_frameGrabber, &ProxyVideoSurface::frameReceived, [this](QImage frame) {
		if (!frame.isNull() && ui->_btnEnableProbing->isChecked())
		{
			// This is the first frame upon connecting to the camera
			if (_frame.isNull())
			{
				if (!analyzeFrame(frame, ui->_threshold->value()))
				{
					// Disconnect and schedule re-check
					stopCamera();
					QTimer::singleShot(10000, [this](){
						startCamera();
					});
				}
			}
			else // Not the first frame - apparently, we're streaming a live picture
				 // Avoid checking every single frame
			{
				static uint32_t frameCounter = 0;
				++frameCounter;

				if (frameCounter > 30)
				{
					frameCounter = 0;
					if (!analyzeFrame(frame, ui->_threshold->value()))
					{
						// Diisconnect and schedule re-check
						stopCamera();
						QTimer::singleShot(10000, [this](){
							startCamera();
						});
					}
				}
			}
		}

		_frame = frame;
		ui->_displayWidget->update();
	});

	connect(ui->_btnConnect, &QPushButton::clicked, [this](bool connect){
		ui->_btnConnect->setChecked(!connect);
		if (connect)
			startCamera();
		else
			stopCamera();
	});

	startCamera();
}

CMainWindow::~CMainWindow()
{
	stopCamera();
	delete ui;
}

bool CMainWindow::eventFilter(QObject* /*object*/, QEvent* event)
{
	if (event->type() == QEvent::Paint)
	{
		QWidget * widget = ui->_displayWidget;
		QPainter painter(widget);
		if (!_frame.isNull())
			painter.drawImage(widget->geometry(), _frame);
		else
			painter.fillRect(widget->geometry(), Qt::darkGray);
		painter.end();

		return true;
	}

	return false;
}

void CMainWindow::startCamera()
{
	if (!_camera)
	{
		const auto cameras = QCameraInfo::availableCameras();
		for (const QCameraInfo& cameraInfo : cameras)
		{
			if (cameraInfo.isNull())
				continue;

			qDebug() << "Creating the camera" << cameraInfo.description();
			_camera = std::make_shared<QCamera>(cameraInfo);
			if (!_camera->isAvailable())
			{
				_camera.reset();
				continue;
			}

			_camera->setViewfinder(&_frameGrabber);

			connect(_camera.get(), &QCamera::stateChanged, [this](const QCamera::State state){
				if (state == QCamera::ActiveState)
				{
					ui->_btnConnect->setChecked(true);
					setWindowTitle("Connected");
				}
				else
				{
					ui->_btnConnect->setChecked(false);
					setWindowTitle("Not Connected");
				}
			});

			break;
		}
	}

	if (_camera)
	{
		qDebug() << "Connecting to the camera";
		_camera->load();
		_camera->start();
	}
}

void CMainWindow::stopCamera()
{
	if (_camera)
	{
		qDebug() << "Disconnecting from the camera";
		_camera->stop();
		_camera->unload();
		_frame = QImage();
	}

	setWindowTitle("Not Connected");
}
<|endoftext|>


<commit_before>/*
				Copyright <SWGEmu>
		See file COPYING for copying conditions.*/

#include "engine/engine.h"

#include "server/zone/managers/resource/ResourceManager.h"
#include "ResourceShiftTask.h"
#include "resourcespawner/SampleTask.h"
#include "resourcespawner/SampleResultsTask.h"
#include "server/zone/managers/resource/InterplanetarySurvey.h"
#include "server/zone/managers/resource/InterplanetarySurveyTask.h"
#include "server/zone/objects/resource/ResourceContainer.h"
#include "server/zone/packets/resource/ResourceContainerObjectDeltaMessage3.h"
#include "server/zone/objects/player/sui/listbox/SuiListBox.h"

void ResourceManagerImplementation::initialize() {
	lua = new Lua();
	lua->init();

	if(!loadConfigData()) {

		loadDefaultConfig();

		info("***** ERROR in configuration, using default values");
	}

	resourceSpawner->init();

	startResourceSpawner();
	loadSurveyData();
}

bool ResourceManagerImplementation::loadConfigFile() {
	return lua->runFile("scripts/managers/resource_manager.lua");
}
void ResourceManagerImplementation::loadSurveyData() {
	info("Loading survey data form surveys.db");
	ObjectDatabaseManager* dbManager = ObjectDatabaseManager::instance();
	ObjectDatabase* surveyDatabase = ObjectDatabaseManager::instance()->loadObjectDatabase("surveys", true);
	if (surveyDatabase == NULL) {
		error("Could not load the survey database.");
		return;
	}
	int i = 0;
	try {
		ObjectDatabaseIterator iterator(surveyDatabase);

		uint64 objectID;

		while (iterator.getNextKey(objectID)) {
			Core::getObjectBroker()->lookUp(objectID);
			++i;
		}
	} catch (DatabaseException& e) {
		error("Database exception in DirectorManager::loadSurveyData(): "	+ e.getMessage());
	}
	info(String::valueOf(i) + " surveys loaded.", true);
}
int ResourceManagerImplementation::notifyObserverEvent(uint32 eventType, Observable* observable, ManagedObject* arg1, int64 arg2) {
	if (eventType == ObserverEventType::POSTURECHANGED) {
		CreatureObject* creature = cast<CreatureObject*>( observable);
		// Cancel Sampling on posture change
		Reference<SampleTask*> task = creature->getPendingTask("sample").castTo<SampleTask*>( );
		Reference<SampleResultsTask*> sampleResultsTask = creature->getPendingTask("sampleresults").castTo<SampleResultsTask*>( );

		if (task != NULL) {

			task->stopSampling();
			//creature->removePendingTask("sample");

			if(sampleResultsTask != NULL) {
				sampleResultsTask->cancel();
				creature->removePendingTask("sampleresults");
			}

			creature->sendSystemMessage("@survey:sample_cancel");
		}
	}

	return 1;
}

bool ResourceManagerImplementation::loadConfigData() {
	if (!loadConfigFile())
		return false;

	bool loadFromScript = lua->getGlobalInt("buildInitialResourcesFromScript");

	String zonesString = lua->getGlobalString("activeZones");

	StringTokenizer zonesTokens(zonesString);
	zonesTokens.setDelimeter(",");

	while(zonesTokens.hasMoreTokens()) {
		String zoneName;
		zonesTokens.getStringToken(zoneName);
		resourceSpawner->addZone(zoneName);
	}

	shiftInterval = lua->getGlobalInt("averageShiftTime");

	int aveduration = lua->getGlobalInt("aveduration");
	float spawnThrottling = float(lua->getGlobalInt("spawnThrottling")) / 100.0f;
	int lowerGateOverride = lua->getGlobalInt("lowerGateOverride");
	int maxSpawnQuantity = lua->getGlobalInt("maxSpawnQuantity");

	resourceSpawner->setSpawningParameters(loadFromScript, aveduration,
			spawnThrottling, lowerGateOverride, maxSpawnQuantity);

	String jtlResources = lua->getGlobalString("jtlresources");

	StringTokenizer jtlTokens(jtlResources);
	jtlTokens.setDelimeter(",");

	while(jtlTokens.hasMoreTokens()) {
		String token;
		jtlTokens.getStringToken(token);
		resourceSpawner->addJtlResource(token);
	}

	LuaObject minpoolinc = lua->getGlobalObject("minimumpoolincludes");
	String minpoolexc = lua->getGlobalString("minimumpoolexcludes");
	resourceSpawner->initializeMinimumPool(minpoolinc, minpoolexc);

	LuaObject randpoolinc = lua->getGlobalObject("randompoolincludes");
	String randpoolexc = lua->getGlobalString("randompoolexcludes");
	int randpoolsize = lua->getGlobalInt("randompoolsize");
	resourceSpawner->initializeRandomPool(randpoolinc, randpoolexc, randpoolsize);

	LuaObject fixedpoolinc = lua->getGlobalObject("fixedpoolincludes");
	String fixedpoolexc = lua->getGlobalString("fixedpoolexcludes");
	resourceSpawner->initializeFixedPool(fixedpoolinc, fixedpoolexc);

	String natpoolinc = lua->getGlobalString("nativepoolincludes");
	String natpoolexc = lua->getGlobalString("nativepoolexcludes");
	resourceSpawner->initializeNativePool(natpoolinc, natpoolexc);

	return true;
}

void ResourceManagerImplementation::loadDefaultConfig() {

	resourceSpawner->addZone("corellia");
	resourceSpawner->addZone("lok");
	resourceSpawner->addZone("yavin4");
	resourceSpawner->addZone("dantooine");
	resourceSpawner->addZone("dathomir");
	resourceSpawner->addZone("naboo");
	resourceSpawner->addZone("rori");
	resourceSpawner->addZone("talus");
	resourceSpawner->addZone("tatooine");
	resourceSpawner->addZone("endor");

	shiftInterval = 7200000;
	resourceSpawner->setSpawningParameters(1, 86400, 90, 1000, 0);
}

void ResourceManagerImplementation::stop() {

}

void ResourceManagerImplementation::startResourceSpawner() {
	Locker _locker(_this.get());

	resourceSpawner->start();

	Reference<ResourceShiftTask*> resourceShift = new ResourceShiftTask(_this.get().get());
	resourceShift->schedule(shiftInterval);
}

void ResourceManagerImplementation::shiftResources() {
	Locker _locker(_this.get());

	resourceSpawner->shiftResources();

	Reference<ResourceShiftTask*> resourceShift = new ResourceShiftTask(_this.get().get());
	resourceShift->schedule(shiftInterval);
}

int ResourceManagerImplementation::getResourceRecycleType(ResourceSpawn* resource) {
	return resourceSpawner->sendResourceRecycleType(resource);
}

void ResourceManagerImplementation::sendResourceListForSurvey(CreatureObject* playerCreature, const int toolType, const String& surveyType) {
	ReadLocker locker(_this.get());

	resourceSpawner->sendResourceListForSurvey(playerCreature, toolType, surveyType);
}

ResourceContainer* ResourceManagerImplementation::harvestResource(CreatureObject* player, const String& type, const int quantity) {
	return resourceSpawner->harvestResource(player, type, quantity);
}
bool ResourceManagerImplementation::harvestResourceToPlayer(CreatureObject* player, ResourceSpawn* resourceSpawn, const int quantity) {
	return resourceSpawner->harvestResource(player, resourceSpawn, quantity);
}

void ResourceManagerImplementation::sendSurvey(CreatureObject* playerCreature, const String& resname) {
	resourceSpawner->sendSurvey(playerCreature, resname);
}

void ResourceManagerImplementation::sendSample(CreatureObject* playerCreature, const String& resname, const String& sampleAnimation) {
	resourceSpawner->sendSample(playerCreature, resname, sampleAnimation);

	playerCreature->registerObserver(ObserverEventType::POSTURECHANGED, _this.get());
}

void ResourceManagerImplementation::createResourceSpawn(CreatureObject* playerCreature, const String& restype) {
	Locker _locker(_this.get());

	ResourceSpawn* resourceSpawn = resourceSpawner->manualCreateResourceSpawn(restype);

	if (resourceSpawn != NULL) {
		StringBuffer buffer;
		buffer << "Spawned " << resourceSpawn->getName() << " of type " << resourceSpawn->getType();

		playerCreature->sendSystemMessage(buffer.toString());
	} else {
		playerCreature->sendSystemMessage("Could not create spawn " + restype);
	}

}

ResourceSpawn* ResourceManagerImplementation::getResourceSpawn(const String& spawnName) {
	ResourceSpawn* spawn = NULL;

	ReadLocker locker(_this.get());

	ResourceMap* resourceMap = resourceSpawner->getResourceMap();

	spawn = resourceMap->get(spawnName.toLowerCase());

	return spawn;
}

ResourceSpawn* ResourceManagerImplementation::getCurrentSpawn(const String& restype, const String& zoneName) {
	return resourceSpawner->getCurrentSpawn(restype, zoneName);
}

void ResourceManagerImplementation::getResourceListByType(Vector<ManagedReference<ResourceSpawn*> >& list, int type, const String& zoneName) {
	list.removeAll();

	ReadLocker locker(_this.get());

	ManagedReference<ResourceSpawn*> resourceSpawn;

	try {
		ResourceMap* resourceMap = resourceSpawner->getResourceMap();

		ZoneResourceMap* zoneMap = resourceMap->getZoneResourceList(zoneName);

		if (zoneMap != NULL) {
			for (int i = 0; i < zoneMap->size(); ++i) {
				resourceSpawn = zoneMap->get(i);

				if (!resourceSpawn->inShift())
					continue;

				if (type == 9){
					if (resourceSpawn->isType("radioactive"))
						list.add(resourceSpawn);
				}

				else if (resourceSpawn->getSurveyToolType() == type) {
					list.add(resourceSpawn);
				}
			}

		}

	} catch (Exception& e) {
		error(e.getMessage());
		e.printStackTrace();
	}
}

uint32 ResourceManagerImplementation::getAvailablePowerFromPlayer(CreatureObject* player) {
	SceneObject* inventory = player->getSlottedObject("inventory");
	uint32 power = 0;

	for (int i = 0; i < inventory->getContainerObjectsSize(); i++) {
		Reference<SceneObject*> obj =  inventory->getContainerObject(i).castTo<SceneObject*>();

		if (obj == NULL || !obj->isResourceContainer())
			continue;

		ResourceContainer* rcno = cast<ResourceContainer*>( obj.get());
		ManagedReference<ResourceSpawn*> spawn = rcno->getSpawnObject();

		if (spawn == NULL || !spawn->isEnergy())
			continue;

		int quantity = rcno->getQuantity();
		int pe = spawn->getValueOf(CraftingManager::PE); // potential energy

		float modifier = MAX(1.0f, pe / 500.0f);

		power += (uint32) (modifier * quantity);
	}

	return power;
}

void ResourceManagerImplementation::removePowerFromPlayer(CreatureObject* player, uint32 power) {
	if (power == 0)
		return;

	SceneObject* inventory = player->getSlottedObject("inventory");

	uint32 containerPower = 0;

	for (int i = 0; i < inventory->getContainerObjectsSize() && power > 0; ++i) {
		ManagedReference<SceneObject*> obj = inventory->getContainerObject(i);

		if (obj == NULL || !obj->isResourceContainer())
			continue;

		ResourceContainer* rcno = cast<ResourceContainer*>( obj.get());
		ManagedReference<ResourceSpawn*> spawn = rcno->getSpawnObject();

		if (spawn == NULL || !spawn->isEnergy())
			continue;

		int quantity = rcno->getQuantity();
		int pe = spawn->getValueOf(CraftingManager::PE); // potential energy

		float modifier = MAX(1.0f, pe / 500.0f);

		containerPower = modifier * quantity;

		if (containerPower > power) {
			uint32 consumedUnits = (uint64) power / modifier;
			rcno->setQuantity(quantity - consumedUnits);

			ResourceContainerObjectDeltaMessage3* drcno3 = new ResourceContainerObjectDeltaMessage3(rcno);
			drcno3->updateQuantity();
			drcno3->close();
			player->sendMessage(drcno3);
			return;
		} else {
			rcno->destroyObjectFromWorld(true);
			rcno->destroyObjectFromDatabase(true);
		}

		power -= containerPower;
	}
}
void ResourceManagerImplementation::givePlayerResource(CreatureObject* playerCreature, const String& restype, const int quantity) {
	ManagedReference<ResourceSpawn* > spawn = getResourceSpawn(restype);

	if(spawn == NULL) {
		playerCreature->sendSystemMessage("Selected spawn does not exist.");
		return;
	}

	ManagedReference<SceneObject*> inventory = playerCreature->getSlottedObject("inventory");

	if(inventory != NULL && !inventory->hasFullContainerObjects()) {

		ResourceContainer* newResource = spawn->createResource(quantity);

		if(newResource != NULL) {
			spawn->extractResource("", quantity);
			if (inventory->transferObject(newResource, -1, true)) {
				inventory->broadcastObject(newResource, true);
			} else {
				newResource->destroyObjectFromDatabase(true);
			}
		}
	}
}

bool ResourceManagerImplementation::isRecycledResource(ResourceSpawn* resource) {
	return resourceSpawner->isRecycledResource(resource);
}

ResourceSpawn* ResourceManagerImplementation::getRecycledVersion(ResourceSpawn* resource) {
	return resourceSpawner->getRecycledVersion(resource);
}

/// Resource Deed Methods
void ResourceManagerImplementation::addNodeToListBox(SuiListBox* sui, const String& nodeName) {
	resourceSpawner->addNodeToListBox(sui, nodeName);
}

void ResourceManagerImplementation::addPlanetsToListBox(SuiListBox* sui) {
	resourceSpawner->addPlanetsToListBox(sui);
}
String ResourceManagerImplementation::getPlanetByIndex(int idx) {
	return resourceSpawner->getPlanetByIndex(idx);
}
String ResourceManagerImplementation::addParentNodeToListBox(SuiListBox* sui, const String& currentNode) {
	return resourceSpawner->addParentNodeToListBox(sui, currentNode);
}

void ResourceManagerImplementation::listResourcesForPlanetOnScreen(CreatureObject* creature, const String& planet) {
	Locker locker(_this.get());

	resourceSpawner->listResourcesForPlanetOnScreen(creature, planet);
}

String ResourceManagerImplementation::healthCheck() {
	return resourceSpawner->healthCheck();
}

String ResourceManagerImplementation::dumpResources() {
	Locker locker(_this.get());

	return resourceSpawner->dumpResources();
}

String ResourceManagerImplementation::despawnResource(String& resourceName) {

	ManagedReference<ResourceSpawn*> spawn = getResourceSpawn(resourceName);
	if(spawn == NULL) {
		return "Spawn not Found";
	}

	spawn->setDespawned(time(0) - 1);
	resourceSpawner->shiftResources();

	return resourceName + " despawned.";
}
<commit_msg>[Fixed] stability issue<commit_after>/*
				Copyright <SWGEmu>
		See file COPYING for copying conditions.*/

#include "engine/engine.h"

#include "server/zone/managers/resource/ResourceManager.h"
#include "ResourceShiftTask.h"
#include "resourcespawner/SampleTask.h"
#include "resourcespawner/SampleResultsTask.h"
#include "server/zone/managers/resource/InterplanetarySurvey.h"
#include "server/zone/managers/resource/InterplanetarySurveyTask.h"
#include "server/zone/objects/resource/ResourceContainer.h"
#include "server/zone/packets/resource/ResourceContainerObjectDeltaMessage3.h"
#include "server/zone/objects/player/sui/listbox/SuiListBox.h"

void ResourceManagerImplementation::initialize() {
	lua = new Lua();
	lua->init();

	if(!loadConfigData()) {

		loadDefaultConfig();

		info("***** ERROR in configuration, using default values");
	}

	resourceSpawner->init();

	startResourceSpawner();
	loadSurveyData();
}

bool ResourceManagerImplementation::loadConfigFile() {
	return lua->runFile("scripts/managers/resource_manager.lua");
}
void ResourceManagerImplementation::loadSurveyData() {
	info("Loading survey data form surveys.db");
	ObjectDatabaseManager* dbManager = ObjectDatabaseManager::instance();
	ObjectDatabase* surveyDatabase = ObjectDatabaseManager::instance()->loadObjectDatabase("surveys", true);
	if (surveyDatabase == NULL) {
		error("Could not load the survey database.");
		return;
	}
	int i = 0;
	try {
		ObjectDatabaseIterator iterator(surveyDatabase);

		uint64 objectID;

		while (iterator.getNextKey(objectID)) {
			Core::getObjectBroker()->lookUp(objectID);
			++i;
		}
	} catch (DatabaseException& e) {
		error("Database exception in DirectorManager::loadSurveyData(): "	+ e.getMessage());
	}
	info(String::valueOf(i) + " surveys loaded.", true);
}
int ResourceManagerImplementation::notifyObserverEvent(uint32 eventType, Observable* observable, ManagedObject* arg1, int64 arg2) {
	if (eventType == ObserverEventType::POSTURECHANGED) {
		CreatureObject* creature = cast<CreatureObject*>( observable);
		// Cancel Sampling on posture change
		Reference<SampleTask*> task = creature->getPendingTask("sample").castTo<SampleTask*>( );
		Reference<SampleResultsTask*> sampleResultsTask = creature->getPendingTask("sampleresults").castTo<SampleResultsTask*>( );

		if (task != NULL) {

			task->stopSampling();
			//creature->removePendingTask("sample");

			if(sampleResultsTask != NULL) {
				sampleResultsTask->cancel();
				creature->removePendingTask("sampleresults");
			}

			creature->sendSystemMessage("@survey:sample_cancel");
		}
	}

	return 1;
}

bool ResourceManagerImplementation::loadConfigData() {
	if (!loadConfigFile())
		return false;

	bool loadFromScript = lua->getGlobalInt("buildInitialResourcesFromScript");

	String zonesString = lua->getGlobalString("activeZones");

	StringTokenizer zonesTokens(zonesString);
	zonesTokens.setDelimeter(",");

	while(zonesTokens.hasMoreTokens()) {
		String zoneName;
		zonesTokens.getStringToken(zoneName);
		resourceSpawner->addZone(zoneName);
	}

	shiftInterval = lua->getGlobalInt("averageShiftTime");

	int aveduration = lua->getGlobalInt("aveduration");
	float spawnThrottling = float(lua->getGlobalInt("spawnThrottling")) / 100.0f;
	int lowerGateOverride = lua->getGlobalInt("lowerGateOverride");
	int maxSpawnQuantity = lua->getGlobalInt("maxSpawnQuantity");

	resourceSpawner->setSpawningParameters(loadFromScript, aveduration,
			spawnThrottling, lowerGateOverride, maxSpawnQuantity);

	String jtlResources = lua->getGlobalString("jtlresources");

	StringTokenizer jtlTokens(jtlResources);
	jtlTokens.setDelimeter(",");

	while(jtlTokens.hasMoreTokens()) {
		String token;
		jtlTokens.getStringToken(token);
		resourceSpawner->addJtlResource(token);
	}

	LuaObject minpoolinc = lua->getGlobalObject("minimumpoolincludes");
	String minpoolexc = lua->getGlobalString("minimumpoolexcludes");
	resourceSpawner->initializeMinimumPool(minpoolinc, minpoolexc);

	LuaObject randpoolinc = lua->getGlobalObject("randompoolincludes");
	String randpoolexc = lua->getGlobalString("randompoolexcludes");
	int randpoolsize = lua->getGlobalInt("randompoolsize");
	resourceSpawner->initializeRandomPool(randpoolinc, randpoolexc, randpoolsize);

	LuaObject fixedpoolinc = lua->getGlobalObject("fixedpoolincludes");
	String fixedpoolexc = lua->getGlobalString("fixedpoolexcludes");
	resourceSpawner->initializeFixedPool(fixedpoolinc, fixedpoolexc);

	String natpoolinc = lua->getGlobalString("nativepoolincludes");
	String natpoolexc = lua->getGlobalString("nativepoolexcludes");
	resourceSpawner->initializeNativePool(natpoolinc, natpoolexc);

	return true;
}

void ResourceManagerImplementation::loadDefaultConfig() {

	resourceSpawner->addZone("corellia");
	resourceSpawner->addZone("lok");
	resourceSpawner->addZone("yavin4");
	resourceSpawner->addZone("dantooine");
	resourceSpawner->addZone("dathomir");
	resourceSpawner->addZone("naboo");
	resourceSpawner->addZone("rori");
	resourceSpawner->addZone("talus");
	resourceSpawner->addZone("tatooine");
	resourceSpawner->addZone("endor");

	shiftInterval = 7200000;
	resourceSpawner->setSpawningParameters(1, 86400, 90, 1000, 0);
}

void ResourceManagerImplementation::stop() {

}

void ResourceManagerImplementation::startResourceSpawner() {
	Locker _locker(_this.get());

	resourceSpawner->start();

	Reference<ResourceShiftTask*> resourceShift = new ResourceShiftTask(_this.get().get());
	resourceShift->schedule(shiftInterval);
}

void ResourceManagerImplementation::shiftResources() {
	Locker _locker(_this.get());

	resourceSpawner->shiftResources();

	Reference<ResourceShiftTask*> resourceShift = new ResourceShiftTask(_this.get().get());
	resourceShift->schedule(shiftInterval);
}

int ResourceManagerImplementation::getResourceRecycleType(ResourceSpawn* resource) {
	return resourceSpawner->sendResourceRecycleType(resource);
}

void ResourceManagerImplementation::sendResourceListForSurvey(CreatureObject* playerCreature, const int toolType, const String& surveyType) {
	ReadLocker locker(_this.get());

	resourceSpawner->sendResourceListForSurvey(playerCreature, toolType, surveyType);
}

ResourceContainer* ResourceManagerImplementation::harvestResource(CreatureObject* player, const String& type, const int quantity) {
	return resourceSpawner->harvestResource(player, type, quantity);
}
bool ResourceManagerImplementation::harvestResourceToPlayer(CreatureObject* player, ResourceSpawn* resourceSpawn, const int quantity) {
	return resourceSpawner->harvestResource(player, resourceSpawn, quantity);
}

void ResourceManagerImplementation::sendSurvey(CreatureObject* playerCreature, const String& resname) {
	resourceSpawner->sendSurvey(playerCreature, resname);
}

void ResourceManagerImplementation::sendSample(CreatureObject* playerCreature, const String& resname, const String& sampleAnimation) {
	resourceSpawner->sendSample(playerCreature, resname, sampleAnimation);

	playerCreature->registerObserver(ObserverEventType::POSTURECHANGED, _this.get());
}

void ResourceManagerImplementation::createResourceSpawn(CreatureObject* playerCreature, const String& restype) {
	Locker _locker(_this.get());

	ResourceSpawn* resourceSpawn = resourceSpawner->manualCreateResourceSpawn(restype);

	if (resourceSpawn != NULL) {
		StringBuffer buffer;
		buffer << "Spawned " << resourceSpawn->getName() << " of type " << resourceSpawn->getType();

		playerCreature->sendSystemMessage(buffer.toString());
	} else {
		playerCreature->sendSystemMessage("Could not create spawn " + restype);
	}

}

ResourceSpawn* ResourceManagerImplementation::getResourceSpawn(const String& spawnName) {
	ResourceSpawn* spawn = NULL;

	ReadLocker locker(_this.get());

	ResourceMap* resourceMap = resourceSpawner->getResourceMap();

	spawn = resourceMap->get(spawnName.toLowerCase());

	return spawn;
}

ResourceSpawn* ResourceManagerImplementation::getCurrentSpawn(const String& restype, const String& zoneName) {
	return resourceSpawner->getCurrentSpawn(restype, zoneName);
}

void ResourceManagerImplementation::getResourceListByType(Vector<ManagedReference<ResourceSpawn*> >& list, int type, const String& zoneName) {
	list.removeAll();

	ReadLocker locker(_this.get());

	ManagedReference<ResourceSpawn*> resourceSpawn;

	try {
		ResourceMap* resourceMap = resourceSpawner->getResourceMap();

		ZoneResourceMap* zoneMap = resourceMap->getZoneResourceList(zoneName);

		if (zoneMap != NULL) {
			for (int i = 0; i < zoneMap->size(); ++i) {
				resourceSpawn = zoneMap->get(i);

				if (!resourceSpawn->inShift())
					continue;

				if (type == 9){
					if (resourceSpawn->isType("radioactive"))
						list.add(resourceSpawn);
				}

				else if (resourceSpawn->getSurveyToolType() == type) {
					list.add(resourceSpawn);
				}
			}

		}

	} catch (Exception& e) {
		error(e.getMessage());
		e.printStackTrace();
	}
}

uint32 ResourceManagerImplementation::getAvailablePowerFromPlayer(CreatureObject* player) {
	SceneObject* inventory = player->getSlottedObject("inventory");
	uint32 power = 0;

	for (int i = 0; i < inventory->getContainerObjectsSize(); i++) {
		Reference<SceneObject*> obj =  inventory->getContainerObject(i).castTo<SceneObject*>();

		if (obj == NULL || !obj->isResourceContainer())
			continue;

		ResourceContainer* rcno = cast<ResourceContainer*>( obj.get());
		ManagedReference<ResourceSpawn*> spawn = rcno->getSpawnObject();

		if (spawn == NULL || !spawn->isEnergy())
			continue;

		int quantity = rcno->getQuantity();
		int pe = spawn->getValueOf(CraftingManager::PE); // potential energy

		float modifier = MAX(1.0f, pe / 500.0f);

		power += (uint32) (modifier * quantity);
	}

	return power;
}

void ResourceManagerImplementation::removePowerFromPlayer(CreatureObject* player, uint32 power) {
	if (power == 0)
		return;

	SceneObject* inventory = player->getSlottedObject("inventory");

	uint32 containerPower = 0;

	for (int i = 0; i < inventory->getContainerObjectsSize() && power > 0; ++i) {
		ManagedReference<SceneObject*> obj = inventory->getContainerObject(i);

		if (obj == NULL || !obj->isResourceContainer())
			continue;

		ResourceContainer* rcno = cast<ResourceContainer*>( obj.get());

		Locker locker(rcno);

		ManagedReference<ResourceSpawn*> spawn = rcno->getSpawnObject();

		if (spawn == NULL || !spawn->isEnergy())
			continue;

		int quantity = rcno->getQuantity();
		int pe = spawn->getValueOf(CraftingManager::PE); // potential energy

		float modifier = MAX(1.0f, pe / 500.0f);

		containerPower = modifier * quantity;

		if (containerPower > power) {
			uint32 consumedUnits = (uint64) power / modifier;
			rcno->setQuantity(quantity - consumedUnits);

			ResourceContainerObjectDeltaMessage3* drcno3 = new ResourceContainerObjectDeltaMessage3(rcno);
			drcno3->updateQuantity();
			drcno3->close();
			player->sendMessage(drcno3);
			return;
		} else {
			rcno->destroyObjectFromWorld(true);
			rcno->destroyObjectFromDatabase(true);
		}

		power -= containerPower;
	}
}
void ResourceManagerImplementation::givePlayerResource(CreatureObject* playerCreature, const String& restype, const int quantity) {
	ManagedReference<ResourceSpawn* > spawn = getResourceSpawn(restype);

	if(spawn == NULL) {
		playerCreature->sendSystemMessage("Selected spawn does not exist.");
		return;
	}

	ManagedReference<SceneObject*> inventory = playerCreature->getSlottedObject("inventory");

	if(inventory != NULL && !inventory->hasFullContainerObjects()) {

		ResourceContainer* newResource = spawn->createResource(quantity);

		if(newResource != NULL) {
			spawn->extractResource("", quantity);
			if (inventory->transferObject(newResource, -1, true)) {
				inventory->broadcastObject(newResource, true);
			} else {
				newResource->destroyObjectFromDatabase(true);
			}
		}
	}
}

bool ResourceManagerImplementation::isRecycledResource(ResourceSpawn* resource) {
	return resourceSpawner->isRecycledResource(resource);
}

ResourceSpawn* ResourceManagerImplementation::getRecycledVersion(ResourceSpawn* resource) {
	return resourceSpawner->getRecycledVersion(resource);
}

/// Resource Deed Methods
void ResourceManagerImplementation::addNodeToListBox(SuiListBox* sui, const String& nodeName) {
	resourceSpawner->addNodeToListBox(sui, nodeName);
}

void ResourceManagerImplementation::addPlanetsToListBox(SuiListBox* sui) {
	resourceSpawner->addPlanetsToListBox(sui);
}
String ResourceManagerImplementation::getPlanetByIndex(int idx) {
	return resourceSpawner->getPlanetByIndex(idx);
}
String ResourceManagerImplementation::addParentNodeToListBox(SuiListBox* sui, const String& currentNode) {
	return resourceSpawner->addParentNodeToListBox(sui, currentNode);
}

void ResourceManagerImplementation::listResourcesForPlanetOnScreen(CreatureObject* creature, const String& planet) {
	Locker locker(_this.get());

	resourceSpawner->listResourcesForPlanetOnScreen(creature, planet);
}

String ResourceManagerImplementation::healthCheck() {
	return resourceSpawner->healthCheck();
}

String ResourceManagerImplementation::dumpResources() {
	Locker locker(_this.get());

	return resourceSpawner->dumpResources();
}

String ResourceManagerImplementation::despawnResource(String& resourceName) {

	ManagedReference<ResourceSpawn*> spawn = getResourceSpawn(resourceName);
	if(spawn == NULL) {
		return "Spawn not Found";
	}

	spawn->setDespawned(time(0) - 1);
	resourceSpawner->shiftResources();

	return resourceName + " despawned.";
}
<|endoftext|>


<commit_before>#include "specter/ViewResources.hpp"

namespace specter
{
static logvisor::Module Log("specter::ViewResources");

void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache,
                         const IThemeData* theme, float pf)
{
    if (!factory || !fcache || !theme)
        Log.report(logvisor::Fatal, "all arguments of ViewResources::init() must be non-null");
    m_pixelFactor = pf;
    m_factory = factory;
    m_theme = theme;
    m_fcache = fcache;
    unsigned dpi = 72.f * m_pixelFactor;

    m_curveFont = fcache->prepCurvesFont(factory, AllCharFilter, false, 8.f, dpi);

    m_resData = factory->commitTransaction(
    [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
    {
        switch (ctx.platform())
        {
        case boo::IGraphicsDataFactory::Platform::OGL:
            init<boo::GLDataFactory::Context>(static_cast<boo::GLDataFactory::Context&>(ctx), *theme, fcache);
            break;
#if _WIN32
        case boo::IGraphicsDataFactory::Platform::D3D11:
        case boo::IGraphicsDataFactory::Platform::D3D12:
            init<boo::ID3DDataFactory::Context>(static_cast<boo::ID3DDataFactory::Context&>(ctx), *theme, fcache);
            break;
#endif
#if BOO_HAS_METAL
        case boo::IGraphicsDataFactory::Platform::Metal:
            init<boo::MetalDataFactory::Context>(static_cast<boo::MetalDataFactory::Context&>(ctx), *theme, fcache);
            break;
#endif
#if BOO_HAS_VULKAN
        case boo::IGraphicsDataFactory::Platform::Vulkan:
            init<boo::VulkanDataFactory::Context>(static_cast<boo::VulkanDataFactory::Context&>(ctx), *theme, fcache);
            break;
#endif
        default:
            Log.report(logvisor::Fatal, _S("unable to init view system for %s"), ctx.platformName());
        }
        return true;
    });
}

void ViewResources::prepFontCacheSync()
{
    unsigned dpi = 72.f * m_pixelFactor;
    if (m_fcacheInterrupt) return;
    m_mainFont = m_fcache->prepMainFont(m_factory, AllCharFilter, false, 10.f, dpi);
    if (m_fcacheInterrupt) return;
    m_monoFont = m_fcache->prepMonoFont(m_factory, AllCharFilter, false, 10.f, dpi);
    if (m_fcacheInterrupt) return;
    m_heading14 = m_fcache->prepMainFont(m_factory, LatinAndJapaneseCharFilter, false, 14.f, dpi);
    if (m_fcacheInterrupt) return;
    m_heading18 = m_fcache->prepMainFont(m_factory, LatinAndJapaneseCharFilter, false, 18.f, dpi);
    if (m_fcacheInterrupt) return;
    m_titleFont = m_fcache->prepMainFont(m_factory, LatinCharFilter, false, 36.f, dpi);
    if (m_fcacheInterrupt) return;
    m_fcache->closeBuiltinFonts();
    m_fcacheReady = true;
}

void ViewResources::prepFontCacheAsync(boo::IWindow* window)
{
    m_fcacheReady = false;
    m_fcacheThread = std::thread([this, window]()
    {
        window->getLoadContextDataFactory();
        prepFontCacheSync();
    });
}

void ViewResources::resetPixelFactor(float pf)
{
    m_pixelFactor = pf;
    unsigned dpi = 72.f * m_pixelFactor;
    m_curveFont = m_fcache->prepCurvesFont(m_factory, AllCharFilter, false, 8.f, dpi);
    prepFontCacheSync();
}

void ViewResources::resetTheme(const IThemeData* theme)
{
    m_theme = theme;
}

}
<commit_msg>OpenGL enum change<commit_after>#include "specter/ViewResources.hpp"

namespace specter
{
static logvisor::Module Log("specter::ViewResources");

void ViewResources::init(boo::IGraphicsDataFactory* factory, FontCache* fcache,
                         const IThemeData* theme, float pf)
{
    if (!factory || !fcache || !theme)
        Log.report(logvisor::Fatal, "all arguments of ViewResources::init() must be non-null");
    m_pixelFactor = pf;
    m_factory = factory;
    m_theme = theme;
    m_fcache = fcache;
    unsigned dpi = 72.f * m_pixelFactor;

    m_curveFont = fcache->prepCurvesFont(factory, AllCharFilter, false, 8.f, dpi);

    m_resData = factory->commitTransaction(
    [&](boo::IGraphicsDataFactory::Context& ctx) -> bool
    {
        switch (ctx.platform())
        {
        case boo::IGraphicsDataFactory::Platform::OpenGL:
            init<boo::GLDataFactory::Context>(static_cast<boo::GLDataFactory::Context&>(ctx), *theme, fcache);
            break;
#if _WIN32
        case boo::IGraphicsDataFactory::Platform::D3D11:
        case boo::IGraphicsDataFactory::Platform::D3D12:
            init<boo::ID3DDataFactory::Context>(static_cast<boo::ID3DDataFactory::Context&>(ctx), *theme, fcache);
            break;
#endif
#if BOO_HAS_METAL
        case boo::IGraphicsDataFactory::Platform::Metal:
            init<boo::MetalDataFactory::Context>(static_cast<boo::MetalDataFactory::Context&>(ctx), *theme, fcache);
            break;
#endif
#if BOO_HAS_VULKAN
        case boo::IGraphicsDataFactory::Platform::Vulkan:
            init<boo::VulkanDataFactory::Context>(static_cast<boo::VulkanDataFactory::Context&>(ctx), *theme, fcache);
            break;
#endif
        default:
            Log.report(logvisor::Fatal, _S("unable to init view system for %s"), ctx.platformName());
        }
        return true;
    });
}

void ViewResources::prepFontCacheSync()
{
    unsigned dpi = 72.f * m_pixelFactor;
    if (m_fcacheInterrupt) return;
    m_mainFont = m_fcache->prepMainFont(m_factory, AllCharFilter, false, 10.f, dpi);
    if (m_fcacheInterrupt) return;
    m_monoFont = m_fcache->prepMonoFont(m_factory, AllCharFilter, false, 10.f, dpi);
    if (m_fcacheInterrupt) return;
    m_heading14 = m_fcache->prepMainFont(m_factory, LatinAndJapaneseCharFilter, false, 14.f, dpi);
    if (m_fcacheInterrupt) return;
    m_heading18 = m_fcache->prepMainFont(m_factory, LatinAndJapaneseCharFilter, false, 18.f, dpi);
    if (m_fcacheInterrupt) return;
    m_titleFont = m_fcache->prepMainFont(m_factory, LatinCharFilter, false, 36.f, dpi);
    if (m_fcacheInterrupt) return;
    m_fcache->closeBuiltinFonts();
    m_fcacheReady = true;
}

void ViewResources::prepFontCacheAsync(boo::IWindow* window)
{
    m_fcacheReady = false;
    m_fcacheThread = std::thread([this, window]()
    {
        window->getLoadContextDataFactory();
        prepFontCacheSync();
    });
}

void ViewResources::resetPixelFactor(float pf)
{
    m_pixelFactor = pf;
    unsigned dpi = 72.f * m_pixelFactor;
    m_curveFont = m_fcache->prepCurvesFont(m_factory, AllCharFilter, false, 8.f, dpi);
    prepFontCacheSync();
}

void ViewResources::resetTheme(const IThemeData* theme)
{
    m_theme = theme;
}

}
<|endoftext|>


<commit_before>#include "chimera/visitor.h"

#include <algorithm>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <llvm/Support/raw_ostream.h>
#include <string>

using namespace chimera;
using namespace clang;
using boost::algorithm::join;

// TODO: Support template functions.
// TODO: Detect missing copy constructors, possibly using:
//  hasUserDeclaredCopyConstructor()
//  hasCopyConstructorWithConstParam ()
// TODO: Mark abstract classes as noncopyable?

chimera::Visitor::Visitor(clang::CompilerInstance *ci,
                          std::unique_ptr<CompiledConfiguration> cc)
: context_(&(ci->getASTContext()))
, printing_policy_(ci->getLangOpts())
, config_(std::move(cc))
{
    // Do nothing.
}

bool chimera::Visitor::VisitDecl(Decl *decl)
{
    // Only visit declarations in namespaces we are configured to read.
    if (!IsEnclosed(decl))
        return true;

    if (isa<ClassTemplateDecl>(decl))
        GenerateClassTemplate(cast<ClassTemplateDecl>(decl));
    else if (isa<CXXRecordDecl>(decl))
        GenerateCXXRecord(cast<CXXRecordDecl>(decl));
    else if (isa<EnumDecl>(decl))
        GenerateEnum(cast<EnumDecl>(decl));
    else if (isa<VarDecl>(decl))
        GenerateGlobalVar(cast<VarDecl>(decl));
    else if (isa<FunctionDecl>(decl))
        GenerateGlobalFunction(cast<FunctionDecl>(decl));

    return true;
}

bool chimera::Visitor::GenerateCXXRecord(CXXRecordDecl *const decl)
{
    // Only traverse CXX records that contain the actual class definition.
    if (!decl->hasDefinition() || decl->getDefinition() != decl)
        return false;

    // Open a stream object unique to this CXX record's mangled name.
    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    // Get configuration, and use any overrides if they exist.
    if (config_->DumpOverride(decl, *stream))
        return true;

    const YAML::Node &node = config_->GetDeclaration(decl);
    if (node.IsNull())
        return false; // Explicitly suppressed.

    *stream << "::boost::python::class_<"
            << decl->getTypeForDecl()->getCanonicalTypeInternal().getAsString(printing_policy_);

    const YAML::Node &noncopyable_node = node["noncopyable"];
    if (noncopyable_node && noncopyable_node.as<bool>(false))
        *stream << ", ::boost::noncopyable";

    if (const YAML::Node &held_type_node = node["held_type"])
        *stream << ", " << held_type_node.as<std::string>();

    std::vector<std::string> base_names;

    if (const YAML::Node &bases_node = node["bases"])
        base_names = bases_node.as<std::vector<std::string> >();
    else
        base_names = GetBaseClassNames(decl);

    if (!base_names.empty())
    {
        *stream << ", ::boost::python::bases<"
                  << join(base_names, ", ") << " >";
    }

    *stream << " >(\"" << decl->getNameAsString()
            << "\", boost::python::no_init)\n";

    // Methods
    std::set<std::string> overloaded_method_names;

    for (CXXMethodDecl *const method_decl : decl->methods())
    {
        if (method_decl->getAccess() != AS_public)
            continue; // skip protected and private members

        if (isa<CXXConversionDecl>(method_decl))
            ; // do nothing
        else if (isa<CXXDestructorDecl>(method_decl))
            ; // do nothing
        else if (isa<CXXConstructorDecl>(method_decl))
        {
            GenerateCXXConstructor(
                *stream, decl, cast<CXXConstructorDecl>(method_decl));
        }
        else if (method_decl->isOverloadedOperator())
            ; // TODO: Wrap overloaded operators.
        else if (method_decl->isStatic())
        {
            // TODO: Missing the dot.
            if (GenerateFunction(*stream, decl, method_decl))
                overloaded_method_names.insert(method_decl->getNameAsString());
        }
        else
        {
            // TODO: Missing the dot.
            GenerateFunction(*stream, decl, method_decl);
        }
    }

    // Static methods MUST be declared after overloads are defined.
    for (const std::string &method_name : overloaded_method_names)
        *stream << ".staticmethod(\"" << method_name << "\")\n";

    // Fields
    for (FieldDecl *const field_decl : decl->fields())
    {
        if (field_decl->getAccess() != AS_public)
            continue; // skip protected and private fields

        GenerateField(*stream, decl, field_decl);
    }

    for (Decl *const child_decl : decl->decls())
    {
        if (isa<VarDecl>(child_decl))
            GenerateStaticField(*stream, decl, cast<VarDecl>(child_decl));
    }

    *stream << ";\n";

    return true;
}

bool chimera::Visitor::GenerateCXXConstructor(
    chimera::Stream &stream,
    CXXRecordDecl *class_decl,
    CXXConstructorDecl *decl)
{
    decl = decl->getCanonicalDecl();

    if (decl->isDeleted())
        return false;

    std::vector<std::string> argument_types;

    for (ParmVarDecl *param_decl : decl->params())
        argument_types.push_back(param_decl->getType().getAsString(printing_policy_));

    stream << ".def(::boost::python::init<"
           << join(argument_types, ", ")
           << ">())\n";
    return true;
}

bool chimera::Visitor::GenerateFunction(
    chimera::Stream &stream,
    CXXRecordDecl *class_decl, FunctionDecl *decl)
{
    decl = decl->getCanonicalDecl();

    if (decl->isDeleted())
        return false;

    // Get configuration, and use any overrides if they exist.
    if (config_->DumpOverride(decl, stream))
        return true;

    const YAML::Node &node = config_->GetDeclaration(decl);
    if (node.IsNull())
        return false; // Explicitly suppressed.

    // Extract the pointer type of this function declaration.
    QualType pointer_type;
    if (class_decl && !cast<CXXMethodDecl>(decl)->isStatic())
    {
        pointer_type = context_->getMemberPointerType(
            decl->getType(), class_decl->getTypeForDecl());
    }
    else
    {
        pointer_type = context_->getPointerType(decl->getType());
    }
    pointer_type = pointer_type.getCanonicalType();

    // Extract the return type of this function declaration.
    const QualType return_qual_type = decl->getReturnType();
    const Type *return_type = return_qual_type.getTypePtr();

    // First, check if a return_value_policy was specified for this function.
    std::string return_value_policy
      = node["return_value_policy"].as<std::string>("");

    // Next, check if a return_value_policy is defined on the return type.
    if (return_value_policy.empty())
    {
        const YAML::Node &type_node = config_->GetType(return_qual_type);
        return_value_policy
          = type_node["return_value_policy"].as<std::string>("");
    }

    // Finally, try the default return_value_policy. This is only acceptable if
    // the output is copy constructable.
    if (return_value_policy.empty())
    {
        if (return_type->isReferenceType())
        {
            std::cerr
                << "Warning: Skipped method '"
                << decl->getQualifiedNameAsString()
                << "' with signature '"
                << decl->getType().getAsString(printing_policy_)
                << "' because it returns a reference and no"
                   " 'return_value_policy' was specified.\n";
            return false;
        }
        else if (return_type->isPointerType())
        {
            std::cerr
                << "Warning: Skipped method '"
                << decl->getQualifiedNameAsString()
                << "' with signature '"
                << decl->getType().getAsString(printing_policy_)
                << "' because it returns a pointer and no"
                   " 'return_value_policy' was specified.\n";
            return false;
        }
        // TODO: Check if return_type is non-copyable.
    }

    // If we are inside a class declaration, this is being called within a
    // builder pattern and will start with '.' since it is a member function.
    if (class_decl)
        stream << ".";

    // Create the actual function declaration here using its name and its
    // full pointer reference.
    stream << "def(\"" << decl->getNameAsString() << "\""
           << ", static_cast<" << pointer_type.getAsString(printing_policy_) << ">(&"
           << decl->getQualifiedNameAsString() << ")";

    // If a return value policy was specified, insert it after the function.
    if (!return_value_policy.empty())
    {
        stream << ", ::boost::python::return_value_policy<"
               << return_value_policy << " >";
    }

    // Construct a list of the arguments that are provided to this function,
    // and define named arguments for them based on their c++ names.
    const auto params = GetParameterNames(decl);
    if (!params.empty())
    {
        // TODO: Suppress any default parameters that occur after the first
        // non-default to default transition. This can only occur if evaluating
        // the default value of one or more parameters failed.

        // TODO: Assign names to unnamed arguments.

        std::vector<std::string> python_args;
        for (const auto &param : params)
        {
            std::stringstream python_arg;
            python_arg << "::boost::python::arg(\"" << param.first << "\")";

            if (!param.second.empty())
                python_arg << " = " << param.second;

            python_args.push_back(python_arg.str());
        }

        stream << ", (" << join(python_args, ", ") << ")";
    }

    stream << ")\n";
    return true;
}

bool chimera::Visitor::GenerateField(
    chimera::Stream &stream,
    clang::CXXRecordDecl *class_decl,
    clang::FieldDecl *decl)
{
    if (decl->getType().isConstQualified())
        stream << ".def_readonly";
    else
        stream << ".def_readwrite";

    // TODO: Check if a copy constructor is defined for this type.

    stream << "(\"" << decl->getNameAsString() << "\","
           << " &" << decl->getQualifiedNameAsString() << ")\n";
    return true;
}

bool chimera::Visitor::GenerateStaticField(
    chimera::Stream &stream,
    clang::CXXRecordDecl *class_decl,
    clang::VarDecl *decl)
{
    if (decl->getAccess() != AS_public)
        return false;
    else if (!decl->isStaticDataMember())
        return false;

    stream << ".add_static_property(\"" << decl->getNameAsString() << "\", "
           << "[]() { return " << decl->getQualifiedNameAsString() << "; }";

    if (!decl->getType().isConstQualified())
    {
        stream << "[](" << decl->getType().getAsString(printing_policy_) << " value) { "
               << decl->getQualifiedNameAsString() << " = value; }";
    }

    stream << ")\n";

    return true;
}

bool chimera::Visitor::GenerateClassTemplate(clang::ClassTemplateDecl *decl)
{
    if (decl != decl->getCanonicalDecl())
        return false;

    for (ClassTemplateSpecializationDecl *spec_decl : decl->specializations())
    {
        if (spec_decl->getSpecializationKind() == TSK_Undeclared)
            continue;

        CXXRecordDecl *decl = spec_decl->getTypeForDecl()->getAsCXXRecordDecl();
        GenerateCXXRecord(decl);
    }

    return true;
}

bool chimera::Visitor::GenerateEnum(clang::EnumDecl *decl)
{
    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    *stream << "::boost::python::enum_<"
            << decl->getQualifiedNameAsString()
            << ">(\"" << decl->getNameAsString() << "\")\n";

    for (EnumConstantDecl *constant_decl : decl->enumerators())
    {
        *stream << ".value(\"" << constant_decl->getNameAsString() << "\", "
                << constant_decl->getQualifiedNameAsString() << ")\n";
    }

    *stream << ";\n";

    return true;
}

bool chimera::Visitor::GenerateGlobalVar(clang::VarDecl *decl)
{
    if (!decl->isFileVarDecl())
        return false;
    else if (!decl->isThisDeclarationADefinition())
        return false;

    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    *stream << "::boost::python::scope().attr(\"" << decl->getNameAsString()
            << "\") = " << decl->getQualifiedNameAsString() << ";\n";
    return true;
}

bool chimera::Visitor::GenerateGlobalFunction(clang::FunctionDecl *decl)
{
    if (isa<clang::CXXMethodDecl>(decl))
        return false;
    else if (decl->isOverloadedOperator())
        return false; // TODO: Wrap overloaded operators.

    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    return GenerateFunction(*stream, nullptr, decl);
}

std::vector<std::string> chimera::Visitor::GetBaseClassNames(
    CXXRecordDecl *decl) const
{
    std::vector<std::string> base_names;

    for (CXXBaseSpecifier &base_decl : decl->bases())
    {
        if (base_decl.getAccessSpecifier() != AS_public)
            continue;

        // TODO: Filter out transitive base classes.

        CXXRecordDecl *const base_record_decl
          = base_decl.getType()->getAsCXXRecordDecl();
        const QualType base_record_type
          = base_record_decl->getTypeForDecl()->getCanonicalTypeInternal();

        base_names.push_back(base_record_type.getAsString(printing_policy_));
    }

    return base_names;
}

std::vector<std::pair<std::string, std::string>>
    chimera::Visitor::GetParameterNames(clang::FunctionDecl *decl) const
{
    std::vector<std::pair<std::string, std::string>> params;

    for (ParmVarDecl *param_decl : decl->params())
    {
        const std::string param_name = param_decl->getNameAsString();
        const Type *param_type = param_decl->getType().getTypePtr();
        std::string param_value;

        if (param_decl->hasDefaultArg()
            && !param_decl->hasUninstantiatedDefaultArg()
            && !param_decl->hasUnparsedDefaultArg())
        {
            Expr *default_expr = param_decl->getDefaultArg();
            assert(default_expr);

            Expr::EvalResult result;
            bool success;

            if (param_type->isReferenceType())
                success = default_expr->EvaluateAsLValue(result, *context_);
            else
                success = default_expr->EvaluateAsRValue(result, *context_);

            if (success)
            {
                param_value = result.Val.getAsString(
                    *context_, param_decl->getType());
            }
            else if (default_expr->hasNonTrivialCall(*context_))
            {
                // TODO: How do we print the decl with argument + return types?
                std::cerr
                  << "Warning: Unable to evaluate non-trivial call in default"
                     " value for parameter"
                  << " '" << param_name << "' of method"
                  << " '" << decl->getQualifiedNameAsString() << "'.\n";
            }
            else
            {
                // TODO: How do we print the decl with argument + return types?
                std::cerr
                  << "Warning: Failed to evaluate default value for parameter"
                  << " '" << param_name << "' of method"
                  << " '" << decl->getQualifiedNameAsString() << "'.\n";
            }
        }

        params.push_back(std::make_pair(param_name, param_value));
    }

    return params;
}

bool chimera::Visitor::IsEnclosed(Decl *decl) const
{
    // Filter over the namespaces and only traverse ones that are enclosed
    // by one of the configuration namespaces.
    for (const auto &it : config_->GetNamespaces())
    {
        if (decl->getDeclContext() && it->Encloses(decl->getDeclContext()))
        {
            return true;
        }
    }
    return false;
}
<commit_msg>Fixed whitespace and printing method pointer_type.<commit_after>#include "chimera/visitor.h"

#include <algorithm>
#include <boost/algorithm/string/join.hpp>
#include <iostream>
#include <llvm/Support/raw_ostream.h>
#include <string>

using namespace chimera;
using namespace clang;
using boost::algorithm::join;

// TODO: Support template functions.
// TODO: Detect missing copy constructors, possibly using:
//  hasUserDeclaredCopyConstructor()
//  hasCopyConstructorWithConstParam ()
// TODO: Mark abstract classes as noncopyable?

chimera::Visitor::Visitor(clang::CompilerInstance *ci,
                          std::unique_ptr<CompiledConfiguration> cc)
: context_(&(ci->getASTContext()))
, printing_policy_(ci->getLangOpts())
, config_(std::move(cc))
{
    // Do nothing.
}

bool chimera::Visitor::VisitDecl(Decl *decl)
{
    // Only visit declarations in namespaces we are configured to read.
    if (!IsEnclosed(decl))
        return true;

    if (isa<ClassTemplateDecl>(decl))
        GenerateClassTemplate(cast<ClassTemplateDecl>(decl));
    else if (isa<CXXRecordDecl>(decl))
        GenerateCXXRecord(cast<CXXRecordDecl>(decl));
    else if (isa<EnumDecl>(decl))
        GenerateEnum(cast<EnumDecl>(decl));
    else if (isa<VarDecl>(decl))
        GenerateGlobalVar(cast<VarDecl>(decl));
    else if (isa<FunctionDecl>(decl))
        GenerateGlobalFunction(cast<FunctionDecl>(decl));

    return true;
}

bool chimera::Visitor::GenerateCXXRecord(CXXRecordDecl *const decl)
{
    // Only traverse CXX records that contain the actual class definition.
    if (!decl->hasDefinition() || decl->getDefinition() != decl)
        return false;

    // Open a stream object unique to this CXX record's mangled name.
    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    // Get configuration, and use any overrides if they exist.
    if (config_->DumpOverride(decl, *stream))
        return true;

    const YAML::Node &node = config_->GetDeclaration(decl);
    if (node.IsNull())
        return false; // Explicitly suppressed.

    *stream << "::boost::python::class_<"
            << decl->getTypeForDecl()->getCanonicalTypeInternal().getAsString(printing_policy_);

    const YAML::Node &noncopyable_node = node["noncopyable"];
    if (noncopyable_node && noncopyable_node.as<bool>(false))
        *stream << ", ::boost::noncopyable";

    if (const YAML::Node &held_type_node = node["held_type"])
        *stream << ", " << held_type_node.as<std::string>();

    std::vector<std::string> base_names;

    if (const YAML::Node &bases_node = node["bases"])
        base_names = bases_node.as<std::vector<std::string> >();
    else
        base_names = GetBaseClassNames(decl);

    if (!base_names.empty())
    {
        *stream << ", ::boost::python::bases<"
                  << join(base_names, ", ") << " >";
    }

    *stream << " >(\"" << decl->getNameAsString()
            << "\", boost::python::no_init)\n";

    // Methods
    std::set<std::string> overloaded_method_names;

    for (CXXMethodDecl *const method_decl : decl->methods())
    {
        if (method_decl->getAccess() != AS_public)
            continue; // skip protected and private members

        if (isa<CXXConversionDecl>(method_decl))
            ; // do nothing
        else if (isa<CXXDestructorDecl>(method_decl))
            ; // do nothing
        else if (isa<CXXConstructorDecl>(method_decl))
        {
            GenerateCXXConstructor(
                *stream, decl, cast<CXXConstructorDecl>(method_decl));
        }
        else if (method_decl->isOverloadedOperator())
            ; // TODO: Wrap overloaded operators.
        else if (method_decl->isStatic())
        {
            // TODO: Missing the dot.
            if (GenerateFunction(*stream, decl, method_decl))
                overloaded_method_names.insert(method_decl->getNameAsString());
        }
        else
        {
            // TODO: Missing the dot.
            GenerateFunction(*stream, decl, method_decl);
        }
    }

    // Static methods MUST be declared after overloads are defined.
    for (const std::string &method_name : overloaded_method_names)
        *stream << ".staticmethod(\"" << method_name << "\")\n";

    // Fields
    for (FieldDecl *const field_decl : decl->fields())
    {
        if (field_decl->getAccess() != AS_public)
            continue; // skip protected and private fields

        GenerateField(*stream, decl, field_decl);
    }

    for (Decl *const child_decl : decl->decls())
    {
        if (isa<VarDecl>(child_decl))
            GenerateStaticField(*stream, decl, cast<VarDecl>(child_decl));
    }

    *stream << ";\n";

    return true;
}

bool chimera::Visitor::GenerateCXXConstructor(
    chimera::Stream &stream,
    CXXRecordDecl *class_decl,
    CXXConstructorDecl *decl)
{
    decl = decl->getCanonicalDecl();

    if (decl->isDeleted())
        return false;

    std::vector<std::string> argument_types;

    for (ParmVarDecl *param_decl : decl->params())
        argument_types.push_back(param_decl->getType().getAsString(printing_policy_));

    stream << ".def(::boost::python::init<"
           << join(argument_types, ", ")
           << ">())\n";
    return true;
}

bool chimera::Visitor::GenerateFunction(
    chimera::Stream &stream,
    CXXRecordDecl *class_decl, FunctionDecl *decl)
{
    decl = decl->getCanonicalDecl();

    if (decl->isDeleted())
        return false;

    // Get configuration, and use any overrides if they exist.
    if (config_->DumpOverride(decl, stream))
        return true;

    const YAML::Node &node = config_->GetDeclaration(decl);
    if (node.IsNull())
        return false; // Explicitly suppressed.

    // Extract the pointer type of this function declaration.
    QualType pointer_type;
    if (class_decl && !cast<CXXMethodDecl>(decl)->isStatic())
    {
        pointer_type = context_->getMemberPointerType(
            decl->getType(), class_decl->getTypeForDecl());
    }
    else
    {
        pointer_type = context_->getPointerType(decl->getType());
    }
    pointer_type = pointer_type.getCanonicalType();

    // Extract the return type of this function declaration.
    const QualType return_qual_type = decl->getReturnType();
    const Type *return_type = return_qual_type.getTypePtr();

    // First, check if a return_value_policy was specified for this function.
    std::string return_value_policy
        = node["return_value_policy"].as<std::string>("");

    // Next, check if a return_value_policy is defined on the return type.
    if (return_value_policy.empty())
    {
        const YAML::Node &type_node = config_->GetType(return_qual_type);
        return_value_policy
            = type_node["return_value_policy"].as<std::string>("");
    }

    // Finally, try the default return_value_policy. This is only acceptable if
    // the output is copy constructable.
    if (return_value_policy.empty())
    {
        if (return_type->isReferenceType())
        {
            std::cerr
                << "Warning: Skipped method '"
                << pointer_type.getAsString(printing_policy_)
                << "' because it returns a reference and no"
                   " 'return_value_policy' was specified.\n";
            return false;
        }
        else if (return_type->isPointerType())
        {
            std::cerr
                << "Warning: Skipped method '"
                << pointer_type.getAsString(printing_policy_)
                << "' because it returns a pointer and no"
                   " 'return_value_policy' was specified.\n";
            return false;
        }
        // TODO: Check if return_type is non-copyable.
    }

    // If we are inside a class declaration, this is being called within a
    // builder pattern and will start with '.' since it is a member function.
    if (class_decl)
        stream << ".";

    // Create the actual function declaration here using its name and its
    // full pointer reference.
    stream << "def(\"" << decl->getNameAsString() << "\""
           << ", static_cast<" << pointer_type.getAsString(printing_policy_) << ">(&"
           << decl->getQualifiedNameAsString() << ")";

    // If a return value policy was specified, insert it after the function.
    if (!return_value_policy.empty())
    {
        stream << ", ::boost::python::return_value_policy<"
               << return_value_policy << " >";
    }

    // Construct a list of the arguments that are provided to this function,
    // and define named arguments for them based on their c++ names.
    const auto params = GetParameterNames(decl);
    if (!params.empty())
    {
        // TODO: Suppress any default parameters that occur after the first
        // non-default to default transition. This can only occur if evaluating
        // the default value of one or more parameters failed.

        // TODO: Assign names to unnamed arguments.

        std::vector<std::string> python_args;
        for (const auto &param : params)
        {
            std::stringstream python_arg;
            python_arg << "::boost::python::arg(\"" << param.first << "\")";

            if (!param.second.empty())
                python_arg << " = " << param.second;

            python_args.push_back(python_arg.str());
        }

        stream << ", (" << join(python_args, ", ") << ")";
    }

    stream << ")\n";
    return true;
}

bool chimera::Visitor::GenerateField(
    chimera::Stream &stream,
    clang::CXXRecordDecl *class_decl,
    clang::FieldDecl *decl)
{
    if (decl->getType().isConstQualified())
        stream << ".def_readonly";
    else
        stream << ".def_readwrite";

    // TODO: Check if a copy constructor is defined for this type.

    stream << "(\"" << decl->getNameAsString() << "\","
           << " &" << decl->getQualifiedNameAsString() << ")\n";
    return true;
}

bool chimera::Visitor::GenerateStaticField(
    chimera::Stream &stream,
    clang::CXXRecordDecl *class_decl,
    clang::VarDecl *decl)
{
    if (decl->getAccess() != AS_public)
        return false;
    else if (!decl->isStaticDataMember())
        return false;

    stream << ".add_static_property(\"" << decl->getNameAsString() << "\", "
           << "[]() { return " << decl->getQualifiedNameAsString() << "; }";

    if (!decl->getType().isConstQualified())
    {
        stream << "[](" << decl->getType().getAsString(printing_policy_) << " value) { "
               << decl->getQualifiedNameAsString() << " = value; }";
    }

    stream << ")\n";

    return true;
}

bool chimera::Visitor::GenerateClassTemplate(clang::ClassTemplateDecl *decl)
{
    if (decl != decl->getCanonicalDecl())
        return false;

    for (ClassTemplateSpecializationDecl *spec_decl : decl->specializations())
    {
        if (spec_decl->getSpecializationKind() == TSK_Undeclared)
            continue;

        CXXRecordDecl *decl = spec_decl->getTypeForDecl()->getAsCXXRecordDecl();
        GenerateCXXRecord(decl);
    }

    return true;
}

bool chimera::Visitor::GenerateEnum(clang::EnumDecl *decl)
{
    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    *stream << "::boost::python::enum_<"
            << decl->getQualifiedNameAsString()
            << ">(\"" << decl->getNameAsString() << "\")\n";

    for (EnumConstantDecl *constant_decl : decl->enumerators())
    {
        *stream << ".value(\"" << constant_decl->getNameAsString() << "\", "
                << constant_decl->getQualifiedNameAsString() << ")\n";
    }

    *stream << ";\n";

    return true;
}

bool chimera::Visitor::GenerateGlobalVar(clang::VarDecl *decl)
{
    if (!decl->isFileVarDecl())
        return false;
    else if (!decl->isThisDeclarationADefinition())
        return false;

    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    *stream << "::boost::python::scope().attr(\"" << decl->getNameAsString()
            << "\") = " << decl->getQualifiedNameAsString() << ";\n";
    return true;
}

bool chimera::Visitor::GenerateGlobalFunction(clang::FunctionDecl *decl)
{
    if (isa<clang::CXXMethodDecl>(decl))
        return false;
    else if (decl->isOverloadedOperator())
        return false; // TODO: Wrap overloaded operators.

    auto stream = config_->GetOutputFile(decl);
    if (!stream)
        return false;

    return GenerateFunction(*stream, nullptr, decl);
}

std::vector<std::string> chimera::Visitor::GetBaseClassNames(
    CXXRecordDecl *decl) const
{
    std::vector<std::string> base_names;

    for (CXXBaseSpecifier &base_decl : decl->bases())
    {
        if (base_decl.getAccessSpecifier() != AS_public)
            continue;

        // TODO: Filter out transitive base classes.

        CXXRecordDecl *const base_record_decl
          = base_decl.getType()->getAsCXXRecordDecl();
        const QualType base_record_type
          = base_record_decl->getTypeForDecl()->getCanonicalTypeInternal();

        base_names.push_back(base_record_type.getAsString(printing_policy_));
    }

    return base_names;
}

std::vector<std::pair<std::string, std::string>>
    chimera::Visitor::GetParameterNames(clang::FunctionDecl *decl) const
{
    std::vector<std::pair<std::string, std::string>> params;

    for (ParmVarDecl *param_decl : decl->params())
    {
        const std::string param_name = param_decl->getNameAsString();
        const Type *param_type = param_decl->getType().getTypePtr();
        std::string param_value;

        if (param_decl->hasDefaultArg()
            && !param_decl->hasUninstantiatedDefaultArg()
            && !param_decl->hasUnparsedDefaultArg())
        {
            Expr *default_expr = param_decl->getDefaultArg();
            assert(default_expr);

            Expr::EvalResult result;
            bool success;

            if (param_type->isReferenceType())
                success = default_expr->EvaluateAsLValue(result, *context_);
            else
                success = default_expr->EvaluateAsRValue(result, *context_);

            if (success)
            {
                param_value = result.Val.getAsString(
                    *context_, param_decl->getType());
            }
            else if (default_expr->hasNonTrivialCall(*context_))
            {
                // TODO: How do we print the decl with argument + return types?
                std::cerr
                  << "Warning: Unable to evaluate non-trivial call in default"
                     " value for parameter"
                  << " '" << param_name << "' of method"
                  << " '" << decl->getQualifiedNameAsString() << "'.\n";
            }
            else
            {
                // TODO: How do we print the decl with argument + return types?
                std::cerr
                  << "Warning: Failed to evaluate default value for parameter"
                  << " '" << param_name << "' of method"
                  << " '" << decl->getQualifiedNameAsString() << "'.\n";
            }
        }

        params.push_back(std::make_pair(param_name, param_value));
    }

    return params;
}

bool chimera::Visitor::IsEnclosed(Decl *decl) const
{
    // Filter over the namespaces and only traverse ones that are enclosed
    // by one of the configuration namespaces.
    for (const auto &it : config_->GetNamespaces())
    {
        if (decl->getDeclContext() && it->Encloses(decl->getDeclContext()))
        {
            return true;
        }
    }
    return false;
}
<|endoftext|>