summaryrefslogblamecommitdiffstats
path: root/src/Plugin.cpp
blob: 4ef1240264418b2f37814fc54c5122d0af371469 (plain) (tree)
1
2
3
4
5
6
7
8
9
10





                          



                        
                    
 

               
                   




                                                             
                                                 








                            
                                                
                                     
                                  
                                                                       


                                                                                   

                                                                                                   






                                                                                                                                    
                                           


                                     










                                         

 

                           

                                                  
                                                          






                                          




                                                   






















































                                                                                        

                                          
                                                                                      




                                            
                                                                                



                                  



                                                                    


                                                           

 

                                                                     



                                         

                              


         

                                                            
                                        
                                                               




                                                               
                                                


                         



                                                 
                                                        




                                                         
                                                


                         
#include "Plugin.hpp"

#include <vector>

#include <easylogging++.h>
#include <sol.hpp>
#include <optick.h>

#include "GameState.hpp"
#include "Game.hpp"
#include "Event.hpp"


struct Plugin {
	int errors;
	const std::string name;
	const std::string displayName;
	const std::function<void()> onLoad;
	const std::function<void()> onUnload;
	const std::function<void(std::string)> onChangeState;
	const std::function<void(double)> onTick;
};


std::vector<Plugin> plugins;
sol::state lua;


namespace PluginApi {

	void RegisterPlugin(sol::table plugin) {
		Plugin nativePlugin {
				0,
				plugin["name"].get_or<std::string>(""),
				plugin["displayName"].get_or<std::string>(""),
				plugin["onLoad"].get_or(std::function<void()>()),
				plugin["onUnload"].get_or(std::function<void()>()),
				plugin["onChangeState"].get_or(std::function<void(std::string)>()),
				plugin["onTick"].get_or(std::function<void(double)>())
		};
		plugins.push_back(nativePlugin);
		nativePlugin.onLoad();
		
		LOG(INFO) << "Loaded plugin " << (!nativePlugin.displayName.empty() ? nativePlugin.displayName : nativePlugin.name);
	}

	void LogWarning(std::string text) {
		LOG(WARNING) << text;
	}

	void LogInfo(std::string text) {
		LOG(INFO) << text;
	}

	void LogError(std::string text) {
		LOG(ERROR) << text;
	}

	GameState *GetGameState() {
		return ::GetGameState();
	}
}

void PluginSystem::Init() {
	OPTICK_EVENT();
	LOG(INFO) << "Initializing plugin system";
	for (Plugin &plugin : plugins) {
		if (plugin.onUnload && plugin.errors < 10)
			plugin.onUnload();
	}

	plugins.clear();
	lua = sol::state();
	lua.open_libraries();

	lua.new_usertype<Entity>("Entity",
		"pos", &Entity::pos);

	lua.new_usertype<GameState>("GameState",
		"GetPlayer", &GameState::GetPlayer,
		"GetWorld", &GameState::GetWorld,
		"GetTimeStatus", &GameState::GetTimeStatus,
		"GetGameStatus", &GameState::GetGameStatus,
		"GetPlayerStatus", &GameState::GetPlayerStatus,
		"GetSelectionStatus", &GameState::GetSelectionStatus,
		"GetInventory", &GameState::GetInventory);

	lua.new_usertype<TimeStatus>("TimeStatus",
		"interpolatedTimeOfDay", &TimeStatus::interpolatedTimeOfDay,
		"worldAge", &TimeStatus::worldAge,
		"timeOfDay", &TimeStatus::timeOfDay,
		"doDaylightCycle", &TimeStatus::doDaylightCycle);

	lua.new_usertype<GameStatus>("GameStatus",
		"levelType", &GameStatus::levelType,
		"spawnPosition", &GameStatus::spawnPosition,
		"gamemode", &GameStatus::gamemode,
		"dimension", &GameStatus::dimension,
		"difficulty", &GameStatus::difficulty,
		"maxPlayers", &GameStatus::maxPlayers,
		"isGameStarted", &GameStatus::isGameStarted,
		"reducedDebugInfo", &GameStatus::reducedDebugInfo);

	lua.new_usertype<SelectionStatus>("SelectionStatus",
		"raycastHit", &SelectionStatus::raycastHit,
		"selectedBlock", &SelectionStatus::selectedBlock,
		"distanceToSelectedBlock", &SelectionStatus::distanceToSelectedBlock,
		"isBlockSelected", &SelectionStatus::isBlockSelected);

	lua.new_usertype<PlayerStatus>("PlayerStatus",
		"uid", &PlayerStatus::uid,
		"name", &PlayerStatus::name,
		"flyingSpeed", &PlayerStatus::flyingSpeed,
		"fovModifier", &PlayerStatus::fovModifier,
		"health", &PlayerStatus::health,
		"eid", &PlayerStatus::eid,
		"invulnerable", &PlayerStatus::invulnerable,
		"flying", &PlayerStatus::flying,
		"allowFlying", &PlayerStatus::allowFlying,
		"creativeMode", &PlayerStatus::creativeMode);

	lua.new_usertype<World>("World",
		"GetEntitiesList", &World::GetEntitiesList,
		"GetEntity",&World::GetEntityPtr,
		"Raycast", &World::Raycast,
		"GetBlockId", &World::GetBlockId,
		"SetBlockId", &World::SetBlockId);

	lua.new_usertype<BlockId>("BlockId",
		"id", sol::property(
			[](BlockId & bid) { return bid.id; },
			[](BlockId & bid, unsigned short id) { bid.id = id; }),
		"state", sol::property(
			[](BlockId & bid) { return bid.state; },
			[](BlockId & bid, unsigned char state) { bid.state = state; }));

	lua.new_usertype<Vector>("Vector",
		sol::constructors<Vector(),Vector(long long, long long, long long)>(),
		"x", &Vector::x,
		"y", &Vector::y,
		"z", &Vector::z);

	lua.new_usertype<VectorF>("VectorF",
		sol::constructors<VectorF(), VectorF(double, double, double)>(),
		"x", &VectorF::x,
		"y", &VectorF::y,
		"z", &VectorF::z);

	sol::table apiTable = lua["AC"].get_or_create<sol::table>();

	apiTable["RegisterPlugin"] = PluginApi::RegisterPlugin;
	apiTable["LogWarning"] = PluginApi::LogWarning;
	apiTable["LogInfo"] = PluginApi::LogInfo;
	apiTable["LogError"] = PluginApi::LogError;
	apiTable["GetGameState"] = PluginApi::GetGameState;
}

void PluginSystem::Execute(const std::string &luaCode, bool except) {
	OPTICK_EVENT();
	try {
		lua.safe_script(luaCode);
	} catch (sol::error &e) {
		LOG(ERROR) << e.what();
		if (except)
			throw;
	}
}

void PluginSystem::CallOnChangeState(std::string newState) {
	OPTICK_EVENT();
	for (Plugin &plugin : plugins) {
		if (plugin.onChangeState && plugin.errors < 10)
			try {
				plugin.onChangeState(newState);
			}
			catch (sol::error &e) {
				LOG(ERROR) << e.what();
				plugin.errors++;
			}
	}
}

void PluginSystem::CallOnTick(double deltaTime) {
	OPTICK_EVENT();
	for (Plugin& plugin : plugins) {
		if (plugin.onTick && plugin.errors < 10)
			try {
				plugin.onTick(deltaTime);
			}
			catch (sol::error &e) {
				LOG(ERROR) << e.what();
				plugin.errors++;
			}
	}
}